e2d.js
An es2015/es5 declarative canvas renderer.
Introduction
Most canvas libraries abstract away different aspect of canvas to make you faster. When using this library, there isn't much abstraction. In fact, the API mirrors the canvas2d API in a way makes coding canvas fun! Much like react uses a render function to make changes to the DOM in an abstract way, so does e2d to the canvas context.
Getting Started
With react.js, the developer calls React.render once to start up the application. Since e2d does not work with the DOM, there are no bindings internally to have a meaningful event lifecycle. This means that e2d.render
must be called every frame. Take the following "Hello World" example:
let canvas = document;canvaswidth = 800;canvasheight = 600; //get the canvas contextlet ctx = canvas; //add the canvas to the domdocumentbody; //for commonjs, browserify, webpacklet e2d = ; //use this if the application requires user input on the canvase2d; //requestAnimationFrame loop will call this function once per frame//it is not necessary to use this convenience function provided by e2de2d;
There is also a babel plugin for e2dx
elements so that developing on canvas can be more like using SVG in javascript. It's located here and looks like this:
//always call this ONCE to obtain mouse, activeRegion, and keyboard supporte2d; //raf will call the provided function every framee2d;
Instruction variables
e2d
introduces "Instruction variables" that represent more complex canvas instructions. They are similar to virtual dom elements in react.
For example, all canvas instructions can be variables and stored for later use. This speeds up execution time and reduces memory usage.
//create a fill command that always fills redlet fillRed = e2d; //create a 6 sided polygon with radius 10 at [0,0]let hexagonShape = e2d; //e2d.path will wrap the instructions passed to it with beginPath and closePathlet hexagonPath = e2d; //combine the path and fill instructions in an arraylet redHexagon = hexagonPath fillRed ;
Mix and match different canvas commands to make code more expressive and easier to read. For example, using the redHexagon
variable in the above example to get started:
//create a canvas first...e2d
Performance
The goal of e2d is to be fast. It has gone under numerous refactors to increase the speed of each canvas property. On top of engine performance, there is an additional benefit to using instruction variables
. Using these will result in less user-defined function calls. With instruction storage, and less user defined function calls, the majority of the application view layer will sit around in memory waiting to be parsed every frame.
Most importantly, creating an entire render tree every frame has a relatively minimal performance impact.
Drawing Collections
Collections are harder to optimize, so try to make data flow into instruction variables
. See the following example:
;let particles = ;forlet i = 0; i < 100; i++ particles; //fillArc has default function parameters [x=0, y=0, beginRadians=0, endRadians=Math.PI*2]let particleShape = ; //only the radius is provided //latere2d;
Getting started
I highly recommend using webpack
or browserify
in node.js
to modularize your code, but the fastest way to get started is to use the e2d.compat.min.js
file in the /dist/
folder, or e2d.min.js
for native es2015
support.
Import using script method
webpack-dev-server
Please see webpack-dev-server for all your web development server needs.
API
e2d.render
This is the command that actually draws to the canvas. Create some drawing instructions and pass them to this function.
; //create a draw commandlet helloWorld = e2d; //create a canvaslet canvas = doucment;canvaswidth = 400;canvasheight = 400;documentbody; let ctx = canvas; e2d;
extend.js
For use with custom instructions.
; let extensions = //first argument is props, second is the canvas context. { ctx; ctx; ctx; ctx; //always make sure to restore canvas context state to prevent render side-effects ctx; } //to use it, pass an Instruction object to e2d.rendere2d;
Render Commands
The following render commands are provided to you in this library.
arc.js
Arcs have 5 forms, and correspond to the documentation here at mdn:
; let fastestArc = e2d; //radius 1 and x, y is 0, 0let justRadius = e2d; //radius is set, x, y is 0let radiusWithXY = e2d; //radius is set, x, y is [x], [y] //to specify the start and end angle, use the startAngle and endAngle parameterslet radiusWithXYandAngles = e2d; //to specify anticlockwise motion, use the anticlockwise parameter like thislet arcAntiClockwise = e2d;
arcTo.js
For information on how the arcTo
function works, see mdn.
let arcToInstruction = e2d; //don't forget to wrap the arcTo function in the path functionlet pathInstruction = e2d;
beginPath.js
It's possible to control when a path begins manually by using the beginPath
function.
let beginPathOperation = e2d;
bezierCurveTo.js
See mdn for information on how to use Bezier curves.
//cp1 and cp2 are control points and the curve ends at [x, y]let myCurve = e2d;
clearRect.js
To see how clearRect works, see mdn. The clearRect
function has two forms.
//to specify a rectangle at [0,0] use the clearRect shorthandlet widthAndHeight = e2d; //otherwise, specify x and ylet sizeAndPosition = e2d;
clip.js
This provides a clipping region for child instructions.
In order to draw a clipped image, for instance, use the clip
function with a path. For more information on clipping, please visit mdn.
Please note that the path cannot be wrapped in the e2d.path()
function because clip
will automatically close the path provided.
//create a hexigon with radius 200 and map it to a set of moveTo and lineTo instructionslet region = e2d; //this results in a polygonal cliped drawImage commandlet clippedImage = e2dclip region //must be the first argument //center the image at [0,0] to see it e2d;
imageSmoothingEnabled.js
This function is wrapper function that sets imageSmoothingEnabled for it's children. (default is true)
For more information on how imageSmoothingEnabled
works, please visit mdn.
let noSmooth = e2d;
drawImage.js
This function draws an image to the canvas when rendered.
See mdn for more information on how to use drawImage.
Note to chrome developers, it's faster to use a image pattern and fill a rectangle using a fillStyle
or imagePattern
.
//one paramenter means draw the image at 0, 0 with img.width and img.height as the width/height parameterslet imgCommand = e2d; let imgCommandPosition = e2d; //draw image at x, y, img.width, img.height let imgCommandSize = e2d; //specify the size of the image //or draw the image from a source within the image (this is hard to optimize for the browser and may be slow)let imgSourceSize = e2d;
ellipse.js
This will add an ellipse to the current path. This method is "pseudo-polyfilled" and supported for all browsers. For more information on this method please visit mdn. There are three forms for the ellipse function.
Please see mdn for more information on this experimental technology.
let example = e2d; //from 0, 0let example2 = e2d; // from x, ylet example3 = e2d;
fillArc.js
This method was added for convenience. It makes the API a bit more consistent and takes the same parameters as the arc
function and works exactly like fillRect
.
; let fastestArc = e2d; //radius 1 and x, y is 0, 0let justRadius = e2d; //radius is set, x, y is 0let radiusWithXY = e2d; //radius is set, x, y is [x], [y] //to specify the start and end angle, use the startAngle and endAngle parameterslet radiusWithXYandAngles = e2d; //to specify anticlockwise motion, use the anticlockwise parameter like thislet arcAntiClockwise = e2d;
fillRect.js
To see how fillRect works, see mdn. The fillRect
function has two forms.
//to specify a rectangle at [0,0] use the fillRect shorthandlet widthAndHeight = e2d; //otherwise, specify x and ylet sizeAndPosition = e2d;
fillStyle.js
This function will "set" the fillStyle
property using the first argument as the value for the property. To see how fillStyle
works visit mdn.
//fill a red circlelet redCircle = e2d;
Nested fill styles can occur (and stack as a result):
let example = e2d;
strokeStyle.js
This function will "set" the strokeStyle
property using the first argument as the value for the property. To see how strokeStyle
works visit mdn.
//fill a red circlelet redCircle = e2d;
Nested stroke styles can occur (and stack as a result):
let example = e2d;
globalCompositeOperation.js
For change global composite operations, use globalCompositeOperation()
.
See mdn: globalCompositeOperation to learn how to use them.
let operation = e2d;
globalAlpha.js
The globalAlpha
function will apply and set the globalAlpha
relative to the parent globalAlpha
value.
let alphaCommands = e2d
hitRegion.js and hitRect.js
The hitRect
and hitRegion
functions will apply a hitRegion
to the canvas.
Hit regions are complicated, because they are relative to the current state of the canvas context.
let hexagon = e2d; let hexagonPath = e2d; e2d;e2d;
To make a square use hitRect(id, x, y, width, height)
or hitRect(id, width, height)
.
invertMatrix.js
This function will return an inverse matrix relative to the canvas matrix provided by calculating a determinant and returning a new Array
.
This function is used internally to transform mouse points inversely to determine point in polygon detection relative to the provided shape.
let a b c d e f = e2d;
lineStyle.js
This is a composite property abstraction that contains lineWidth
and other useful properties. See mdn: lineCap, mdn: lineWidth, mdn: lineJoin, mdn: miterLimit, and mdn: setLineDash
let style = lineWidth: 1 lineCap: 'round' lineJoin: 'bevel' miterLimit: 10 lineDash: lineDashOffset: 0;
lineDashOffset
and lineDash
are abstracted to make them easier to animate.
let example = e2d;
path.js, lineTo.js and moveTo.js
The path(pathInstructions)
call wraps pathInstructions
in beginPath()
and endPath()
operations.
To see how these functions work, visit mdn for moveTo, and lineTo.
//wrap paths in e2d.path()let example = e2d;
quadraticCurveTo.js
Use this to make a quadratic curve to another point. All 4 parameters are required. To see how this function works, please visit mdn.
let curveCommand = e2d;
rotate.js, translate.js, and scale.js
Use these functions to translate/rotate/and scale the provided context.
These are the most important functions abstracted by the e2d render engine. Internally e2d uses setTransform
on the canvas and keeps track of transforms manually. This allows the developer to use transforms
like rotate
and scale
without worrying about permanently displacing a canvas context.
The rotate
function uses radians like this.
let rotatedSquare = e2d;
To translate a draw command, use the translate
function with the x
and y
parameters.
//fill a circle at [x, y] with radius 100let movedCircle = e2d;
To scale a draw command, use the `scale function. It has two forms.
//scale a rectangle to double it's sizelet doubleSized = e2d; //scale the rectangle by [x, y]let doubleSizedXOnly = e2d;
As a final example, a default drawSprite function is provided here.
//standard sprite functionlet e2d; //this is how it's usede2d;
transform.js
transform([a,b,c,d,e,f], children...)
is a convenience function for advanced developers to add a transform to the current stack. For more information on how the transform
operation works, please visit mdn.
let transformOperation = e2d;
resetTransform.js and setTransform
These functions give direct access to the transformStack
values. To see how these functions work, please see mdn.
let changeCurrentTransform = e2d; //this is a shortcut for setTransform([1, 0, 0, 1, 0, 0]);let returnToIdentity = e2d;
shadowStyle.js
Much like lineStyle.js this is a compound property that can be nested.
See mdn for more details.
let shadowStyleDefinition = shadowBlur: 0 shadowColor: 'black' shadowOffsetX: 0 shadowOffsetY: 0;
Example:
let shadowCommand = e2d;
stokeArc.js
This function doesn't exist on the Canvas prototype, but was added for completeness. It draws a circular arc.
This command has four forms.
let strokeRadius = e2d; //at 0, 0let strokePosition = e2d; //full anglelet strokePortion = e2d; //specify the angleslet strokeCounterClockwise = e2d; //counterclockwise
strokeRect.js
This will outline a rectangle. Please visit mdn to see how strokeRect works. It has two forms.
let rect = e2d; //at 0, 0let rect2 = e2d;
textStyle.js, fillText.js, and strokeText
These functions help you draw text to the screen using Canvas's really poorly implemented text API. Please see mdn for more information about the font properties.
Note: the text
function is deprecated.
let style = font: 'Comic Sans MS' //probably pick another font... please? textAlign: 'center' // text alignment textBaseline: 'top' // base alignment direction: 'ltr' // ltr: left to right, rtl: right to left, and inherit ; let textCommand = e2d;
transformPoints.js
This utility function transforms a set of points relative to the specified transform matrix. It is used internally by e2d
to calculate and apply mouse regions to the canvas.
let matrix = a b c d e f;//or...let matrix = d11 d12 d21 d22 d31 d32;//lookup map//[d11, d21, d31] ---- [a, c, e]//[d12, d22, d32] ---- [b, d, f]//[ 0, 0, 1] ---- [0, 0, 1] let points = x0 y0 x1 y1 x2 y2 ... xN yN; let newPoints = ;
It returns a new array of [x, y]
points with the coordinates transformed.
createRegularPolygon.js
Creates a regular polygon shape: an array of arrays.
let radius = 10;let position = x y;let sides = 6;let hexagon = e2d; console; 10 0 5000000000000001 8660254037844386 -4999999999999998 8660254037844387 -10 12246467991473533e-15 -5000000000000004 -8660254037844384 5000000000000001 -8660254037844386
moveToLineTo.js
This is a convenience function used with the Array.prototype.map
function that maps shapes to drawable polygons.
let hexagonShape = e2d;let hexagonPath = e2d; e2d;
License
The MIT License (MIT)
Copyright (c) 2015 Joshua Tenner
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.