1. What is It ?
canvasInteractor is a JavaScript micro-library (4.7 kB compressed) used to handle pointer events for simple geometry editing together with one or more HTML canvases [1].
It implements a global event loop based on requestAnimationFrame and supports throttling of pointermove and wheel events via its custom tick event for efficient animation [2]. Cartesian coordinates for scientific and engineering applications are supported. Pan, drag and zoom operations based on an user defined origin can be done.
It was primarily implemented for use in engineering education and conference presentations.
canvasInteractor is the modern and more minimal successor of deprecated canvas-area [3].
2. How to Initialize ?
For each HTML canvas in an HTML document an instance via canvasInteractor.create is required.
<canvas id="c" width="601" height="401"></canvas>
<script src="https://cdn.jsdelivr.net/gh/goessner/canvasinteractor/canvasInteractor.js"></script>
<script>
const ctx = document.getElementById('c').getContext('2d');
const interactor = canvasInteractor.create(ctx, {x: 300, // view ...
y: 200, // ... properties
cartesian: true});
// ...
</script>
View coordinates provided by events can be controlled in the constructor by an additional view argument {x=0,y=0,scl=1,cartesian=false} beside the canvas RenderingContext2D object.
x,y… view's origin location.scl… view's scaling.cartesian… cartesian coordinate system (y-axis up).
3. Handling Events
Each canvasInteractor instance handles DOM pointer events and some custom events.
| Event | Comment |
|---|---|
pointermove |
Pointer moved. |
pointerdown |
Pointer device button pressed. |
pointerup |
Pointer device button released. |
pointerenter |
Pointer enters canvas. |
pointerleave |
Pointer leaves canvas. |
pointercancel |
DOM event forwarded. |
click |
Pointer device button pressed and released at the same location. |
wheel |
Pointer device wheel event. |
tick |
Throttled timer event. At most every 60 milliseconds. |
pan |
Pan by pointer device. Occuring only with (left) button pressed. |
drag |
Drag by pointer device. Occuring only with (left) button pressed and something was signalled as 'hit'. |
Instead of registering events via well known addEventListener, an application registers events to a canvasInteractor instance using thats on method.
// ...
interactor.on('pointermove', (e) => { /* do stuff */ })
.on('tick', (e) => { /* do other stuff */ })
.on('pan', (e) => { /* do yet other stuff */ })
.startTimer();
The pointermove event in combination with (left) pointer device button pressed also notifies the application of a drag or pan event, whether an underlying element is hit or not. See the example how to control that behavior.
Callback functions registered via on recieve an extended event object e.
| Property | Type | Comment |
|---|---|---|
type |
string |
Event type. |
x, y |
number |
Canvas coordinates with respect to upper left or lower left (cartesian) corner. |
dx, dy |
number |
Pointer location displacement from previous position. |
xusr, yusr |
number |
Coordinates with respect to user defined view origin and scaling. |
dxusr, dyusr |
number |
Pointer location displacement with respect to user defined view scaling. |
btn |
number |
Pointer device button identifier on button press (left: 1, right: 2, middle: 4). |
dbtn |
number |
Pointer device button difference on button release (left: -1, right: -2, middle: -4). |
eps |
number |
Some pixel tolerance for selecting/hitting (default = 5). |
inside |
boolean |
Is pointer currently inside canvas. |
delta |
number |
Wheel delta. |
hit |
boolean |
Needs to be set by application within pointermove event. Can be treated then within tick event. |
4. Example
The example shows how to use canvasInteractor.
Rectangles can be dragged, whereas the origin symbol can not, which induces the pan event. zooming is done by the pointer device' wheel operation.
fps: - |
|
zoom-scale: 1 |
pos: ./. | state: - |
Example Code
<!doctype html>
<html>
<head>
<title>canvasInteractor example</title>
</head>
<body>
<h1>canvasInteractor example</h1>
<canvas id="c" width="601" height="301"
style="border:1px solid black;background-color:snow"></canvas>
<script src="https://cdn.jsdelivr.net/gh/goessner/canvasinteractor/canvasInteractor.js"></script>
<script>
const ctx = document.getElementById('c').getContext('2d');
const interactor = canvasInteractor.create(ctx, {x:200,
y:100,
scl:1,
cartesian:true});
const rec1 = {x:50,y:50,b:80,h:60,fs:'orange',lw:4};
const rec2 = {x:150,y:50,b:100,h:40,fs:'cyan',lw:4};
function render() {
// ...
}
function hitRec(x,y,rec) {
return (x > rec.x && x < rec.x + rec.b && y > rec.y && y < rec.y + rec.h);
}
interactor
.on('tick', (e) => {
render();
})
.on('pointermove', (e) => {
rec1.sel = hitRec(e.xusr,e.yusr,rec1) ? true : false;
rec2.sel = hitRec(e.xusr,e.yusr,rec2) ? true : false;
e.hit = rec1.sel || rec2.sel;
})
.on('wheel', (e) => { // zooming about pointer location ...
interactor.view.x = e.x + e.dscl*(interactor.view.x - e.x);
interactor.view.y = e.y + e.dscl*(interactor.view.y - e.y);
interactor.view.scl *= e.dscl;
})
.on('pan', (e) => {
interactor.view.x += e.dx;
interactor.view.y += e.dy;
})
.on('drag', (e) => {
if (rec1.sel) { rec1.x += e.dxusr; rec1.y += e.dyusr; }
if (rec2.sel) { rec2.x += e.dxusr; rec2.y += e.dyusr; }
})
.startTimer();
</script>
</body>
</html>
5. Conclusion
canvasInteractor is a tiny JavaScript library enhancing and extending HTML canvas' event handling for performant animation and geometrical interaction.
A global event loop (singleton) based on requestAnimationFrame provides assistance with event throttling via its custom tick event. Cartesian coordinates preferred in scientific and engineering applications are supported. Pan, drag and zoom based on user defined origins can be done.
References
[1] Canvas API, https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API
[2]
D. Corbacho, Debouncing and Throttling Explained Through Examples
https://css-tricks.com/debouncing-throttling-explained-examples/
[3] S. Goessner, canvas-area,
https://github.com/goessner/canvas-area
[4] S. Goessner, canvasInteractor,
https://github.com/goessner/canvasInteractor