Skip to content
A simple Javascript boilerplate setup for plotting 2d stuff on HTML canvas (my default setup).
JavaScript CSS HTML Shell Ruby
Branch: master
Clone or download
ikaroskappler
Latest commit f1eb15f Dec 11, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
demos Updated some demos and the readme. Dec 11, 2019
dist Updated some demos and the readme. Dec 11, 2019
docs_jekyll Fixed a missing image in the readme. Dec 8, 2019
lib Added the drawables-to-svg demo helper. Fixed a click area issue when… Nov 13, 2019
screenshots Updated some demos and the readme. Dec 11, 2019
src Hotfixed a bug in the new line-point-distance demo (still a better so… Dec 11, 2019
tests Fixed an issue in Touchy.js: touch-move did not call e.preventDefault… Apr 3, 2019
.env.example Added an automatic uploader script. Nov 13, 2019
.gitignore Extended the line-point-distance demo (unfinished). Extended the publ… Dec 9, 2019
README.md Hotfixed a bug in the new line-point-distance demo (still a better so… Dec 11, 2019
beziergsap-animation.mov Added relative positioned zooming. Dec 4, 2019
build.sh Added a build script. Added a new main screenshot. Nov 18, 2019
changelog.md Updated some demos and the readme. Dec 11, 2019
circular-vertex-animator-with-distance-graph.mp4 Added the drawables-to-svg demo helper. Fixed a click area issue when… Nov 13, 2019
circular-vertex-animator-with-distance-graph.ogv Added the drawables-to-svg demo helper. Fixed a click area issue when… Nov 13, 2019
example-image.png Minor changes to the image demo (replaced non-working SVG by PNG). Feb 2, 2019
example-image.svg Added image rendering. Jan 30, 2019
howto-generate-docs.txt Added JSDoc and jsdoc inline tags for some basic classes. Re-generate… Mar 20, 2019
installation-notes.txt Removed the overlay-dialog from the package as it was not in use at a… Mar 28, 2019
jsdoc.config.json Merged jekyll- and jsdoc-stylesheets. Re-styled the website and docum… Apr 7, 2019
main-dist.html Added a basic tween test (using gsap). Dec 2, 2019
main-gl.html Added the Triangle test class to the PlotBoilerplate. Adapted the dem… Nov 18, 2019
main.html Added a basic tween test (using gsap). Dec 2, 2019
mkdocs.sh Merged jekyll- and jsdoc-stylesheets. Re-styled the website and docum… Apr 7, 2019
package.json Recompiled the package. Dec 8, 2019
plot-boilerplate.svg Built a basis SVG export. Dec 5, 2018
publish.sh Updated some demos and the readme. Dec 11, 2019
style.css Added default rastered background (fallback). Dec 8, 2019
upload-to-production.sh Cleaned up the uploader script. Nov 19, 2019
webpack.config.js Added the Triangle test class to the PlotBoilerplate. Adapted the dem… Nov 18, 2019

README.md

An interactive Javascript Plotting Boilerplate

For plotting visual 2D data with Javascript and canvas (in 2d-context).

This is a simple collection of useful functions I repetitively used for visualizing 2D geometries on HTML canvas. Basic features are

  • adding elements like vertices, lines, vectors, triangles, curves, polygons, ellipses, images
  • cofiguration of the canvas behavior (fullsize, interaction, raster)
  • mouse interaction (zoom, pan, drag elements)
  • keyboard interaction
  • touch interaction for dragging vertices (desktop and mobile)

Install the package via npm

   $ npm i -g npm          # Updates your npm if necessary
   $ npm i plotboilerplate # Installs the package

The HTML file

For a full example see main-dist.html:

   <canvas id="my-canvas">
      Your browser does not support the canvas tag.
   </canvas>

   <!-- Optional: a helper to display mouse/touch position -->
   <div class="info monospace">
      [<span id="cx">-</span>,<span id="cy">-</span>]
   </div>

The 'info' block is just for displaying the current mouse/touch coordinates.

The javascript

   var pb = new PlotBoilerplate( {
       canvas		: document.getElementById('my-canvas'),
       fullSize         : true
    } );

Add elements to your canvas

   // Create two points:
   //   The origin is at the visual center by default.
   var pointA = new Vertex( -100, -100 );
   var pointB = new Vertex( 100, 100 );
   pb.add( new Line(pointA,pointB) );

   // When point A is moved by the user
   //   then move point B in the opposite direction
   pointA.listeners.addDragListener( function(e) {
   	pointB.sub( e.params.dragAmount );
	pb.redraw();
   } );
   
   // and when point B is moved
   //   then move point A
   pointB.listeners.addDragListener( function(e) {
   	pointA.sub( e.params.dragAmount );
	pb.redraw();
   } );

And the simple demo is here

Simple Demo

Examples and screenshots

Current demo

See the demo

Feigenbaum bifurcation (logistic map)

Plotting the Feigenbaum bifurcation Plotting the Feigenbaum bifurcation

For a detailed description of this plot see my Feigenbaum-plot mini-project

See the demo

And here is a tiny article about it

Perpendiducular point-to-line-distance demo

Perpendiducular point-to-line distance

See the demo

Random-scripture demo

Random-scripture demo

See the demo

Vector field test

Vectorfield test

See the demo

Simple circumcircles of walking triangles animation

Circumcircle animation

See the demo

Interactive Delaunay triangulation and Voronoi diagram

Delaunay and Voronoi Voronoi Bézier Cells Voronoi Bézier Cells with scaling

See the demo

Walking triangle demo

Walking Triangles, Demo A Walking Triangles, Demo B Walking Triangles, Demo C

See the demo

Simple tweening animation using the GSAP library

Simple Tweening Animation

See the demo

Perpendiculars of a Bézier path

Perpendiculars of a Bézier path

See the demo

Tracing a cubic Bézier spline (finding the tangent values for each vertex)

Tracing a cubic Bézier spline

See the demo

Initialization parameters

Name Type Default Description
canvas HTMLCamvasElement null The canvas (must not be null).
`fullsize boolean true If true, then the canvas will always claim tha max available screen size.
fitToParent boolean true If true, then the canvas will alway claim the max available parent container size.
scaleX number 1.0 The initial horizontal zoom. Default is 1.0.
scaleY number 1.0 The initial vertical zoom. Default is 1.0.
offsetX number 0.0 The initial offset. Default is 0.0. Note that autoAdjustOffset=true overrides these values.
offsetY number 0.0 The initial offset. Default is 0.0. Note that autoAdjustOffset=true overrides these values.
drawGrid boolean true Specifies if the raster should be drawn.
rasterGrid boolean true If set to true the background grid will be drawn rastered.
rasterAdjustFactor number 2.0 The exponential limit for wrapping down the grid. (2.0 means: halve the grid each 2.0*n zoom step).
drawOrigin boolean false Draw a crosshair at (0,0).
autoAdjustOffset boolean true When set to true then the origin of the XY plane will be re-adjusted automatically (see the params offsetAdjust{X,Y}Percent for more).
offsetAdjustXPercent number 50 The x- and y- fallback position for the origin after resizing the canvas.
offsetAdjustYPercent number 50 The x- and y- fallback position for the origin after resizing the canvas.
defaultCanvasWidth number 1024 The canvas size fallback if no automatic resizing is switched on.
defaultCanvasHeight number 768 The canvas size fallback if no automatic resizing is switched on.
canvasWidthFactor number 1.0 Two scaling factors (width and height) upon the canvas size. In combination with cssScale{X,Y} this can be used to obtain sub pixel resolutions for retina displays.
canvasHeightFactor number 1.0 Two scaling factors (width and height) upon the canvas size. In combination with cssScale{X,Y} this can be used to obtain sub pixel resolutions for retina displays.
cssScaleX number 1.0 Visually resize the canvas using CSS transforms (scale x).
cssScaleY number 1.0 Visually resize the canvas using CSS transforms (scale y).
cssUniformScale boolean 1.0 If set to true only cssScaleX applies for both dimensions.
backgroundColor string #ffffff A background color (CSS string) for the canvas.
redrawOnResize boolean true Switch auto-redrawing on resize on/off (some applications might want to prevent automatic redrawing to avoid data loss from the drae buffer).
drawBezierHandleLines boolean true Indicates if Bézier curve handle points should be drawn.
drawBezierHandlePoints boolean true Indicates if Bézier curve handle points should be drawn.
preClear function null A callback function that will be triggered just before the draw function clears the canvas (before anything else was drawn).
preDraw function null A callback function that will be triggered just before the draw function starts.
postDraw function null A callback function that will be triggered right after the drawing process finished.
enableMouse boolean true Indicates if the application should handle touch events for you.
enableTouch boolean true Indicates if the application should handle touch events for you.
enableKeys boolean true Indicates if the application should handle key events for you.
enableMouseWheel boolean true Indicates if the application should handle mouse wheelevents for you.
enableGL boolean false [Experimental] Indicates if the application should use the experimental WebGL features.
 var pb = new PlotBoilerplate( {
  // HTMLElement
  //   Your canvas element in the DOM (required).
  canvas			: document.getElementById('my-canvas'),

  // boolean
  //   If set to true the canvas will gain full window size.
  fullSize              	: true,

  // boolean
  //   If set to true the canvas will gain the size of its parent
  //   container.
  // @overrides fullSize
  fitToParent           	: true,

  // float
  //   The initial zoom. Default is 1.0.
  scaleX                	: 1.0,
  scaleY                	: 1.0,

  // float
  //   The initial offset. Default is 0.0. Note that autoAdjustOffset=true overrides these values.
  offsetX                	: 0.0,
  offsetY                	: 0.0,

  // Specifies if the raster should be drawn.
  drawGrid                : true,

  // If set to true the background grid will be drawn rastered.
  rasterGrid              : true,

  // float
  //    The exponential limit for wrapping down the grid.
  //    (2.0 means: halve the grid each 2.0*n zoom step).
  rasterAdjustFactor    	: 2.0,

  // Draw a crosshair at (0,0).
  drawOrigin              : false,

  // boolean
  //   When set to true then the origin of the XY plane will
  //   be re-adjusted automatically (see the params
  //    offsetAdjust{X,Y}Percent for more).
  autoAdjustOffset      	: true,
  // float
  //   The x- and y- fallback position for the origin after
  //   resizing the canvas.
  offsetAdjustXPercent  	: 50,
  offsetAdjustYPercent  	: 50,

  // int
  //   The canvas size fallback if no automatic resizing
  //   is switched on.
  defaultCanvasWidth    	: 1024,
  defaultCanvasHeight   	: 768,

  // float
  //   Two scaling factors (width and height) upon the canvas size.
  //   In combination with cssScale{X,Y} this can be used to obtain
  //   sub pixel resolutions for retina displays.
  canvasWidthFactor     	: 1.0,
  canvasHeightFactor    	: 1.0,

  // float
  //   Visually resize the canvas using CSS transforms (scale).
  cssScaleX	       	: 1.0,
  cssScaleY	       	: 1.0,

  // boolean
  //   If set to true only cssScaleX applies for both dimensions.
  cssUniformScale         : true,

  // string
  //   A background color (CSS string) for the canvas.
  backgroundColor       	: '#ffffff',

  // boolean
  //   Switch auto-redrawing on resize on/off (some applications
  //   might want to prevent automatic redrawing to avoid data
  //   loss from the drae buffer).
  redrawOnResize        	: true,

  // boolean
  //   Indicates if Bézier curve handles should be drawn (used for
  //   editors, no required in pure visualizations).
  drawBezierHandleLines 	: true,

  // boolean
  //   Indicates if Bézier curve handle points should be drawn.
  drawBezierHandlePoints 	: true,

  // function
  //   A callback function that will be triggered just before the
  //   draw function clears the canvas (before anything else was drawn).
  preClear              	: function() { console.log('before clearing the canvas on redraw.'); },
	
  // function
  //   A callback function that will be triggered just before the
  //   draw function starts.
  preDraw               	: function() { console.log('before clearing and before drawing.'); },

  // function
  //   A callback function that will be triggered right after the
  //   drawing process finished.
  postDraw              	: function() { console.log('after drawing.'); },

  // boolean
  //   Indicates if the application should handle mouse events for you.

  enableMouse           	: true,
  // boolean
  //   Indicates if the application should handle touch events for you.
  enableTouch           	: true,

  // boolean
  //   Indicates if the application should handle key events for you.
  enableKeys            	: true,

  // boolean
  //   Indicates if the application should handle mouse wheelevents for you.
  enableMouseWheel            : true,

  // boolean
  //   Indicates if the application should use the experimental WebGL features.
  enableGL                    : false
 } );

Events

The Vertex class has basic drag event support:

 var vert = new Vertex(100,100);
 vert.listeners.addDragListener( function(e) {
   // e is of type Event.
   // You are encouraged to use the values in the object e.params
   console.log( 'vertex was dragged by: ',
   	        'x='+e.params.dragAmount.x,
	        'y='+e.params.dragAmount.y );
 } );

The e.params object

 {
  // The canvas that fired the event.
  element : [HTMLElement],
    
  // The event name.
  //   Default: 'drag'
  name : string,

  // The current drag position.
  pos : { x : Number, y : Number },

  // A mouse button indicator (if mouse event).
  //    0=left, 1=middle, 2=right
  button : Number,

  // A flag indicating if event comes from left mouse button.
  leftButton : boolean,

  // A flag indicating if event comes from middle mouse button.
  middleButton : boolean,

  // A flag indicating if event comes from right mouse button.
  rightButton : boolean,

  // A mouse-down-position: position where the dragging
  //   started. This will not change during one drag process.
  mouseDownPos : { x : Number, y : Number },

  // The most recent drag position (position before
  //   current drag step).
  draggedFrom : { x : Number, y : Number },

  // True if this is a drag event (nothing else possible at the moment).
  wasDragged : boolean,

  // The x-y-amount of the current drag step.
  //   This is the difference between the recent drag step
  //   and the actual drag position.
  dragAmount : { x : Number, y : Number }
 }

Usage

  • [SHIFT] + [Click] : Select/Deselect vertex
  • [Y] + [Click]: Toggle Bézier auto-adjustment for clicked bézier path point
  • [ALT or CTRL] + [Mousedown] + [Drag] : Pan the area
  • [Mousewheel-up] : Zoom in
  • [Mousewheel-down] : Zoom out

Re-compile the package

The package is compiled with webpack. See the webpack.config.js file.

Install webpack

This will install the npm-webpack package with the required dependencies for you from the package.json file.

 $ npm install

Run webpack

This will generate the ./dist/plotboilerplate.min.js file for you from the sources code files in ./src/*.

 $ npm run webpack

Todos

  • Use a sorted map in the line-point-distance demo.
  • The experimental WebGL support requires Color objects instead of color strings. Otherwise each color string will be parse on each roundtrip which is a nightmare for the performance.
  • The Color.parse(string) function does only recognize HEX, RGB and RGBA strings. HSL is still missing. Required?
  • Include Touchy.js as a package dependency.
  • Include FileSaver.js as a package dependency.
  • Measure the canvas' border when applying fitToParent! Currently a 1px border is expected.
  • Make strokes configurable (color, width, style).
  • Make Bézier Curves dividable (by double click?).
  • Implement snap-to-grid.
  • Make ellipses rotatable.
  • Write better viewport/viewbox export. Some viewers do not understand the current format. Refactor BoundingBox2 for this?
  • The PlotBoilerplate.viewport() function already returns a bounding box (min:{Vertex},max:{Vertex}).
  • Add arcs?
  • Add image flipping.
  • Add Images to the SVGBuiler.
  • Move the helper function PlotBoilerplate.utils.buildArrowHead to the Vector class. It belongs there.
  • Add image/svg support (adding SVG images).
  • Add a proper webpack entry point file (like index.js or entry.js?).
  • Add typescript and define an interface for drawables (Drawable.ts?).
  • Add a vertex attribute: visible. (to hide vertices).
  • Add control button: reset zoom.
  • Add control button: reset to origin.
  • [Partially done] Add control button: set to retina resolution (size factors and css scale).
  • Add a demo that draws a proper mathematical xy-grid.
  • Switching browser tabs back and forth sometimes locks the Ctrl-Key. Check that.
  • [NPM/Bash] Add a pre-publish check if there are unstaged changes.
  • [Readme] Add params as table.
  • The intersection points in the line-point-distance demo are draggable. Why?
  • Move the helper function triangle.pointIsInTriangle()...pointIsInTriangle() should be in a utils wrapper somewhere.

Todos for future Version 2 (not backwards compatible)

  • Change the Vector.inverse() function to reverse (or something). Currently this is not what the inverse of a vector should be.
  • Change the bezier point path order from [start,end,startContro,endControl] to [start,startControl,endControl,end].

Browsers support

IE / Edge
IE / Edge
Firefox
Firefox
Chrome
Chrome
iOS Safari
iOS Safari
IE11 & Edge latest latest latest

Used Libraries

Known bugs

  • Vertex rotation is faulty (angle=0 is wrong somehow, see the polygon).
  • BezierPath counstructor (from an older implementation) fails. This needs to be refactored.
  • SVG resizing does not work in Firefox (aspect ratio is always kept, even if clip box changes). Please use PNGs until this is fixed.
  • Currently no more known. Please report bugs.
You can’t perform that action at this time.