Proposal: Using ECMAScript 6 Map for Node._cache instead of plain Object

This commit is contained in:
VladimirTechMan 2019-02-17 23:59:08 +03:00
parent 1dea3696a2
commit 26d40ae1f9
8 changed files with 65 additions and 58 deletions

View File

@ -404,7 +404,7 @@ export abstract class Container extends Node {
var layer = this.getLayer(),
canvas = can || (layer && layer.getCanvas()),
context = canvas && canvas.getContext(),
cachedCanvas = this._cache.canvas,
cachedCanvas = this._getCanvasCache(),
cachedSceneCanvas = cachedCanvas && cachedCanvas.scene;
if (this.isVisible() || caching) {
@ -423,7 +423,7 @@ export abstract class Container extends Node {
var layer = this.getLayer(),
canvas = can || (layer && layer.hitCanvas),
context = canvas && canvas.getContext(),
cachedCanvas = this._cache.canvas,
cachedCanvas = this._getCanvasCache(),
cachedHitCanvas = cachedCanvas && cachedCanvas.hit;
if (this.shouldDrawHit(canvas) || caching) {

View File

@ -70,6 +70,7 @@ type globalCompositeOperationType =
var ABSOLUTE_OPACITY = 'absoluteOpacity',
ABSOLUTE_TRANSFORM = 'absoluteTransform',
ABSOLUTE_SCALE = 'absoluteScale',
CANVAS = 'canvas',
CHANGE = 'Change',
CHILDREN = 'children',
KONVA = 'konva',
@ -116,7 +117,7 @@ export abstract class Node {
attrs: any = {};
index = 0;
parent: Container = null;
_cache: any = {};
_cache: Map<string, any> = new Map<string, any>();
_lastPos = null;
_filterUpToDate = false;
@ -160,21 +161,25 @@ export abstract class Node {
/** @lends Konva.Node.prototype */
_clearCache(attr) {
if (attr) {
delete this._cache[attr];
this._cache.delete(attr);
} else {
this._cache = {};
this._cache.clear();
}
}
_getCache(attr, privateGetter) {
var cache = this._cache[attr];
var cache = this._cache.get(attr);
// if not cached, we need to set it using the private getter method.
if (cache === undefined) {
this._cache[attr] = cache = privateGetter.call(this);
cache = privateGetter.call(this);
this._cache.set(attr, cache);
}
return cache;
}
_getCanvasCache() {
return this._cache.get(CANVAS);
}
/*
* when the logic for a cached result depends on ancestor propagation, use this
* method to clear self and children cache
@ -183,7 +188,7 @@ export abstract class Node {
this._clearCache(attr);
// skip clearing if node is cached with canvas
if (this._cache.canvas) {
if (this._getCanvasCache()) {
return;
}
if (this.children) {
@ -201,7 +206,7 @@ export abstract class Node {
* node.clearCache();
*/
clearCache() {
delete this._cache.canvas;
this._cache.delete(CANVAS);
this._filterUpToDate = false;
this._clearSelfAndDescendantCache();
return this;
@ -339,13 +344,13 @@ export abstract class Node {
sceneContext.restore();
}
this._cache.canvas = {
this._cache.set(CANVAS, {
scene: cachedSceneCanvas,
filter: cachedFilterCanvas,
hit: cachedHitCanvas,
x: x,
y: y
};
});
return this;
}
@ -430,7 +435,9 @@ export abstract class Node {
context.save();
context._applyOpacity(this);
context._applyGlobalCompositeOperation(this);
context.translate(this._cache.canvas.x, this._cache.canvas.y);
const canvasCache = this._getCanvasCache();
context.translate(canvasCache.x, canvasCache.y);
var cacheCanvas = this._getCachedSceneCanvas();
var ratio = cacheCanvas.pixelRatio;
@ -445,16 +452,16 @@ export abstract class Node {
context.restore();
}
_drawCachedHitCanvas(context) {
var cachedCanvas = this._cache.canvas,
hitCanvas = cachedCanvas.hit;
var canvasCache = this._getCanvasCache(),
hitCanvas = canvasCache.hit;
context.save();
context.translate(this._cache.canvas.x, this._cache.canvas.y);
context.translate(canvasCache.x, canvasCache.y);
context.drawImage(hitCanvas._canvas, 0, 0);
context.restore();
}
_getCachedSceneCanvas() {
var filters = this.filters(),
cachedCanvas = this._cache.canvas,
cachedCanvas = this._getCanvasCache(),
sceneCanvas = cachedCanvas.scene,
filterCanvas = cachedCanvas.filter,
filterContext = filterCanvas.getContext(),

View File

@ -406,7 +406,7 @@ export class Shape extends Node {
var layer = this.getLayer(),
canvas = can || layer.getCanvas(),
context = canvas.getContext(),
cachedCanvas = this._cache.canvas,
cachedCanvas = this._getCanvasCache(),
drawFunc = this.sceneFunc(),
hasShadow = this.hasShadow(),
hasStroke = this.hasStroke(),
@ -530,7 +530,7 @@ export class Shape extends Node {
canvas = can || layer.hitCanvas,
context = canvas.getContext(),
drawFunc = this.hitFunc() || this.sceneFunc(),
cachedCanvas = this._cache.canvas,
cachedCanvas = this._getCanvasCache(),
cachedHitCanvas = cachedCanvas && cachedCanvas.hit;
if (!this.colorKey) {
@ -581,7 +581,7 @@ export class Shape extends Node {
*/
drawHitFromCache(alphaThreshold) {
var threshold = alphaThreshold || 0,
cachedCanvas = this._cache.canvas,
cachedCanvas = this._getCanvasCache(),
sceneCanvas = this._getCachedSceneCanvas(),
hitCanvas = cachedCanvas.hit,
hitContext = hitCanvas.getContext(),

View File

@ -210,8 +210,8 @@ suite('Caching', function() {
context.shadowBlur = 10;
context.fill();
showCanvas(rect._cache.canvas.scene._canvas);
showCanvas(rect._cache.canvas.hit._canvas);
showCanvas(rect._getCanvasCache().scene._canvas);
showCanvas(rect._getCanvasCache().hit._canvas);
showHit(layer);
compareLayerAndCanvas(layer, canvas, 10);
Konva.pixelRatio = undefined;
@ -596,7 +596,7 @@ suite('Caching', function() {
layer.add(group);
stage.add(layer);
assert.equal(circle._cache.canvas, undefined);
assert.equal(circle._getCanvasCache(), undefined);
var canvas = createCanvas();
var context = canvas.getContext('2d');

View File

@ -150,17 +150,17 @@ suite('Node', function() {
strokeWidth: 4
});
assert.equal(circle._cache.transform, undefined);
assert.equal(circle._cache.get('transform'), undefined);
layer.add(circle);
stage.add(layer);
// transform cache
assert.notEqual(circle._cache.transform, undefined);
assert.notEqual(circle._cache.get('transform'), undefined);
circle.setX(100);
assert.equal(circle._cache.transform, undefined);
assert.equal(circle._cache.get('transform'), undefined);
layer.draw();
assert.notEqual(circle._cache.transform, undefined);
assert.notEqual(circle._cache.get('transform'), undefined);
});
// ======================================================
@ -179,15 +179,15 @@ suite('Node', function() {
stage.add(layer);
// visible cache
assert.equal(circle._cache.visible, true);
assert.equal(circle._cache.get('visible'), true);
circle.hide();
assert.equal(circle._cache.visible, undefined);
assert.equal(circle._cache.get('visible'), undefined);
stage.draw();
assert.equal(circle._cache.visible, false);
assert.equal(circle._cache.get('visible'), false);
circle.show();
assert.equal(circle._cache.visible, undefined);
assert.equal(circle._cache.get('visible'), undefined);
layer.draw();
assert.equal(circle._cache.visible, true);
assert.equal(circle._cache.get('visible'), true);
});
// ======================================================
@ -206,14 +206,14 @@ suite('Node', function() {
stage.add(layer);
// shadow cache
assert.equal(circle._cache.hasShadow, false);
assert.equal(circle._cache.get('hasShadow'), false);
circle.setShadowColor('red');
circle.setShadowOffset(10);
assert.equal(circle._cache.hasShadow, undefined);
assert.equal(circle._cache.get('hasShadow'), undefined);
layer.draw();
assert.equal(circle._cache.hasShadow, true);
assert.equal(circle._cache.get('hasShadow'), true);
layer.draw();
assert.equal(circle._cache.hasShadow, true);
assert.equal(circle._cache.get('hasShadow'), true);
});
// ======================================================
@ -255,11 +255,11 @@ suite('Node', function() {
stage.add(layer);
// opacity cache
assert.equal(circle._cache.absoluteOpacity, 1);
assert.equal(circle._cache.get('absoluteOpacity'), 1);
circle.setOpacity(0.5);
assert.equal(circle._cache.absoluteOpacity, undefined);
assert.equal(circle._cache.get('absoluteOpacity'), undefined);
layer.draw();
assert.equal(circle._cache.absoluteOpacity, 0.5);
assert.equal(circle._cache.get('absoluteOpacity'), 0.5);
});
// ======================================================
@ -282,11 +282,11 @@ suite('Node', function() {
// prime the cache
circle.isListening();
assert.equal(circle._cache.listening, true);
assert.equal(circle._cache.get('listening'), true);
circle.setListening(false);
assert.equal(circle._cache.listening, undefined);
assert.equal(circle._cache.get('listening'), undefined);
circle.isListening();
assert.equal(circle._cache.listening, false);
assert.equal(circle._cache.get('listening'), false);
});
// ======================================================
@ -306,7 +306,7 @@ suite('Node', function() {
// stage cache
var st = circle.getStage();
assert.equal(circle._cache.stage._id, stage._id);
assert.equal(circle._cache.get('stage')._id, stage._id);
});
// ======================================================
@ -3405,7 +3405,7 @@ suite('Node', function() {
layer.add(group);
stage.add(layer);
assert.equal(circle._cache.canvas, undefined);
assert.equal(circle._getCanvasCache(), undefined);
circle
.cache({
@ -3419,19 +3419,19 @@ suite('Node', function() {
y: 74
});
assert.notEqual(circle._cache.canvas.scene, undefined);
assert.notEqual(circle._cache.canvas.hit, undefined);
assert.notEqual(circle._getCanvasCache().scene, undefined);
assert.notEqual(circle._getCanvasCache().hit, undefined);
layer.draw();
//document.body.appendChild(circle._cache.canvas.scene._canvas);
// document.body.appendChild(circle._cache.canvas.hit._canvas);
//document.body.appendChild(circle._getCanvasCache().scene._canvas);
// document.body.appendChild(circle._getCanvasCache().hit._canvas);
showHit(layer);
//assert.equal(layer.getContext().getTrace(), 'clearRect(0,0,578,200);save();transform(1,0,0,1,74,74);beginPath();arc(0,0,70,0,6.283,false);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);drawImage([object HTMLCanvasElement],0,0);restore();');
//assert.equal(circle._cache.canvas.scene.getContext().getTrace(), 'save();translate(74,74);beginPath();arc(0,0,70,0,6.283,false);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();');
//assert.equal(circle._getCanvasCache().scene.getContext().getTrace(), 'save();translate(74,74);beginPath();arc(0,0,70,0,6.283,false);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();');
});
test('cache shape before adding to layer', function() {
@ -3457,7 +3457,7 @@ suite('Node', function() {
});
group.add(rect);
assert.equal(rect._cache.canvas, undefined);
assert.equal(rect._getCanvasCache(), undefined);
group.cache({
x: 0,
y: 0,
@ -3466,8 +3466,8 @@ suite('Node', function() {
});
stage.add(layer);
assert(group._cache.canvas.scene);
assert(group._cache.canvas.hit);
assert(group._getCanvasCache().scene);
assert(group._getCanvasCache().hit);
layer.add(group);
layer.draw();

View File

@ -904,7 +904,7 @@ suite('Shape', function() {
lion.cache();
//document.body.appendChild(lion._cache.canvas.hit._canvas);
//document.body.appendChild(lion._getCanvasCache().hit._canvas);
lion.drawHitFromCache();

View File

@ -108,7 +108,7 @@ suite('Blur', function() {
layer.draw();
//document.body.appendChild(group._cache.canvas.hit._canvas);
//document.body.appendChild(group._getCanvasCache().hit._canvas);
//showHit(layer);
});
@ -293,11 +293,11 @@ suite('Blur', function() {
darth.drawHitFromCache(100);
layer.draw();
showCanvas(darth._cache.canvas.hit._canvas);
showCanvas(darth._getCanvasCache().hit._canvas);
//console.log(darth._cache.canvas.hit.getContext().getTrace());
//console.log(darth._getCanvasCache().hit.getContext().getTrace());
//assert.equal(darth._cache.canvas.hit.getContext().getTrace(true), 'save();translate();beginPath();rect();closePath();save();fillStyle;fill();restore();restore();clearRect();getImageData();putImageData();');
//assert.equal(darth._getCanvasCache().hit.getContext().getTrace(true), 'save();translate();beginPath();rect();closePath();save();fillStyle;fill();restore();restore();clearRect();getImageData();putImageData();');
done();
};

View File

@ -1294,7 +1294,7 @@ suite('Transformer', function() {
layer.draw();
assert.equal(tr._cache.transform.m[4], 50);
assert.equal(tr._cache.get('transform').m[4], 50);
var rect = new Konva.Rect({
x: 50,
@ -1308,7 +1308,7 @@ suite('Transformer', function() {
tr.forceUpdate();
layer.draw();
assert.equal(tr._cache.transform.m[4], 100);
assert.equal(tr._cache.get('transform').m[4], 100);
// tr._fitNodeInto({
// x: 100,