fix some docs, partial cache fixes

This commit is contained in:
Anton Lavrenov 2019-02-18 12:12:03 -05:00
parent 1dea3696a2
commit 40cf5a5909
14 changed files with 171 additions and 37 deletions

View File

@ -8,7 +8,7 @@
* Konva JavaScript Framework v3.0.0-0
* http://konvajs.github.io/
* Licensed under the MIT
* Date: Thu Feb 14 2019
* Date: Mon Feb 18 2019
*
* Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS)
* Modified work Copyright (C) 2014 - present by Anton Lavrenov (Konva)
@ -1721,6 +1721,12 @@
});
};
};
Context.prototype._applyGlobalCompositeOperation = function (node) {
var globalCompositeOperation = node.getGlobalCompositeOperation();
if (globalCompositeOperation !== 'source-over') {
this.setAttr('globalCompositeOperation', globalCompositeOperation);
}
};
return Context;
}());
CONTEXT_PROPERTIES.forEach(function (prop) {
@ -1863,12 +1869,6 @@
this.setAttr('shadowOffsetX', offset.x * scaleX);
this.setAttr('shadowOffsetY', offset.y * scaleY);
};
SceneContext.prototype._applyGlobalCompositeOperation = function (shape) {
var globalCompositeOperation = shape.getGlobalCompositeOperation();
if (globalCompositeOperation !== 'source-over') {
this.setAttr('globalCompositeOperation', globalCompositeOperation);
}
};
return SceneContext;
}(Context));
var HitContext = /** @class */ (function (_super) {
@ -2012,7 +2012,7 @@
return this._canvas.toDataURL();
}
catch (err) {
Util.warn('Unable to get data URL. ' + err.message);
Util.error('Unable to get data URL. ' + err.message);
return '';
}
}
@ -2531,7 +2531,7 @@
Node.prototype.clearCache = function () {
delete this._cache.canvas;
this._filterUpToDate = false;
this._clearSelfAndDescendantCache();
this._clearSelfAndDescendantCache(undefined);
return this;
};
/**
@ -2613,7 +2613,7 @@
height: height
}), sceneContext = cachedSceneCanvas.getContext(), hitContext = cachedHitCanvas.getContext();
cachedHitCanvas.isCache = true;
this.clearCache();
// this.clearCache();
sceneContext.save();
hitContext.save();
sceneContext.translate(-x, -y);
@ -2730,6 +2730,7 @@
Node.prototype._drawCachedHitCanvas = function (context) {
var cachedCanvas = this._cache.canvas, hitCanvas = cachedCanvas.hit;
context.save();
context._applyGlobalCompositeOperation(this);
context.translate(this._cache.canvas.x, this._cache.canvas.y);
context.drawImage(hitCanvas._canvas, 0, 0);
context.restore();
@ -5272,7 +5273,7 @@
context.restore();
}
else {
this._drawChildren(canvas, 'drawHit', top);
this._drawChildren(canvas, 'drawHit', top, false, caching);
}
}
return this;
@ -5301,10 +5302,18 @@
.getMatrix();
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
}
var hasComposition = this.globalCompositeOperation() !== 'source-over' && !caching;
if (hasComposition && layer) {
context.save();
context._applyGlobalCompositeOperation(this);
}
this.children.each(function (child) {
child[drawMethod](canvas, top, caching, skipBuffer);
});
if (hasClip) {
if (hasComposition && layer) {
context.restore();
}
if (hasClip && layer) {
context.restore();
}
};
@ -6138,7 +6147,6 @@
}(Container));
Stage.prototype.nodeType = STAGE$1;
// TODO: test for replacing container
Factory.addGetterSetter(Stage, 'container');
/**
* get/set container DOM element
* @method
@ -6151,7 +6159,8 @@
* var container = document.createElement('div');
* body.appendChild(container);
* stage.container(container);
*/
*/
Factory.addGetterSetter(Stage, 'container');
/**
* BaseLayer constructor.
@ -6650,6 +6659,20 @@
this.hitGraphEnabled(false);
return this;
};
// document it:
Layer.prototype.toggleHitCanvas = function () {
if (!this.parent) {
return;
}
var parent = this.parent;
var added = !!this.hitCanvas._canvas.parentNode;
if (added) {
parent.content.removeChild(this.hitCanvas._canvas);
}
else {
parent.content.appendChild(this.hitCanvas._canvas);
}
};
Layer.prototype.setSize = function (_a) {
var width = _a.width, height = _a.height;
_super.prototype.setSize.call(this, { width: width, height: height });
@ -7474,7 +7497,8 @@
*/
Factory.addGetterSetter(Shape, 'sceneFunc');
/**
* get/set scene draw function
* get/set scene draw function. That function is used to draw the shape on a canvas.
* Also that function will be used to draw hit area of the shape, in case if hitFunc is not defined.
* @name Konva.Shape#sceneFunc
* @method
* @param {Function} drawFunc drawing function
@ -7489,12 +7513,13 @@
* context.rect(0, 0, shape.width(), shape.height());
* context.closePath();
* // important Konva method that fill and stroke shape from its properties
* // like stroke and fill
* context.fillStrokeShape(shape);
* });
*/
Factory.addGetterSetter(Shape, 'hitFunc');
/**
* get/set hit draw function
* get/set hit draw function. That function is used to draw custom hit area of a shape.
* @name Konva.Shape#hitFunc
* @method
* @param {Function} drawFunc drawing function
@ -9831,6 +9856,7 @@
/**
* Ellipse constructor
* @constructor
* @memberof Konva
* @augments Konva.Shape
* @param {Object} config
* @param {Object} config.radius defines x and y radius
@ -11639,6 +11665,7 @@
* Ring constructor
* @constructor
* @augments Konva.Shape
* @memberof Konva
* @param {Object} config
* @param {Number} config.innerRadius
* @param {Number} config.outerRadius
@ -12617,7 +12644,7 @@
* That method can't handle multiline text.
* @method
* @name Konva.Text#measureSize
* @param {Number} [text] text to measure
* @param {String} [text] text to measure
* @returns {Object} { width , height} of measured text
*/
Text.prototype.measureSize = function (text) {
@ -14668,6 +14695,7 @@
/**
* Wedge constructor
* @constructor
* @memberof Konva
* @augments Konva.Shape
* @param {Object} config
* @param {Number} config.angle in degrees

4
konva.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -134,7 +134,7 @@ export class Canvas {
try {
return this._canvas.toDataURL();
} catch (err) {
Util.warn('Unable to get data URL. ' + err.message);
Util.error('Unable to get data URL. ' + err.message);
return '';
}
}

View File

@ -433,7 +433,7 @@ export abstract class Container extends Node {
this._drawCachedHitCanvas(context);
context.restore();
} else {
this._drawChildren(canvas, 'drawHit', top);
this._drawChildren(canvas, 'drawHit', top, false, caching);
}
}
return this;
@ -470,11 +470,21 @@ export abstract class Container extends Node {
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
}
var hasComposition =
this.globalCompositeOperation() !== 'source-over' && !caching;
if (hasComposition && layer) {
context.save();
context._applyGlobalCompositeOperation(this);
}
this.children.each(function(child) {
child[drawMethod](canvas, top, caching, skipBuffer);
});
if (hasComposition && layer) {
context.restore();
}
if (hasClip) {
if (hasClip && layer) {
context.restore();
}
}

View File

@ -452,6 +452,12 @@ export class Context {
});
};
}
_applyGlobalCompositeOperation(node) {
var globalCompositeOperation = node.getGlobalCompositeOperation();
if (globalCompositeOperation !== 'source-over') {
this.setAttr('globalCompositeOperation', globalCompositeOperation);
}
}
}
CONTEXT_PROPERTIES.forEach(function(prop) {
@ -628,12 +634,6 @@ export class SceneContext extends Context {
this.setAttr('shadowOffsetX', offset.x * scaleX);
this.setAttr('shadowOffsetY', offset.y * scaleY);
}
_applyGlobalCompositeOperation(shape) {
var globalCompositeOperation = shape.getGlobalCompositeOperation();
if (globalCompositeOperation !== 'source-over') {
this.setAttr('globalCompositeOperation', globalCompositeOperation);
}
}
}
export class HitContext extends Context {

View File

@ -207,6 +207,20 @@ export class Layer extends BaseLayer {
this.hitGraphEnabled(false);
return this;
}
// document it:
toggleHitCanvas() {
if (!this.parent) {
return;
}
var parent = this.parent as any;
var added = !!this.hitCanvas._canvas.parentNode;
if (added) {
parent.content.removeChild(this.hitCanvas._canvas);
} else {
parent.content.appendChild(this.hitCanvas._canvas);
}
}
setSize({ width, height }) {
super.setSize({ width, height });
this.hitCanvas.setSize(width, height);

View File

@ -203,7 +203,7 @@ export abstract class Node {
clearCache() {
delete this._cache.canvas;
this._filterUpToDate = false;
this._clearSelfAndDescendantCache();
this._clearSelfAndDescendantCache(undefined);
return this;
}
/**
@ -306,7 +306,7 @@ export abstract class Node {
cachedHitCanvas.isCache = true;
this.clearCache();
// this.clearCache();
sceneContext.save();
hitContext.save();
@ -448,6 +448,7 @@ export abstract class Node {
var cachedCanvas = this._cache.canvas,
hitCanvas = cachedCanvas.hit;
context.save();
context._applyGlobalCompositeOperation(this);
context.translate(this._cache.canvas.x, this._cache.canvas.y);
context.drawImage(hitCanvas._canvas, 0, 0);
context.restore();

View File

@ -855,7 +855,8 @@ Factory.addGetterSetter(Shape, 'lineCap');
Factory.addGetterSetter(Shape, 'sceneFunc');
/**
* get/set scene draw function
* get/set scene draw function. That function is used to draw the shape on a canvas.
* Also that function will be used to draw hit area of the shape, in case if hitFunc is not defined.
* @name Konva.Shape#sceneFunc
* @method
* @param {Function} drawFunc drawing function
@ -870,6 +871,7 @@ Factory.addGetterSetter(Shape, 'sceneFunc');
* context.rect(0, 0, shape.width(), shape.height());
* context.closePath();
* // important Konva method that fill and stroke shape from its properties
* // like stroke and fill
* context.fillStrokeShape(shape);
* });
*/
@ -877,7 +879,7 @@ Factory.addGetterSetter(Shape, 'sceneFunc');
Factory.addGetterSetter(Shape, 'hitFunc');
/**
* get/set hit draw function
* get/set hit draw function. That function is used to draw custom hit area of a shape.
* @name Konva.Shape#hitFunc
* @method
* @param {Function} drawFunc drawing function

View File

@ -773,8 +773,6 @@ export class Stage extends Container {
Stage.prototype.nodeType = STAGE;
// TODO: test for replacing container
Factory.addGetterSetter(Stage, 'container');
/**
* get/set container DOM element
* @method
@ -788,3 +786,6 @@ Factory.addGetterSetter(Stage, 'container');
* body.appendChild(container);
* stage.container(container);
*/
Factory.addGetterSetter(Stage, 'container');

View File

@ -8,6 +8,7 @@ import { GetSet, Vector2d } from '../types';
/**
* Ellipse constructor
* @constructor
* @memberof Konva
* @augments Konva.Shape
* @param {Object} config
* @param {Object} config.radius defines x and y radius

View File

@ -8,6 +8,7 @@ var PIx2 = Math.PI * 2;
* Ring constructor
* @constructor
* @augments Konva.Shape
* @memberof Konva
* @param {Object} config
* @param {Number} config.innerRadius
* @param {Number} config.outerRadius

View File

@ -292,7 +292,7 @@ export class Text extends Shape {
* That method can't handle multiline text.
* @method
* @name Konva.Text#measureSize
* @param {Number} [text] text to measure
* @param {String} [text] text to measure
* @returns {Object} { width , height} of measured text
*/
measureSize(text) {

View File

@ -9,6 +9,7 @@ import { GetSet } from '../types';
/**
* Wedge constructor
* @constructor
* @memberof Konva
* @augments Konva.Shape
* @param {Object} config
* @param {Number} config.angle in degrees

View File

@ -176,7 +176,7 @@ suite('Caching', function() {
layer.add(rect);
stage.add(layer);
cloneAndCompareLayer(layer, 10);
cloneAndCompareLayer(layer, 10);
});
test('cache rectangle with fill and simple shadow', function() {
@ -386,7 +386,7 @@ suite('Caching', function() {
layer.add(group);
stage.add(layer);
cloneAndCompareLayer(layer, 200);
cloneAndCompareLayer(layer, 200);
});
test('cache group with several shape with transform', function() {
@ -1027,4 +1027,79 @@ suite('Caching', function() {
// make sure all cleared for children
assert.equal(callCount, 1);
});
it.skip('check caching with global composite operation', function() {
var stage = addStage();
const layer = new Konva.Layer();
stage.add(layer);
const bg = new Konva.Rect({
x: 0,
y: 0,
width: stage.width(),
height: stage.height(),
fill: 'lightgray'
});
layer.add(bg);
const group = new Konva.Group();
layer.add(group);
const rect = new Konva.Rect({
x: 10,
y: 0,
width: 200,
height: 100,
fill: 'blue',
draggable: true
});
group.add(rect);
const maskgroup = new Konva.Group({});
group.add(maskgroup);
const mask = new Konva.Rect({
x: 50,
y: 0,
width: 100,
height: 100,
fill: 'black'
});
maskgroup.add(mask);
maskgroup.cache();
var canvasBefore = maskgroup._cache.canvas.scene._canvas;
maskgroup.globalCompositeOperation('destination-in');
maskgroup.cache();
var canvasAfter = maskgroup._cache.canvas.scene._canvas;
compareCanvases(canvasBefore, canvasAfter);
console.log(maskgroup);
// maskgroup.clearCache();
// layer.draw();
// // // no caches - mask group clipped all drawing
// assert.equal(stage.getIntersection({ x: 5, y: 20 }), null);
// assert.equal(stage.getIntersection({ x: 55, y: 20 }), rect);
// // cache inner mask group - same result
// maskgroup.cache();
// layer.draw();
// assert.equal(stage.getIntersection({ x: 5, y: 20 }), null);
// assert.equal(stage.getIntersection({ x: 55, y: 20 }), rect);
// cache group
// background will be visible now, because globalCompositeOperation
// will work inside cached parent only
// debugger;
// group.cache();
// layer.draw();
// console.log(group);
// assert.equal(stage.getIntersection({ x: 5, y: 20 }), bg);
// assert.equal(stage.getIntersection({ x: 55, y: 20 }), rect);
throw '';
});
});