Refator zCanvas actor inheritance to use ES6 classes

This commit is contained in:
Igor Zinken
2020-12-20 10:28:06 +01:00
parent 6abcc01edf
commit b685c669de
2 changed files with 117 additions and 116 deletions

View File

@@ -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 );
};

View File

@@ -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;