2D graphics canvas framework for easier interactive web graphics.
MIT License
<div style="width: 100%; height: 100%; position: absolute; top: 0px; left: 0px">
<canvas id="canvas" style="width: 100%; height: 100%;"></canvas>
</div>
var canvas = document.getElementById(canvas);
document.body.onresize = function()
{
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
Object2D
object to serve as a container for all other objects. Objects can be added to the container using the add()
method.Viewport
object is used to define how the user views the objects, the window size, zoom and rotation.Renderer
that will take care of drawing the object to the screen for us. By using the createRenderLoop()
method the renderer also creates a control object for user interaction with the viewport (dragging, zoom, rotate) using the mouse/touchscreen.var group = new Escher.Object2D();
var text = new Escher.Text();
text.position.set(0, -100);
text.text = "Hello World!"
group.add(text);
var box = new Escher.Box();
box.position.set(-100, 0);
group.add(box);
var circle = new Escher.Circle();
circle.position.set(100, 0);
circle.radius = 50;
group.add(circle);
var viewport = new Escher.Viewport(canvas);
var renderer = new Escher.Renderer(canvas);
renderer.createRenderLoop(group, viewport);
AnimationTimer
object from the library.var renderer = new Escher.Renderer(canvas);
var controls = new ViewportControls(viewport);
var timer = new AnimationTimer(function()
{
controls.update(renderer.pointer);
renderer.update(group, viewport);
});
timer.start();
EventManager
object to create and manage these events but we could also create these directly attached to the DOM elements.function preventDefault(event)
{
event.preventDefault();
return false;
}
var event = new EventManager();
event.add(canvas, 'DOMMouseScroll', preventDefault);
event.add(canvas, 'wheel', preventDefault);
event.add(canvas, 'mousewheel', preventDefault);
event.add(canvas, 'contextmenu', preventDefault);
event.create();
Viewport
is the object that indicates how the user will view the objects, the viewport can be used to change the position of the elements, zoom in and out, or even rotate the entire canvas.ignoreViewport
flag to false. This will indicate to the renderer to reset the viewport transform for that object so that the viewport does not affect it.ViewportController
(or implement new variants of this object) to allow the user control over the viewport.getValue()
method of its sockets. This method is called across the nodes connected together to retrieve the result at any point.registerSockets()
{
this.a = this.addInput("number", "a");
this.b = this.addInput("number", "b");
this.r = this.addOutput("number", "r");
this.r.getValue = () =>
{
// Add input A and input B
return this.a.getValue() + this.b.getValue();
};
}
draw(context, viewport, canvas)
and its transform(context, viewport, canvas)
methods.draw(context, viewport, canvas)
function is where the object gets draw into the screen, here you can implement your custom object as if it was drawn alone in a canvas.transform(context, viewport, canvas)
is where the object matrix gets applied to the canvas drawing context, it is assumed that the viewport transformation was pre-applied.Box
that already includes the necessary code for mouse events.var object = new Escher.Object2D();
object.draw = function(context, viewport, canvas)
{
// Create gradient
var grd = context.createLinearGradient(0, 0, 70, 0);
grd.addColorStop(0, "#FF0000");
grd.addColorStop(1, "#FFFFFF");
// Fill with gradient
context.fillStyle = grd;
context.fillRect(-70, 70, 140, 140);
};
class CustomObject extends Escher.Node
{
constructor(operation)
{
super();
this.type = "CustomObject";
this.something = 2;
}
serialize(recursive)
{
var data = super.serialize(recursive);
data.something = this.something;
return data;
}
parse(data, root)
{
super.parse(data, root);
this.something = data.something;
}
}
Escher.Object2D.register(CustomObject, "CustomObject");
serializable
attribute to false.constructor()
{
super();
this.text = new Escher.Text();
this.text.serializable = false;
this.add(this.text);
}
parse(data, root)
{
this.someObject = root.getChildByUUID(data.someObject);
}
// Called when the pointer enters the object.
onPointerEnter(pointer, viewport);
// Called when the was inside of the object and leaves the object.
onPointerLeave(pointer, viewport);
// Called while the pointer is over (inside) of the object.
onPointerOver(pointer, viewport);
// Called when the object is dragged across the screen, only works if the object has the property draggable set true.
// Delta is the movement of the pointer already translated into local object coordinates.
onPointerDrag(pointer, viewport, delta);
// Called while the pointer button is pressed.
onButtonPressed(pointer, viewport);
// Called when the pointer button is pressed down.
onButtonDown(pointer, viewport);
// Called after the pointer button gets released.
onButtonUp(pointer, viewport);
element
inside that can be used to attach custom code, by default that element pointerEvents
CSS style is set to none, disabling all the pointer events, it can be set to auto to re-enable them.var dom = new Escher.DOM(division);
dom.size.set(100, 50);
dom.origin.set(50, 25);
group.add(dom);
// Re-enable DOM pointer events
dom.element.style.pointerEvents = "auto";
// Attach a new DOM element to the DOM object
var text = document.createElement("div");
text.style.fontFamily = "Arial";
text.style.textAlign = "center";
text.innerHTML = "DOM text!";
dom.element.appendChild(text);
context.drawImage()
method to copy the content from the internal canvas to the drawing object.// Read the tiff data as arraybuffer from file
var xhr = new XMLHttpRequest();
xhr.responseType = "arraybuffer";
xhr.open("GET", "images/kofax.tif");
xhr.onload = function (e)
{
// Decode the image using tiffjs
var tiff = new Tiff({buffer: xhr.response});
var tiffCanvas = tiff.toCanvas();
if(tiffCanvas)
{
// Create the object to draw
var tiffImage = new Escher.Object2D();
tiffImage.draw = function(context, viewport, canvas)
{
// Copy the content of the tiff canvas
context.drawImage(tiffCanvas, 0, 0);
};
// Add object to the group
group.add(tiffImage);
}
};
xhr.send();
ImageData
, the context.putImageData()
method does not consider the canvas transforms. To draw ImageData
into the canvas its possible instead to create a offscreen canvas draw into that canvas and the use the context.drawImage()
method.