mirror of
https://github.com/konvajs/konva.git
synced 2025-06-28 06:07:13 +08:00
fix caching when buffer is used. close #1886
fix svg length calculation. close #1869
This commit is contained in:
parent
8211db3233
commit
2e08f7319f
@ -1,8 +1,6 @@
|
|||||||
import { Util } from './Util';
|
import { Util } from './Util';
|
||||||
import { SceneContext, HitContext, Context } from './Context';
|
import { SceneContext, HitContext, Context } from './Context';
|
||||||
import { Konva } from './Global';
|
import { Konva } from './Global';
|
||||||
import { Factory } from './Factory';
|
|
||||||
import { getNumberValidator } from './Validators';
|
|
||||||
|
|
||||||
// calculate pixel ratio
|
// calculate pixel ratio
|
||||||
let _pixelRatio;
|
let _pixelRatio;
|
||||||
|
26
src/Node.ts
26
src/Node.ts
@ -248,8 +248,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
|
|||||||
*/
|
*/
|
||||||
clearCache() {
|
clearCache() {
|
||||||
if (this._cache.has(CANVAS)) {
|
if (this._cache.has(CANVAS)) {
|
||||||
const { scene, filter, hit } = this._cache.get(CANVAS);
|
const { scene, filter, hit, buffer } = this._cache.get(CANVAS);
|
||||||
Util.releaseCanvas(scene, filter, hit);
|
Util.releaseCanvas(scene, filter, hit, buffer);
|
||||||
this._cache.delete(CANVAS);
|
this._cache.delete(CANVAS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,6 +385,18 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
|
|||||||
sceneContext = cachedSceneCanvas.getContext(),
|
sceneContext = cachedSceneCanvas.getContext(),
|
||||||
hitContext = cachedHitCanvas.getContext();
|
hitContext = cachedHitCanvas.getContext();
|
||||||
|
|
||||||
|
const bufferCanvas = new SceneCanvas({
|
||||||
|
// width and height already multiplied by pixelRatio
|
||||||
|
// so we need to revert that
|
||||||
|
// also increase size by x nd y offset to make sure content fits canvas
|
||||||
|
width:
|
||||||
|
cachedSceneCanvas.width / cachedSceneCanvas.pixelRatio + Math.abs(x),
|
||||||
|
height:
|
||||||
|
cachedSceneCanvas.height / cachedSceneCanvas.pixelRatio + Math.abs(y),
|
||||||
|
pixelRatio: cachedSceneCanvas.pixelRatio,
|
||||||
|
}),
|
||||||
|
bufferContext = bufferCanvas.getContext();
|
||||||
|
|
||||||
cachedHitCanvas.isCache = true;
|
cachedHitCanvas.isCache = true;
|
||||||
cachedSceneCanvas.isCache = true;
|
cachedSceneCanvas.isCache = true;
|
||||||
|
|
||||||
@ -398,16 +410,23 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
|
|||||||
|
|
||||||
sceneContext.save();
|
sceneContext.save();
|
||||||
hitContext.save();
|
hitContext.save();
|
||||||
|
bufferContext.save();
|
||||||
|
|
||||||
sceneContext.translate(-x, -y);
|
sceneContext.translate(-x, -y);
|
||||||
hitContext.translate(-x, -y);
|
hitContext.translate(-x, -y);
|
||||||
|
bufferContext.translate(-x, -y);
|
||||||
|
// hard-code offset to make sure content fits canvas
|
||||||
|
// @ts-ignore
|
||||||
|
bufferCanvas.x = x;
|
||||||
|
// @ts-ignore
|
||||||
|
bufferCanvas.y = y;
|
||||||
|
|
||||||
// extra flag to skip on getAbsolute opacity calc
|
// extra flag to skip on getAbsolute opacity calc
|
||||||
this._isUnderCache = true;
|
this._isUnderCache = true;
|
||||||
this._clearSelfAndDescendantCache(ABSOLUTE_OPACITY);
|
this._clearSelfAndDescendantCache(ABSOLUTE_OPACITY);
|
||||||
this._clearSelfAndDescendantCache(ABSOLUTE_SCALE);
|
this._clearSelfAndDescendantCache(ABSOLUTE_SCALE);
|
||||||
|
|
||||||
this.drawScene(cachedSceneCanvas, this);
|
this.drawScene(cachedSceneCanvas, this, bufferCanvas);
|
||||||
this.drawHit(cachedHitCanvas, this);
|
this.drawHit(cachedHitCanvas, this);
|
||||||
this._isUnderCache = false;
|
this._isUnderCache = false;
|
||||||
|
|
||||||
@ -431,6 +450,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
|
|||||||
scene: cachedSceneCanvas,
|
scene: cachedSceneCanvas,
|
||||||
filter: cachedFilterCanvas,
|
filter: cachedFilterCanvas,
|
||||||
hit: cachedHitCanvas,
|
hit: cachedHitCanvas,
|
||||||
|
buffer: bufferCanvas,
|
||||||
x: x,
|
x: x,
|
||||||
y: y,
|
y: y,
|
||||||
});
|
});
|
||||||
|
10
src/Shape.ts
10
src/Shape.ts
@ -602,7 +602,7 @@ export class Shape<
|
|||||||
stage,
|
stage,
|
||||||
bufferContext;
|
bufferContext;
|
||||||
|
|
||||||
const skipBuffer = canvas.isCache;
|
const skipBuffer = false;
|
||||||
const cachingSelf = top === this;
|
const cachingSelf = top === this;
|
||||||
|
|
||||||
if (!this.isVisible() && !cachingSelf) {
|
if (!this.isVisible() && !cachingSelf) {
|
||||||
@ -646,7 +646,13 @@ export class Shape<
|
|||||||
}
|
}
|
||||||
context._applyOpacity(this);
|
context._applyOpacity(this);
|
||||||
context._applyGlobalCompositeOperation(this);
|
context._applyGlobalCompositeOperation(this);
|
||||||
context.drawImage(bc._canvas, 0, 0, bc.width / ratio, bc.height / ratio);
|
context.drawImage(
|
||||||
|
bc._canvas,
|
||||||
|
bc.x || 0,
|
||||||
|
bc.y || 0,
|
||||||
|
bc.width / ratio,
|
||||||
|
bc.height / ratio
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
context._applyLineJoin(this);
|
context._applyLineJoin(this);
|
||||||
|
|
||||||
|
@ -258,11 +258,19 @@ export class Path extends Shape<PathConfig> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (length < 0.01) {
|
if (length < 0.01) {
|
||||||
|
const cmd = dataArray[i].command;
|
||||||
|
if (cmd === 'M') {
|
||||||
points = dataArray[i].points.slice(0, 2);
|
points = dataArray[i].points.slice(0, 2);
|
||||||
return {
|
return {
|
||||||
x: points[0],
|
x: points[0],
|
||||||
y: points[1],
|
y: points[1],
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
x: dataArray[i].start.x,
|
||||||
|
y: dataArray[i].start.y,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const cp = dataArray[i];
|
const cp = dataArray[i];
|
||||||
|
@ -1083,6 +1083,7 @@ describe('Path', function () {
|
|||||||
it('get point at path', function () {
|
it('get point at path', function () {
|
||||||
var stage = addStage();
|
var stage = addStage();
|
||||||
var layer = new Konva.Layer();
|
var layer = new Konva.Layer();
|
||||||
|
stage.add(layer);
|
||||||
const data =
|
const data =
|
||||||
'M 300,10 L 250,100 A 100 40 30 1 0 150 150 C 160,100, 290,100, 300,150';
|
'M 300,10 L 250,100 A 100 40 30 1 0 150 150 C 160,100, 290,100, 300,150';
|
||||||
var path = new Konva.Path({
|
var path = new Konva.Path({
|
||||||
@ -1102,7 +1103,7 @@ describe('Path', function () {
|
|||||||
var circle = new Konva.Circle({
|
var circle = new Konva.Circle({
|
||||||
x: p.x,
|
x: p.x,
|
||||||
y: p.y,
|
y: p.y,
|
||||||
radius: 2,
|
radius: 0.1,
|
||||||
fill: 'black',
|
fill: 'black',
|
||||||
stroke: 'black',
|
stroke: 'black',
|
||||||
});
|
});
|
||||||
@ -1164,13 +1165,49 @@ describe('Path', function () {
|
|||||||
{ x: 299.87435436448743, y: 149.4028482225714 },
|
{ x: 299.87435436448743, y: 149.4028482225714 },
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('get point at vertical path', function () {
|
||||||
|
var stage = addStage();
|
||||||
|
var layer = new Konva.Layer();
|
||||||
|
const data = 'M 614.96002,7.5147864 611.20262,429.59529';
|
||||||
|
var path = new Konva.Path({
|
||||||
|
stroke: 'red',
|
||||||
|
strokeWidth: 3,
|
||||||
|
data,
|
||||||
|
x: -600,
|
||||||
|
});
|
||||||
|
layer.add(path);
|
||||||
|
if (isBrowser) {
|
||||||
|
const SVGPath = document.createElementNS(
|
||||||
|
'http://www.w3.org/2000/svg',
|
||||||
|
'path'
|
||||||
|
) as SVGPathElement;
|
||||||
|
SVGPath.setAttribute('d', data);
|
||||||
|
for (var i = 0.001; i < path.getLength(); i += 1) {
|
||||||
|
var p = path.getPointAtLength(i);
|
||||||
|
console.log(p);
|
||||||
|
var circle = new Konva.Circle({
|
||||||
|
x: p.x + path.x(),
|
||||||
|
y: p.y + path.y(),
|
||||||
|
radius: 2,
|
||||||
|
fill: 'black',
|
||||||
|
stroke: 'black',
|
||||||
|
});
|
||||||
|
layer.add(circle);
|
||||||
|
const position = SVGPath.getPointAtLength(i);
|
||||||
|
console.log(position);
|
||||||
|
assert(Math.abs(p.x - position.x) <= 1);
|
||||||
|
assert(Math.abs(p.y - position.y) <= 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
stage.add(layer);
|
stage.add(layer);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('get point at path with float attrs', function () {
|
it('get point at path with float attrs', function () {
|
||||||
var stage = addStage();
|
var stage = addStage();
|
||||||
var layer = new Konva.Layer();
|
var layer = new Konva.Layer();
|
||||||
|
stage.add(layer);
|
||||||
|
|
||||||
const data =
|
const data =
|
||||||
'M419.0000314094981 342.88624187900973 L419.00003140949804 577.0038889378335 L465.014001082264 577.0038889378336 Z';
|
'M419.0000314094981 342.88624187900973 L419.00003140949804 577.0038889378335 L465.014001082264 577.0038889378336 Z';
|
||||||
|
@ -1597,6 +1597,36 @@ describe('Shape', function () {
|
|||||||
compareCanvases(canvas1, canvas2, 240, 110);
|
compareCanvases(canvas1, canvas2, 240, 110);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('check stroke rendering on buffer canvas', async function () {
|
||||||
|
var stage = addStage();
|
||||||
|
|
||||||
|
var layer = new Konva.Layer();
|
||||||
|
stage.add(layer);
|
||||||
|
|
||||||
|
const rect = new Konva.Rect({
|
||||||
|
x: 150,
|
||||||
|
y: 50,
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
fill: '#039BE5',
|
||||||
|
stroke: 'yellow',
|
||||||
|
strokeWidth: 5,
|
||||||
|
shadowColor: 'black',
|
||||||
|
shadowOffset: { x: 10, y: 10 },
|
||||||
|
shadowOpacity: 0.5,
|
||||||
|
});
|
||||||
|
|
||||||
|
layer.add(rect);
|
||||||
|
|
||||||
|
const canvas1 = layer.toCanvas();
|
||||||
|
rect.cache();
|
||||||
|
const canvas2 = layer.toCanvas();
|
||||||
|
|
||||||
|
// throw new Error('stop');
|
||||||
|
|
||||||
|
compareCanvases(canvas1, canvas2);
|
||||||
|
});
|
||||||
|
|
||||||
// ======================================================
|
// ======================================================
|
||||||
it('optional disable shadow for stroke', function () {
|
it('optional disable shadow for stroke', function () {
|
||||||
var stage = addStage();
|
var stage = addStage();
|
||||||
|
@ -131,6 +131,14 @@ export function compareCanvases(canvas1, canvas2, tol?, secondTol?) {
|
|||||||
b.appendChild(canvas2);
|
b.appendChild(canvas2);
|
||||||
c.appendChild(diffCanvas);
|
c.appendChild(diffCanvas);
|
||||||
div.appendChild(b);
|
div.appendChild(b);
|
||||||
|
if (!canvas1.parentNode) {
|
||||||
|
const d = get('div', '<div>Original:</div>');
|
||||||
|
canvas1.style.position = '';
|
||||||
|
canvas1.style.display = '';
|
||||||
|
d.style.float = 'left';
|
||||||
|
d.appendChild(canvas1);
|
||||||
|
div.appendChild(d);
|
||||||
|
}
|
||||||
div.appendChild(c);
|
div.appendChild(c);
|
||||||
getContainer().appendChild(div);
|
getContainer().appendChild(div);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user