canvas-area
Advanced tools
Comparing version 0.4.3 to 0.4.5
@@ -11,3 +11,6 @@ /** | ||
constructor: function() { | ||
this.style.display = 'block'; | ||
this.style.overflow = 'hidden'; | ||
this._view = {x:0,y:0,scl:1}; | ||
this.ptrloc = {x:0,y:0}; | ||
this.registerEvents(); | ||
@@ -32,3 +35,3 @@ this.handleEventPtr = this.handleEvent.bind(this); | ||
get cursor() { return this.style.cursor; }, | ||
set cursor(q) { return this.style.cursor = q; }, | ||
set cursor(q) { this.style.cursor = q; }, | ||
get cartesian() { return !!eval(this.getAttribute('cartesian')); }, | ||
@@ -39,13 +42,13 @@ set cartesian(q) { this.setAttribute('cartesian',q); }, | ||
this._view.x = q.x || 0; this._view.y = q.y || 0; this._view.scl = q.scl || 1; | ||
this.notify('view', this._view); | ||
this.notify('view', Object.assign({type:'view'},this._view)); | ||
}, | ||
// viewport handling ... | ||
pan: function({dx,dy}) { this._view.x+=dx; this._view.y+=dy; this.notify('view', this._view); }, | ||
pan: function({dx,dy}) { this._view.x+=dx; this._view.y+=dy; this.notify('view', Object.assign({type:'view'},this._view)); }, | ||
zoom: function({x,y,scl}) { | ||
this._view.x = x + scl*(this._view.x - x) | ||
this._view.y = y + scl*(this._view.y - y) | ||
this._view.scl *= scl | ||
this.notify('view', this._view); | ||
this._view.x = x + scl*(this._view.x - x); | ||
this._view.y = y + scl*(this._view.y - y); | ||
this._view.scl *= scl; | ||
this.notify('view', Object.assign({type:'view'},this._view)); // MS Edge doesn't support 'spread operator' '...' | ||
}, | ||
pntToUsr: function({x,y}) { let vw = this._view; return {x:(x - vw.x)/vw.scl, y:(y - vw.y)/vw.scl} }, | ||
pntToUsr: function({x,y,btn,type}) { let vw = this._view; return {x:(x - vw.x)/vw.scl, y:(y - vw.y)/vw.scl, btn, type} }, | ||
// vecToUsr: function({x,y}) { let vw = this._view; return {x:(x - vw.x)/vw.scl, y:(y - vw.y)/vw.scl} }, | ||
@@ -69,5 +72,10 @@ resize: function({width,height}) { | ||
this.addEventListener("wheel", this, false); | ||
this.addEventListener("touchmove", this, false); | ||
this.addEventListener("touchstart", this, false); | ||
this.addEventListener("touchend", this, false); | ||
}, | ||
handleEventPtr: null, | ||
handleEvent: function(e) { | ||
if (canvasArea.defaultPreventers.includes(e.type)) | ||
e.preventDefault(); | ||
if (e.type in this) | ||
@@ -77,3 +85,3 @@ this[e.type](this.getEventData(e)); | ||
mousemove: function(e) { | ||
if (e.buttons === 1) { // left mouse button down ... | ||
if (e.btn === 1) { // left mouse button down ... | ||
if (this.resizeActive) { // resize mode active .. | ||
@@ -83,3 +91,3 @@ this.resize({width: this.width + (this.cursor[1] === 'w' ? e.dx : 0), | ||
} | ||
else if (this.notify('drag',e)) // something dragged .. ? | ||
else if (this.notify((e.type='drag'),e)) // something dragged .. ? | ||
; | ||
@@ -95,3 +103,3 @@ else | ||
if (this.cursor !== 'auto') this.cursor = 'auto'; | ||
this.notify('pointer',e); | ||
this.notify((e.type='pointer'),e); | ||
} | ||
@@ -106,3 +114,3 @@ } | ||
else | ||
this.notify('buttondown',e); | ||
this.notify((e.type='buttondown'),e); | ||
}, | ||
@@ -115,9 +123,18 @@ mouseup: function(e) { | ||
else | ||
this.notify('buttonup',e); | ||
this.notify((e.type='buttonup'),e); | ||
}, | ||
mouseenter: function(e) { this.notify('pointerenter',e) }, | ||
mouseleave: function(e) { this.notify('pointerleave',e) }, | ||
mouseenter: function(e) { this.notify((e.type='pointerenter'),e) }, | ||
mouseleave: function(e) { this.notify((e.type='pointerleave'),e) }, | ||
wheel: function(e) { this.zoom({x:e.x,y:e.y,scl:e.delta>0?9/10:10/9}) }, | ||
touchstart: function(e) { this.mousedown(e); }, | ||
touchend: function(e) { this.mouseup(e); }, | ||
touchmove: function(e) { | ||
if (this.resizeActive) { // resize mode active .. | ||
this.resize({width: this.width + (this.cursor[1] === 'w' ? e.dx : 0), | ||
height: this.height + (this.cursor[0] === 'n' ? (this.cartesian ? -e.dy : e.dy) : 0)}); | ||
} | ||
else | ||
this.pan(e); | ||
}, | ||
resizeMode: function({x,y}) { | ||
@@ -132,14 +149,23 @@ let mode = this.resizable, w = mode && this.width, h = mode && this.height, cartesian = this.cartesian; | ||
let bbox = e.target.getBoundingClientRect && e.target.getBoundingClientRect() || {left:0, top:0}, | ||
x = e.clientX - Math.floor(bbox.left), | ||
y = e.clientY - Math.floor(bbox.top); | ||
touch = e.changedTouches && e.changedTouches[0], | ||
x = (touch && touch.clientX || e.clientX) - Math.floor(bbox.left), | ||
y = (touch && touch.clientY || e.clientY) - Math.floor(bbox.top), | ||
dx = touch ? x - this.ptrloc.x : e.movementX, | ||
dy = touch ? y - this.ptrloc.y : e.movementY; | ||
this.ptrloc.x = x; | ||
this.ptrloc.y = y; | ||
return { | ||
buttons: (e.buttons !== undefined && e.type !== 'mouseup' ? e.buttons : (e.button || e.which)), | ||
type: e.type, | ||
btn: (e.buttons !== undefined && e.type !== 'mouseup' ? e.buttons : (e.button || e.which)), | ||
x: x, | ||
y: this.cartesian ? this.height - y : y, | ||
dx: e.movementX, | ||
dy: this.cartesian ? -e.movementY : e.movementY, | ||
dx: dx, | ||
dy: this.cartesian ? -dy : dy, | ||
scl: this._view.scl, | ||
delta: Math.max(-1,Math.min(1,e.deltaY||e.wheelDelta)) || 0 | ||
} | ||
}, | ||
// observer management ... | ||
// observer management ... todo: decouple from canvas-erea | ||
signals: {}, | ||
@@ -153,2 +179,3 @@ notify: function(key,val) { | ||
}, | ||
// deprecated .. use 'on(..)' instead ... | ||
observe: function(key,handler) { | ||
@@ -158,2 +185,6 @@ (this.signals[key] || (this.signals[key]=[])).push(handler); | ||
}, | ||
on: function(key,handler) { | ||
(this.signals[key] || (this.signals[key]=[])).push(handler); | ||
return this; | ||
}, | ||
remove: function(key,handler) { | ||
@@ -166,2 +197,3 @@ let idx = this.signals[key] ? this.signals[key].indexOf(handler) : -1; | ||
canvasArea.defaultPreventers = ['touchstart','touchend','touchmove']; | ||
canvasArea.register = function() { | ||
@@ -168,0 +200,0 @@ const register = () => { |
{ | ||
"name": "canvas-area", | ||
"version": "0.4.3", | ||
"version": "0.4.5", | ||
"description": "lightweight html container element as a controller parent for one or more canvas elements. It allows zoom, pan and resize interactions", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -53,3 +53,3 @@ # canvas-area | ||
|`notify(key,value)`|`key`: event type<br>`value`: event data |`undefined`| notify observers of event type `key` about event `value`| | ||
|`observe(key,handler)`|`key`: event type<br>`handler`: event handler|`undefined`| let `handler` get invoked with event type `key`. | | ||
|`on(key,handler)`|`key`: event type<br>`handler`: event handler|`undefined`| register `handler` with event type `key`. | | ||
@@ -87,6 +87,15 @@ ... and events, which can be observed via `observe` method. | ||
## FAQ | ||
* __Can we use multiple *canvases* with `canvas-area` ?__ | ||
* `canvas-area` is a container element for potentially multiple `canvas` elements. | ||
* Multiple *canvases* are mostly used as layers stacked on top of each others in practice. Please note here: | ||
* for every `canvas` element except the first one use `position:absolute;` style. | ||
* stacking level can be made explicite using `z-index: 5;` style. | ||
* `canvas` elements are transparent by default. So avoid giving them individual background colors. | ||
* `canvas-area` is managing the *resize* of its `canvas` children, but not their - then necessary - `redraw`. | ||
* `canvas-area` is managing the *view* parameters for *pan* and *zoom*, but does not apply those values to the `canvas` contexes. Do that by yourself while redrawing or by using the `on('view',...)` handler. | ||
* __Does not work properly with Mobile Device X and Touch Screen Y ?__ | ||
* Desktop browsers only are addressed at current. | ||
* I'm unsure, if and when to add *touch* and *pen* events. | ||
* Desktop browsers only are addressed primarily at current. | ||
* Implementation of touch events is experimental (*pan* works with touch and *resize* also using a *pen* now). | ||
* Issues with Microsoft Edge. | ||
@@ -98,10 +107,14 @@ * __Can you implement feature X and possibly feature Y ?__ | ||
* If you think, your enhancement is of common interest, you are very welcome, to send me a pull request. | ||
## Changelog | ||
### [0.4.5] on January 19, 2018 | ||
* chainable method `on(key,handler)` added. | ||
* method `observe(key,handler)` marked as deprecated. Use `on(key,handler)` instead. | ||
* renamed event property `buttons` to `btn` in [`drag`,`pointer`,`buttondown`,`buttonup`,`pointerenter`,`pointerleave`] event. | ||
* necessary styles `display: block; overflow: hidden;` automatically added as inline style while constructing. | ||
### [0.4.0] on January 06, 2018 | ||
* Initial release. | ||
## License | ||
@@ -108,0 +121,0 @@ |
Sorry, the diff of this file is not supported yet
1626895
192
122