mirror of
https://github.com/igorski/bitmappery.git
synced 2026-07-26 16:57:43 +02:00
Refator zCanvas actor inheritance to use ES6 classes
This commit is contained in:
@@ -24,69 +24,71 @@ import { sprite } from "zcanvas";
|
||||
import { createCanvas } from "@/utils/canvas-util";
|
||||
import { LAYER_GRAPHIC, LAYER_MASK } from "@/definitions/layer-types";
|
||||
|
||||
function LayerSprite( layer ) {
|
||||
this._layer = layer;
|
||||
class LayerSprite extends sprite {
|
||||
constructor( layer ) {
|
||||
if ( layer.type === LAYER_GRAPHIC && !layer.bitmap ) {
|
||||
// create a Bitmap on which this layer will render its drawable content.
|
||||
// assign this Bitmap to the layer
|
||||
const { cvs } = createCanvas( layer.width, layer.height );
|
||||
layer.bitmap = cvs;
|
||||
}
|
||||
let { bitmap, x, y, width, height } = layer;
|
||||
|
||||
if ( layer.type === LAYER_GRAPHIC && !layer.bitmap ) {
|
||||
// create a Bitmap on which this layer will render its drawable content.
|
||||
// assign this Bitmap to the layer
|
||||
const { cvs } = createCanvas( layer.width, layer.height );
|
||||
layer.bitmap = cvs;
|
||||
// zCanvas inheritance
|
||||
super({ bitmap, x, y, width, height } );
|
||||
this.setDraggable( true );
|
||||
|
||||
this._layer = layer;
|
||||
|
||||
// create brush (always as all layers can be maskable)
|
||||
const brushCanvas = createCanvas();
|
||||
this._brushCvs = brushCanvas.cvs;
|
||||
this._brushCtx = brushCanvas.ctx;
|
||||
this._halfRadius = 0;
|
||||
|
||||
this.cacheGradient( "rgba(255,0,0,1)" );
|
||||
}
|
||||
let { bitmap, x, y, width, height } = layer;
|
||||
|
||||
// zCanvas inheritance
|
||||
LayerSprite.super( this, "constructor", { bitmap, x, y, width, height } );
|
||||
this.setDraggable( true );
|
||||
isDrawable() {
|
||||
return this._layer.type === LAYER_GRAPHIC || this.isMaskable();
|
||||
}
|
||||
|
||||
// create brush (always as all layers can be maskable)
|
||||
const brushCanvas = createCanvas();
|
||||
this._brushCvs = brushCanvas.cvs;
|
||||
this._brushCtx = brushCanvas.ctx;
|
||||
this._halfRadius = 0;
|
||||
isMaskable() {
|
||||
return !!this._layer.mask;
|
||||
}
|
||||
|
||||
this.cacheGradient( "rgba(255,0,0,1)" );
|
||||
cacheGradient( color, radius = 30 ) {
|
||||
const innerRadius = radius / 6;
|
||||
const outerRadius = radius * 2;
|
||||
|
||||
const x = radius;
|
||||
const y = radius;
|
||||
|
||||
// update brush Canvas size
|
||||
this._brushCvs.width = outerRadius;
|
||||
this._brushCvs.height = outerRadius;
|
||||
|
||||
const gradient = this._brushCtx.createRadialGradient( x, y, innerRadius, x, y, outerRadius );
|
||||
gradient.addColorStop( 0, color );
|
||||
gradient.addColorStop( 1, 'rgba(255,255,255,0)' );
|
||||
|
||||
this._brushCtx.clearRect( 0, 0, this._brushCvs.width, this._brushCvs.height );
|
||||
this._brushCtx.arc( x, y, radius, 0, 2 * Math.PI );
|
||||
this._brushCtx.fillStyle = gradient;
|
||||
this._brushCtx.fill();
|
||||
|
||||
this._halfRadius = radius / 2;
|
||||
}
|
||||
|
||||
// overridden from zCanvas.sprite
|
||||
handleMove( x, y ) {
|
||||
if ( !this.isDrawable() ) {
|
||||
return super.handleMove( x, y );
|
||||
}
|
||||
// cache this upfront
|
||||
const ctx = this.isMaskable() ? this._layer.mask.getContext( "2d" ) : this._bitmap.getContext( "2d" );
|
||||
// note we draw onto the layer bitmap to make this permanent
|
||||
ctx.drawImage( this._brushCvs, x - this._halfRadius, y - this._halfRadius );
|
||||
}
|
||||
}
|
||||
sprite.extend( LayerSprite );
|
||||
export default LayerSprite;
|
||||
|
||||
/* instance methods */
|
||||
|
||||
LayerSprite.prototype.isDrawable = function() {
|
||||
return this._layer.type === LAYER_GRAPHIC || this.isMaskable();
|
||||
};
|
||||
|
||||
LayerSprite.prototype.isMaskable = function() {
|
||||
return !!this._layer.mask;
|
||||
};
|
||||
|
||||
LayerSprite.prototype.cacheGradient = function( color, radius = 30 ) {
|
||||
const innerRadius = radius / 6;
|
||||
const outerRadius = radius * 2;
|
||||
|
||||
const x = radius;
|
||||
const y = radius;
|
||||
|
||||
// update brush Canvas size
|
||||
this._brushCvs.width = outerRadius;
|
||||
this._brushCvs.height = outerRadius;
|
||||
|
||||
const gradient = this._brushCtx.createRadialGradient( x, y, innerRadius, x, y, outerRadius );
|
||||
gradient.addColorStop( 0, color );
|
||||
gradient.addColorStop( 1, 'rgba(255,255,255,0)' );
|
||||
|
||||
this._brushCtx.clearRect( 0, 0, this._brushCvs.width, this._brushCvs.height );
|
||||
this._brushCtx.arc( x, y, radius, 0, 2 * Math.PI );
|
||||
this._brushCtx.fillStyle = gradient;
|
||||
this._brushCtx.fill();
|
||||
|
||||
this._halfRadius = radius / 2;
|
||||
};
|
||||
|
||||
// overridden from zCanvas.sprite
|
||||
LayerSprite.prototype.handleMove = function( x, y ) {
|
||||
// cache this upfront
|
||||
const ctx = this.isMaskable() ? this._layer.mask.getContext( "2d" ) : this._bitmap.getContext( "2d" );
|
||||
// note we draw onto the layer bitmap to make this permanent
|
||||
ctx.drawImage( this._brushCvs, x - this._halfRadius, y - this._halfRadius );
|
||||
};
|
||||
|
||||
@@ -22,77 +22,76 @@
|
||||
*/
|
||||
import { canvas } from "zcanvas";
|
||||
|
||||
function ZoomableCanvas( opts ) {
|
||||
ZoomableCanvas.super( this, "constructor", opts ); // zCanvas inheritance
|
||||
class ZoomableCanvas extends canvas {
|
||||
constructor( opts ) {
|
||||
super( opts );
|
||||
this.setZoomFactor( 1 );
|
||||
}
|
||||
|
||||
this.setZoomFactor = function( xScale, yScale ) {
|
||||
setZoomFactor( xScale, yScale ) {
|
||||
this.zoomFactor = xScale;
|
||||
|
||||
// This zoom factor logic should move into the zCanvas
|
||||
// library where updateCanvasSize() takes this additional factor into account
|
||||
|
||||
this._canvasContext.scale( xScale, yScale );
|
||||
this.invalidate();
|
||||
};
|
||||
this._canvasContext.scale( xScale, yScale );
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
// TODO add the lines suffixed with // QQQ to zCanvas lib instead of using these overrides
|
||||
|
||||
this.setZoomFactor( 1 );
|
||||
}
|
||||
canvas.extend( ZoomableCanvas );
|
||||
export default ZoomableCanvas;
|
||||
handleInteraction( aEvent ) {
|
||||
const numChildren = this._children.length;
|
||||
let theChild, touches, found;
|
||||
|
||||
// TODO add the lines suffixed with // QQQ to zCanvas lib instead of using these overrides
|
||||
if ( numChildren > 0 ) {
|
||||
|
||||
ZoomableCanvas.prototype.handleInteraction = function( aEvent ) {
|
||||
const numChildren = this._children.length;
|
||||
let theChild, touches, found;
|
||||
// reverse loop to first handle top layers
|
||||
theChild = this._children[ numChildren - 1 ];
|
||||
|
||||
if ( numChildren > 0 ) {
|
||||
switch ( aEvent.type ) {
|
||||
|
||||
// reverse loop to first handle top layers
|
||||
theChild = this._children[ numChildren - 1 ];
|
||||
// all touch events
|
||||
default:
|
||||
let eventOffsetX = 0, eventOffsetY = 0;
|
||||
touches /** @type {TouchList} */ = ( aEvent.touches.length > 0 ) ? aEvent.touches : aEvent.changedTouches;
|
||||
|
||||
switch ( aEvent.type ) {
|
||||
if ( touches.length > 0 ) {
|
||||
const offset = this.getCoordinate();
|
||||
|
||||
// all touch events
|
||||
default:
|
||||
let eventOffsetX = 0, eventOffsetY = 0;
|
||||
touches /** @type {TouchList} */ = ( aEvent.touches.length > 0 ) ? aEvent.touches : aEvent.changedTouches;
|
||||
|
||||
if ( touches.length > 0 ) {
|
||||
const offset = this.getCoordinate();
|
||||
|
||||
eventOffsetX = ( touches[ 0 ].pageX - offset.x ) / this.zoomFactor ; // QQQ
|
||||
eventOffsetY = ( touches[ 0 ].pageY - offset.y ) / this.zoomFactor; // QQQ
|
||||
}
|
||||
|
||||
while ( theChild ) {
|
||||
theChild.handleInteraction( eventOffsetX, eventOffsetY, aEvent );
|
||||
theChild = theChild.last; // note we don't break this loop for multi touch purposes
|
||||
}
|
||||
break;
|
||||
|
||||
// all mouse events
|
||||
case "mousedown":
|
||||
case "mousemove":
|
||||
case "mouseup":
|
||||
let { offsetX, offsetY } = aEvent;
|
||||
offsetX /= this.zoomFactor; // QQQ
|
||||
offsetY /= this.zoomFactor; // QQQ
|
||||
while ( theChild ) {
|
||||
found = theChild.handleInteraction( offsetX, offsetY, aEvent );
|
||||
if ( found ) {
|
||||
break;
|
||||
eventOffsetX = ( touches[ 0 ].pageX - offset.x ) / this.zoomFactor ; // QQQ
|
||||
eventOffsetY = ( touches[ 0 ].pageY - offset.y ) / this.zoomFactor; // QQQ
|
||||
}
|
||||
theChild = theChild.last;
|
||||
}
|
||||
break;
|
||||
|
||||
while ( theChild ) {
|
||||
theChild.handleInteraction( eventOffsetX, eventOffsetY, aEvent );
|
||||
theChild = theChild.last; // note we don't break this loop for multi touch purposes
|
||||
}
|
||||
break;
|
||||
|
||||
// all mouse events
|
||||
case "mousedown":
|
||||
case "mousemove":
|
||||
case "mouseup":
|
||||
let { offsetX, offsetY } = aEvent;
|
||||
offsetX /= this.zoomFactor; // QQQ
|
||||
offsetY /= this.zoomFactor; // QQQ
|
||||
while ( theChild ) {
|
||||
found = theChild.handleInteraction( offsetX, offsetY, aEvent );
|
||||
if ( found ) {
|
||||
break;
|
||||
}
|
||||
theChild = theChild.last;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( this._preventDefaults ) {
|
||||
aEvent.stopPropagation();
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
// update the Canvas contents
|
||||
this.invalidate();
|
||||
}
|
||||
if ( this._preventDefaults ) {
|
||||
aEvent.stopPropagation();
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
// update the Canvas contents
|
||||
this.invalidate();
|
||||
};
|
||||
}
|
||||
export default ZoomableCanvas;
|
||||
|
||||
Reference in New Issue
Block a user