konva/test/unit/Node-cache-test.js
Anton Lavrenov 970473a56f fix test
2020-08-08 09:45:01 -05:00

1474 lines
31 KiB
JavaScript

suite('Caching', function () {
// this.timeout(5000);
// CACHING SHAPE
test('cache simple rectangle', function () {
var stage = addStage();
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 100,
height: 50,
fill: 'green',
draggable: true,
});
rect.cache();
layer.add(rect);
stage.add(layer);
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.beginPath();
context.rect(100, 50, 100, 50);
context.closePath();
context.fillStyle = 'green';
context.fill();
compareLayerAndCanvas(layer, canvas, 10);
cloneAndCompareLayer(layer);
showHit(layer);
});
test('cache simple rectangle with transform', function () {
var stage = addStage();
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 100,
height: 50,
rotation: 45,
scaleY: 2,
fill: 'green',
});
rect.cache();
layer.add(rect);
stage.add(layer);
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.translate(100, 50);
context.rotate(Math.PI / 4);
context.beginPath();
context.rect(0, 0, 100, 100);
context.closePath();
context.fillStyle = 'green';
context.fill();
compareLayerAndCanvas(layer, canvas, 200);
cloneAndCompareLayer(layer, 150);
});
test('cache rectangle with fill and stroke', function () {
var stage = addStage();
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 100,
height: 50,
fill: 'green',
stroke: 'black',
strokeWidth: 20,
});
rect.cache();
layer.add(rect);
stage.add(layer);
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.beginPath();
context.rect(100, 50, 100, 50);
context.closePath();
context.fillStyle = 'green';
context.fill();
context.lineWidth = 20;
context.stroke();
compareLayerAndCanvas(layer, canvas, 50);
cloneAndCompareLayer(layer, 50);
});
test('cache rectangle with fill and opacity', function () {
var stage = addStage();
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 100,
height: 50,
fill: 'green',
opacity: 0.5,
});
rect.cache();
rect.opacity(0.3);
layer.add(rect);
stage.add(layer);
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.globalAlpha = 0.3;
context.beginPath();
context.rect(100, 50, 100, 50);
context.closePath();
context.fillStyle = 'green';
context.fill();
compareLayerAndCanvas(layer, canvas, 5);
});
test('cache rectangle with fill, stroke opacity', function () {
var stage = addStage();
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 100,
height: 50,
fill: 'green',
opacity: 0.5,
stroke: 'black',
strokeWidth: 10,
});
rect.cache();
rect.opacity(0.3);
layer.add(rect);
stage.add(layer);
cloneAndCompareLayer(layer, 100);
});
// skip, because opacity rendering of cached shape is different
// nothing we can do here
test('cache rectangle with fill, shadow and opacity', function () {
var stage = addStage();
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 10,
y: 10,
width: 100,
height: 50,
fill: 'green',
opacity: 0.5,
shadowBlur: 10,
shadowColor: 'black',
draggable: true,
});
// rect.cache();
// rect.opacity(0.3);
layer.add(rect.clone({ y: 50, x: 50, shadowEnabled: false }));
layer.add(rect);
stage.add(layer);
cloneAndCompareLayer(layer, 10);
});
test('cache rectangle with fill and simple shadow', function () {
Konva.pixelRatio = 1;
var stage = addStage();
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 100,
height: 50,
fill: 'green',
shadowColor: 'black',
shadowBlur: 10,
draggable: true,
});
rect.cache();
layer.add(rect);
stage.add(layer);
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.beginPath();
context.rect(100, 50, 100, 50);
context.closePath();
context.fillStyle = 'green';
context.shadowColor = 'black';
context.shadowBlur = 10;
context.fill();
showCanvas(rect._getCanvasCache().scene._canvas);
showCanvas(rect._getCanvasCache().hit._canvas);
showHit(layer);
compareLayerAndCanvas(layer, canvas, 10);
Konva.pixelRatio = undefined;
});
test('cache rectangle with fill and shadow with offset', function () {
var stage = addStage();
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 50,
height: 25,
fill: 'green',
shadowOffsetX: 10,
shadowOffsetY: 10,
shadowColor: 'black',
shadowBlur: 10,
});
rect.cache();
layer.add(rect);
stage.add(layer);
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.translate(100, 50);
context.beginPath();
context.rect(0, 0, 50, 25);
context.closePath();
context.fillStyle = 'green';
context.shadowColor = 'black';
context.shadowBlur = 10 * canvas.ratio;
context.shadowOffsetX = 10 * canvas.ratio;
context.shadowOffsetY = 10 * canvas.ratio;
context.fill();
compareLayerAndCanvas(layer, canvas, 50);
});
test('cache rectangle with fill and shadow with negative offset', function () {
var stage = addStage();
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 50,
height: 25,
fill: 'green',
shadowOffsetX: -10,
shadowOffsetY: -10,
shadowColor: 'black',
shadowBlur: 10,
});
rect.cache();
layer.add(rect);
stage.add(layer);
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.translate(100, 50);
context.beginPath();
context.rect(0, 0, 50, 25);
context.closePath();
context.fillStyle = 'green';
context.shadowColor = 'black';
context.shadowBlur = 10 * canvas.ratio;
context.shadowOffsetX = -10 * canvas.ratio;
context.shadowOffsetY = -10 * canvas.ratio;
context.fill();
compareLayerAndCanvas(layer, canvas, 50);
});
test('cache rectangle with fill and shadow with negative offset and scale', function () {
var stage = addStage();
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 50,
height: 25,
fill: 'green',
shadowOffsetX: -10,
shadowOffsetY: -10,
shadowColor: 'black',
shadowBlur: 10,
scaleX: 2,
scaleY: 2,
});
rect.cache();
layer.add(rect);
stage.add(layer);
cloneAndCompareLayer(layer, 200);
});
test('cache rectangle with fill and shadow and some transform', function () {
var stage = addStage();
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 50,
height: 25,
fill: 'green',
shadowOffsetX: -10,
shadowOffsetY: -10,
shadowColor: 'black',
shadowBlur: 10,
offsetX: 50,
offsetY: 25,
});
rect.cache();
layer.add(rect);
stage.add(layer);
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.translate(50, 25);
context.beginPath();
context.rect(0, 0, 50, 25);
context.closePath();
context.fillStyle = 'green';
context.shadowColor = 'black';
context.shadowBlur = 10 * canvas.ratio;
context.shadowOffsetX = -10 * canvas.ratio;
context.shadowOffsetY = -10 * canvas.ratio;
context.fill();
compareLayerAndCanvas(layer, canvas, 50);
});
// CACHING CONTAINERS
test('cache group with simple rectangle', function () {
var stage = addStage();
var layer = new Konva.Layer();
var group = new Konva.Group({
x: 100,
y: 50,
});
var rect = new Konva.Rect({
width: 100,
height: 50,
fill: 'green',
});
group.add(rect);
group.cache();
layer.add(group);
stage.add(layer);
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.beginPath();
context.rect(100, 50, 100, 50);
context.closePath();
context.fillStyle = 'green';
context.fill();
compareLayerAndCanvas(layer, canvas, 10);
cloneAndCompareLayer(layer);
});
test('cache group with simple rectangle with transform', function () {
var stage = addStage();
var layer = new Konva.Layer();
var group = new Konva.Group({
x: 50,
y: 25,
});
var rect = new Konva.Rect({
x: 50,
y: 25,
width: 100,
height: 50,
fill: 'green',
rotation: 45,
});
group.add(rect);
group.cache();
layer.add(group);
stage.add(layer);
cloneAndCompareLayer(layer, 200);
});
test('cache group with several shape with transform', function () {
var stage = addStage();
var layer = new Konva.Layer();
var group = new Konva.Group({
x: 50,
y: 25,
});
var rect = new Konva.Rect({
x: 50,
y: 25,
width: 100,
height: 50,
fill: 'green',
shadowOffsetX: 10,
shadowOffsetY: 10,
shadowBlur: 10,
});
group.add(rect);
var circle = new Konva.Circle({
x: 250,
y: 50,
radius: 25,
fill: 'red',
// rotation on circle should not have any effects
stroke: 'black',
rotation: 45,
scaleX: 2,
scaleY: 2,
});
group.add(circle);
group.cache();
layer.add(group);
stage.add(layer);
var canvas = createCanvas();
var context = canvas.getContext('2d');
// draw rect
context.save();
context.beginPath();
context.rect(100, 50, 100, 50);
context.closePath();
context.fillStyle = 'green';
context.shadowColor = 'black';
context.shadowBlur = 10 * canvas.ratio;
context.shadowOffsetX = 10 * canvas.ratio;
context.shadowOffsetY = 10 * canvas.ratio;
context.fill();
context.restore();
// circle
context.save();
context.beginPath();
context.arc(300, 75, 50, 0, Math.PI * 2);
context.closePath();
context.fillStyle = 'red';
context.lineWidth = 4;
context.fill();
context.stroke();
context.restore();
compareLayerAndCanvas(layer, canvas, 150);
// recache
group.cache();
layer.draw();
compareLayerAndCanvas(layer, canvas, 150);
});
test('cache group with rectangle and text', function () {
var stage = addStage();
var layer = new Konva.Layer();
var button = new Konva.Group({
width: 100,
height: 50,
draggable: true,
});
var face = new Konva.Rect({
fill: 'red',
x: 0,
y: 0,
width: 100,
height: 50,
});
var text = new Konva.Text({
text: 'Wrong button',
x: 15,
y: 20,
});
button.add(face);
button.add(text);
button.cache();
layer.add(button);
stage.add(layer);
cloneAndCompareLayer(layer, 100);
});
test('cache layer with several shape with transform', function () {
var stage = addStage();
var layer = new Konva.Layer({
draggable: true,
});
var group = new Konva.Group({
x: 50,
y: 25,
});
var rect = new Konva.Rect({
x: 50,
y: 25,
width: 100,
height: 50,
fill: 'green',
shadowOffsetX: 10,
shadowOffsetY: 10,
shadowBlur: 10,
});
group.add(rect);
var circle = new Konva.Circle({
x: 250,
y: 50,
radius: 25,
fill: 'red',
// rotation on circle should not have any effects
rotation: 45,
stroke: 'black',
scaleX: 2,
scaleY: 2,
});
group.add(circle);
group.cache();
layer.add(group);
stage.add(layer);
var canvas = createCanvas();
var context = canvas.getContext('2d');
// draw rect
context.save();
context.beginPath();
context.rect(100, 50, 100, 50);
context.closePath();
context.fillStyle = 'green';
context.shadowColor = 'black';
context.shadowBlur = 10 * canvas.ratio;
context.shadowOffsetX = 10 * canvas.ratio;
context.shadowOffsetY = 10 * canvas.ratio;
context.fill();
context.restore();
// circle
context.save();
context.beginPath();
context.arc(300, 75, 50, 0, Math.PI * 2);
context.closePath();
context.fillStyle = 'red';
context.lineWidth = 4;
context.fill();
context.stroke();
context.restore();
compareLayerAndCanvas(layer, canvas, 150);
// recache
group.cache();
layer.draw();
compareLayerAndCanvas(layer, canvas, 150);
});
test('cache shape that is larger than stage', function () {
var stage = addStage();
var layer = new Konva.Layer();
var group = new Konva.Group();
var circle = new Konva.Circle({
x: 74,
y: 74,
radius: 300,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
scaleX: 1 / 2,
scaleY: 1 / 2,
});
group.add(circle);
layer.add(group);
stage.add(layer);
assert.equal(circle._getCanvasCache(), undefined);
var canvas = createCanvas();
var context = canvas.getContext('2d');
// circle
context.save();
context.beginPath();
context.arc(74, 74, 150, 0, Math.PI * 2);
context.closePath();
context.fillStyle = 'red';
context.lineWidth = 2;
context.fill();
context.stroke();
context.restore();
compareLayerAndCanvas(layer, canvas, 150);
});
test('cache shape that is larger than stage but need buffer canvas', function () {
var stage = addStage();
var layer = new Konva.Layer();
var group = new Konva.Group();
var circle = new Konva.Circle({
x: stage.width() / 2,
y: stage.height() / 2,
radius: 400,
fill: 'red',
stroke: 'black',
strokeWidth: 50,
opacity: 0.5,
scaleX: 1 / 5,
scaleY: 1 / 5,
});
group.add(circle);
layer.add(group);
stage.add(layer);
circle.cache();
layer.draw();
cloneAndCompareLayer(layer, 200);
});
test('cache nested groups', function () {
var stage = addStage();
var layer = new Konva.Layer();
var groupOuter = new Konva.Group({
x: 50,
y: 10,
});
var groupInner = new Konva.Group({
x: 10,
y: 10,
draggable: true,
});
var rect = new Konva.Rect({
width: 50,
height: 50,
stroke: 'grey',
strokeWidth: 3,
fill: 'yellow',
});
var text = new Konva.Text({
x: 18,
y: 15,
text: 'A',
fill: 'black',
fontSize: 24,
});
groupInner.add(rect);
groupInner.add(text);
groupOuter.add(groupInner);
layer.add(groupOuter);
stage.add(layer);
groupInner.cache();
layer.draw();
cloneAndCompareLayer(layer, 150);
groupInner.clearCache();
groupOuter.cache();
layer.draw();
cloneAndCompareLayer(layer, 150);
groupOuter.clearCache();
groupInner.clearCache();
rect.cache();
layer.draw();
cloneAndCompareLayer(layer, 150);
});
test('test group with circle + buffer canvas usage', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var group = new Konva.Group({
x: 100,
y: 100,
draggable: true,
});
layer.add(group);
var circle = new Konva.Circle({
radius: 10,
// fill: 'white',
fillRadialGradientStartRadius: 0,
fillRadialGradientEndRadius: 10,
fillRadialGradientColorStops: [0, 'red', 0.5, 'yellow', 1, 'black'],
opacity: 0.4,
strokeHitEnabled: false,
stroke: 'rgba(0,0,0,0)',
});
group.add(circle);
group.cache();
stage.draw();
cloneAndCompareLayer(layer, 200);
});
test('test group with opacity', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var group = new Konva.Group({
x: 100,
y: 100,
draggable: true,
});
layer.add(group);
var circle = new Konva.Circle({
radius: 10,
fillRadialGradientStartRadius: 0,
fillRadialGradientEndRadius: 10,
fillRadialGradientColorStops: [0, 'red', 0.5, 'yellow', 1, 'black'],
opacity: 0.4,
strokeHitEnabled: false,
stroke: 'rgba(0,0,0,0)',
});
group.add(circle);
group.cache();
stage.draw();
cloneAndCompareLayer(layer, 210);
});
test('test group with opacity', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var group = new Konva.Group({
x: 100,
y: 100,
draggable: true,
});
layer.add(group);
var circle = new Konva.Circle({
radius: 10,
fillRadialGradientStartRadius: 0,
fillRadialGradientEndRadius: 10,
fillRadialGradientColorStops: [0, 'red', 0.5, 'yellow', 1, 'black'],
opacity: 0.4,
strokeHitEnabled: false,
stroke: 'rgba(0,0,0,0)',
});
group.add(circle);
group.cache();
stage.draw();
cloneAndCompareLayer(layer, 100);
});
test('test rect with float dimensions', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var group = new Konva.Group({
x: 10,
y: 10,
draggable: true,
});
layer.add(group);
var circle = new Konva.Circle({
radius: 52.2,
fill: 'red',
});
group.add(circle);
group.cache();
const canvas = group._cache.get('canvas').scene;
assert.equal(canvas.width, 105 * canvas.pixelRatio);
});
test('cache group with rectangle with fill and opacity', function () {
var stage = addStage();
var layer = new Konva.Layer();
var group = new Konva.Group({
opacity: 0.5,
});
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 100,
height: 50,
fill: 'green',
});
group.add(rect);
layer.add(group);
stage.add(layer);
group.cache();
layer.draw();
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.globalAlpha = 0.5;
context.beginPath();
context.rect(100, 50, 100, 50);
context.closePath();
context.fillStyle = 'green';
context.fill();
compareLayerAndCanvas(layer, canvas, 5);
});
test('even if parent is not visible cache should be created', function () {
var stage = addStage();
var layer = new Konva.Layer({
visible: false,
});
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 100,
height: 100,
fill: 'green',
});
layer.add(rect);
stage.add(layer);
rect.cache();
layer.visible(true);
layer.draw();
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.beginPath();
context.rect(100, 50, 100, 100);
context.closePath();
context.fillStyle = 'green';
context.fill();
showHit(layer);
compareLayerAndCanvas(layer, canvas, 5);
assert.equal(stage.getIntersection({ x: 150, y: 100 }), rect);
});
test('even if parent is not listening cache and hit should be created', function () {
var stage = addStage();
var layer = new Konva.Layer({
listening: false,
});
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 100,
height: 100,
fill: 'green',
});
layer.add(rect);
stage.add(layer);
rect.cache();
layer.listening(true);
layer.draw();
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.beginPath();
context.rect(100, 50, 100, 100);
context.closePath();
context.fillStyle = 'green';
context.fill();
showHit(layer);
compareLayerAndCanvas(layer, canvas, 5);
assert.equal(stage.getIntersection({ x: 150, y: 100 }), rect);
});
// hard to fix
test.skip('even if parent is not visible cache should be created - test for group', function () {
var stage = addStage();
var layer = new Konva.Layer({
visible: false,
});
var group = new Konva.Group({
opacity: 0.5,
});
var rect = new Konva.Rect({
x: 100,
y: 50,
width: 100,
height: 100,
fill: 'green',
});
group.add(rect);
layer.add(group);
stage.add(layer);
group.cache();
layer.visible(true);
layer.draw();
var canvas = createCanvas();
var context = canvas.getContext('2d');
context.globalAlpha = 0.5;
context.beginPath();
context.rect(100, 50, 100, 100);
context.closePath();
context.fillStyle = 'green';
context.fill();
compareLayerAndCanvas(layer, canvas, 5);
assert.equal(stage.getIntersection({ x: 150, y: 100 }), rect);
});
it('listening false on a shape should not create hit area', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var bigCircle = new Konva.Circle({
x: 100,
y: 100,
radius: 100,
fill: 'green',
});
layer.add(bigCircle);
var smallCircle = new Konva.Circle({
x: 100,
y: 100,
radius: 50,
fill: 'red',
listening: false,
});
layer.add(smallCircle);
smallCircle.cache();
layer.draw();
var shape = stage.getIntersection({ x: 100, y: 100 });
assert.equal(shape, bigCircle);
});
it('listening false on a shape inside group should not create hit area', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var group = new Konva.Group();
layer.add(group);
var bigCircle = new Konva.Circle({
x: 100,
y: 100,
radius: 100,
fill: 'green',
});
group.add(bigCircle);
var smallCircle = new Konva.Circle({
x: 100,
y: 100,
radius: 50,
fill: 'red',
listening: false,
});
group.add(smallCircle);
group.cache();
layer.draw();
var shape = stage.getIntersection({ x: 100, y: 100 });
assert.equal(shape, bigCircle);
});
it('listening false on a group inside a group should not create hit area', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var group = new Konva.Group();
layer.add(group);
var bigCircle = new Konva.Circle({
x: 100,
y: 100,
radius: 100,
fill: 'green',
});
group.add(bigCircle);
var innerGroup = new Konva.Group({
listening: false,
});
group.add(innerGroup);
var smallCircle = new Konva.Circle({
x: 100,
y: 100,
radius: 50,
fill: 'red',
});
innerGroup.add(smallCircle);
group.cache();
layer.draw();
var shape = stage.getIntersection({ x: 100, y: 100 });
assert.equal(shape, bigCircle);
});
// for performance reasons
it('do no call client rect calculation, if we do not need it', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var group = new Konva.Group();
layer.add(group);
var bigCircle = new Konva.Circle({
x: 100,
y: 100,
radius: 100,
fill: 'green',
});
group.add(bigCircle);
layer.draw();
var called = false;
group.getClientRect = function () {
called = true;
};
group.cache({
x: 0,
y: 0,
width: 100,
height: 100,
});
assert.equal(called, false);
});
// for performance reasons
it('caching should skip clearing internal caching for perf boos', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var bigCircle = new Konva.Circle({
x: 100,
y: 100,
radius: 100,
fill: 'green',
});
layer.add(bigCircle);
layer.cache();
var callCount = 0;
bigCircle._clearSelfAndDescendantCache = function () {
callCount += 1;
};
layer.x(10);
assert.equal(callCount, 0);
layer.clearCache();
// make sure all cleared for children
assert.equal(callCount, 1);
});
it('caching group with clip', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var width = 100;
var height = 100;
var verts = [
{ x: width * 0.2, y: 0 },
{ x: width, y: 0 },
{ x: width * 0.8, y: height },
{ x: 0, y: height },
];
var clipFunc = (ctx) => {
for (let i = 0; i < verts.length; i++) {
const vertex = verts[i];
if (i === 0) {
ctx.moveTo(vertex.x, vertex.y);
} else {
ctx.lineTo(vertex.x, vertex.y);
}
}
ctx.closePath();
};
var group1 = new Konva.Group({
clipFunc: clipFunc,
x: 50,
y: 50,
listening: false,
});
layer.add(group1);
var rect1 = new Konva.Rect({
fill: 'green',
width: 100,
height: 100,
});
group1.add(rect1);
layer.draw();
group1.cache();
layer.draw();
// var group2 = group1.clone({
// x: height - 20,
// y: 50,
// });
// group2.findOne('Rect').fill('red');
// layer.add(group2);
// group2.cache();
// var group3 = group1.clone({
// x: width + 20,
// });
// layer.add(group3);
// group3.findOne('Rect').x(150);
// group2.cache();
layer.draw();
cloneAndCompareLayer(layer, 10);
// throw 1;
});
it('check caching with global composite operation', function () {
var stage = addStage();
const layer = new Konva.Layer();
stage.add(layer);
function getColor(pos) {
var ratio = layer.canvas.pixelRatio;
var p = layer.canvas.context.getImageData(
Math.round(pos.x * ratio),
Math.round(pos.y * ratio),
1,
1
).data;
return Konva.Util._rgbToHex(p[0], p[1], p[2]);
}
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.get('canvas').scene._canvas;
maskgroup.globalCompositeOperation('destination-in');
maskgroup.cache();
var canvasAfter = maskgroup._cache.get('canvas').scene._canvas;
compareCanvases(canvasBefore, canvasAfter);
maskgroup.clearCache();
layer.draw();
// no caches - mask group clipped all drawing
assert.equal(getColor({ x: 5, y: 20 }), '000000');
assert.equal(getColor({ x: 55, y: 20 }), '0000ff');
// cache inner mask group - same result
maskgroup.cache();
layer.draw();
assert.equal(getColor({ x: 5, y: 20 }), '000000');
assert.equal(getColor({ x: 55, y: 20 }), '0000ff');
// cache group
// background will be visible now, because globalCompositeOperation
// will work inside cached parent only
group.cache();
layer.draw();
assert.equal(getColor({ x: 5, y: 20 }), 'd3d3d3');
assert.equal(getColor({ x: 55, y: 20 }), '0000ff');
});
it('recache should update internal caching', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var bigCircle = new Konva.Circle({
x: 100,
y: 100,
radius: 100,
fill: 'red',
draggable: true,
});
layer.add(bigCircle);
bigCircle.cache();
layer.draw();
var d = layer.getContext().getImageData(100, 100, 1, 1).data;
assert.equal(d[0], 255, 'see red');
bigCircle.fill('blue');
bigCircle.cache();
layer.draw();
d = layer.getContext().getImageData(100, 100, 1, 1).data;
assert.equal(d[0], 0, 'no red');
assert.equal(d[2], 255, 'see blue');
});
it('recache with filters', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var bigCircle = new Konva.Circle({
x: 100,
y: 100,
radius: 100,
fill: 'red',
draggable: true,
});
layer.add(bigCircle);
bigCircle.filters([Konva.Filters.Blur]);
bigCircle.blurRadius(10);
bigCircle.cache();
layer.draw();
bigCircle.cache();
layer.draw();
var d = layer.getContext().getImageData(100, 100, 1, 1).data;
assert.equal(d[0], 255, 'see red');
});
test('check image smooth', function () {
var stage = addStage();
var layer = new Konva.Layer({
imageSmoothingEnabled: false,
});
stage.add(layer);
var bigCircle = new Konva.Circle({
x: 100,
y: 100,
radius: 10,
fill: 'red',
draggable: true,
scaleX: 10,
scaleY: 10,
});
layer.add(bigCircle);
bigCircle.cache({
imageSmoothingEnabled: false,
});
layer.draw();
assert.equal(
bigCircle._cache.get('canvas').scene.getContext()._context
.imageSmoothingEnabled,
false
);
});
test('getAbsolutePosition for cached container', function () {
var stage = addStage();
var layer = new Konva.Layer({});
stage.add(layer);
var circle = new Konva.Circle({
x: 100,
y: 100,
radius: 10,
fill: 'red',
draggable: true,
scaleX: 10,
scaleY: 10,
});
layer.add(circle);
// initial calculations
circle.getAbsolutePosition();
//
layer.cache();
layer.draw();
layer.position({
x: 10,
y: 10,
});
assert.equal(circle.getAbsolutePosition().x, 110);
assert.equal(circle.getAbsolutePosition().y, 110);
});
test('cached node should not have filter canvas until we have a filter', function () {
var stage = addStage();
var layer = new Konva.Layer({});
stage.add(layer);
var circle = new Konva.Circle({
x: 100,
y: 100,
radius: 10,
fill: 'red',
draggable: true,
scaleX: 10,
scaleY: 10,
});
layer.add(circle);
circle.cache();
assert.equal(circle._cache.get('canvas').filter.width, 0);
circle.filters([Konva.Filters.Blur]);
layer.draw();
assert.equal(
circle._cache.get('canvas').filter.width,
20 * circle._cache.get('canvas').filter.pixelRatio
);
circle.filters([]);
// TODO: should we clear cache canvas?
// assert.equal(circle._cache.get('canvas').filter.width, 0);
});
test('hit from cache + global composite', function (done) {
// blend mode should NOT effect hit detection.
var stage = addStage();
var layer = new Konva.Layer({});
stage.add(layer);
Konva.Image.fromURL('./assets/lion.png', function (lion) {
lion.name('lion');
lion.cache();
lion.drawHitFromCache();
layer.add(lion);
Konva.Image.fromURL('./assets/lion.png', function (lion2) {
lion2.position({
x: 50,
y: 50,
});
lion2.name('lion2');
lion2.globalCompositeOperation('overlay');
lion2.cache();
lion2.drawHitFromCache();
layer.add(lion2);
layer.draw();
layer.toggleHitCanvas();
var shape = layer.getIntersection({ x: 106, y: 78 });
assert.equal(shape, lion2);
done();
});
});
});
});