konva/test/unit/Node-cache-test.js

974 lines
20 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);
});
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();
if (!window.isPhantomJS) {
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.skip('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);
if (!window.isPhantomJS) {
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._cache.canvas.scene._canvas);
showCanvas(rect._cache.canvas.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 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);
if (!window.isPhantomJS) {
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._cache.canvas, 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',
fillRadialGradientStartPoint: 0,
fillRadialGradientStartRadius: 0,
fillRadialGradientEndPoint: 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,
fillRadialGradientStartPoint: 0,
fillRadialGradientStartRadius: 0,
fillRadialGradientEndPoint: 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('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);
});
// 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);
});
});