perf optimizations

This commit is contained in:
Anton Lavrenov
2020-06-16 16:20:36 -05:00
parent e22a98d656
commit 0fe8e7fb7f
7 changed files with 126 additions and 39 deletions

View File

@@ -2644,6 +2644,7 @@
this.index = 0; this.index = 0;
this.parent = null; this.parent = null;
this._cache = new Map(); this._cache = new Map();
this._attachedDepsListeners = new Map();
this._lastPos = null; this._lastPos = null;
this._batchingTransformChange = false; this._batchingTransformChange = false;
this._needClearTransformCache = false; this._needClearTransformCache = false;
@@ -2706,6 +2707,20 @@
} }
return cache; return cache;
}; };
Node.prototype._calculate = function (name, deps, getter) {
var _this = this;
// if we are trying to calculate function for the first time
// we need to attach listeners for change events
if (!this._attachedDepsListeners.get(name)) {
var depsString = deps.map(function (dep) { return dep + 'Change.konva'; }).join(SPACE);
this.on(depsString, function () {
_this._clearCache(name);
});
this._attachedDepsListeners.set(name, true);
}
// just use cache function
return this._getCache(name, getter);
};
Node.prototype._getCanvasCache = function () { Node.prototype._getCanvasCache = function () {
return this._cache.get(CANVAS); return this._cache.get(CANVAS);
}; };
@@ -4044,6 +4059,9 @@
Node.prototype._getTransform = function () { Node.prototype._getTransform = function () {
var m = this._cache.get(TRANSFORM) || new Transform(); var m = this._cache.get(TRANSFORM) || new Transform();
m.reset(); m.reset();
// I was trying to use attributes directly here
// but it doesn't work for Transformer well
// because it overwrite x,y getters
var x = this.x(), y = this.y(), rotation = Konva.getAngle(this.rotation()), scaleX = this.scaleX(), scaleY = this.scaleY(), skewX = this.skewX(), skewY = this.skewY(), offsetX = this.offsetX(), offsetY = this.offsetY(); var x = this.x(), y = this.y(), rotation = Konva.getAngle(this.rotation()), scaleX = this.scaleX(), scaleY = this.scaleY(), skewX = this.skewX(), skewY = this.skewY(), offsetX = this.offsetX(), offsetY = this.offsetY();
if (x !== 0 || y !== 0) { if (x !== 0 || y !== 0) {
m.translate(x, y); m.translate(x, y);
@@ -6964,11 +6982,20 @@
* @returns {Boolean} * @returns {Boolean}
*/ */
Shape.prototype.hasFill = function () { Shape.prototype.hasFill = function () {
return (this.fillEnabled() && var _this = this;
!!(this.fill() || return this._calculate('hasFill', [
this.fillPatternImage() || 'fillEnabled',
this.fillLinearGradientColorStops() || 'fill',
this.fillRadialGradientColorStops())); 'fillPatternImage',
'fillLinearGradientColorStops',
'fillRadialGradientColorStops',
], function () {
return (_this.fillEnabled() &&
!!(_this.fill() ||
_this.fillPatternImage() ||
_this.fillLinearGradientColorStops() ||
_this.fillRadialGradientColorStops()));
});
}; };
/** /**
* returns whether or not the shape will be stroked * returns whether or not the shape will be stroked
@@ -6977,11 +7004,25 @@
* @returns {Boolean} * @returns {Boolean}
*/ */
Shape.prototype.hasStroke = function () { Shape.prototype.hasStroke = function () {
return (this.strokeEnabled() && var _this = this;
this.strokeWidth() && return this._calculate('hasStroke', [
!!(this.stroke() || this.strokeLinearGradientColorStops()) 'strokeEnabled',
// this.getStrokeRadialGradientColorStops() 'strokeWidth',
); 'stroke',
'strokeLinearGradientColorStops',
], function () {
return (_this.strokeEnabled() &&
_this.strokeWidth() &&
!!(_this.stroke() || _this.strokeLinearGradientColorStops())
// this.getStrokeRadialGradientColorStops()
);
});
// return (
// this.strokeEnabled() &&
// this.strokeWidth() &&
// !!(this.stroke() || this.strokeLinearGradientColorStops())
// // this.getStrokeRadialGradientColorStops()
// );
}; };
Shape.prototype.hasHitStroke = function () { Shape.prototype.hasHitStroke = function () {
var width = this.hitStrokeWidth(); var width = this.hitStrokeWidth();
@@ -14806,7 +14847,7 @@
var lastPos; var lastPos;
node.on("dragstart." + EVENTS_NAME, function (e) { node.on("dragstart." + EVENTS_NAME, function (e) {
lastPos = node.getAbsolutePosition(); lastPos = node.getAbsolutePosition();
_this.fire('dragstart', e); // this.fire('dragstart', e);
}); });
node.on("dragmove." + EVENTS_NAME, function (e) { node.on("dragmove." + EVENTS_NAME, function (e) {
if (!lastPos) { if (!lastPos) {
@@ -14828,12 +14869,10 @@
y: otherAbs.y + dy, y: otherAbs.y + dy,
}); });
otherNode.startDrag(); otherNode.startDrag();
// TODO: how to trigger event after all nodes are dragged?
_this.fire('dragmove', e);
});
node.on("dragend." + EVENTS_NAME, function (e) {
_this.fire('dragend', e);
}); });
// node.on(`dragend.${EVENTS_NAME}`, (e) => {
// this.fire('dragend', e);
// });
lastPos = null; lastPos = null;
}); });
}; };

2
konva.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -197,6 +197,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
index = 0; index = 0;
parent: Container<Node> | null = null; parent: Container<Node> | null = null;
_cache: Map<string, any> = new Map<string, any>(); _cache: Map<string, any> = new Map<string, any>();
_attachedDepsListeners: Map<string, boolean> = new Map<string, boolean>();
_lastPos: Vector2d = null; _lastPos: Vector2d = null;
_attrsAffectingSize!: string[]; _attrsAffectingSize!: string[];
_batchingTransformChange = false; _batchingTransformChange = false;
@@ -273,6 +274,21 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
return cache; return cache;
} }
_calculate(name, deps, getter) {
// if we are trying to calculate function for the first time
// we need to attach listeners for change events
if (!this._attachedDepsListeners.get(name)) {
const depsString = deps.map((dep) => dep + 'Change.konva').join(SPACE);
this.on(depsString, () => {
this._clearCache(name);
});
this._attachedDepsListeners.set(name, true);
}
// just use cache function
return this._getCache(name, getter);
}
_getCanvasCache() { _getCanvasCache() {
return this._cache.get(CANVAS); return this._cache.get(CANVAS);
} }
@@ -1786,6 +1802,9 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
var m: Transform = this._cache.get(TRANSFORM) || new Transform(); var m: Transform = this._cache.get(TRANSFORM) || new Transform();
m.reset(); m.reset();
// I was trying to use attributes directly here
// but it doesn't work for Transformer well
// because it overwrite x,y getters
var x = this.x(), var x = this.x(),
y = this.y(), y = this.y(),
rotation = Konva.getAngle(this.rotation()), rotation = Konva.getAngle(this.rotation()),

View File

@@ -351,14 +351,26 @@ export class Shape<Config extends ShapeConfig = ShapeConfig> extends Node<
* @returns {Boolean} * @returns {Boolean}
*/ */
hasFill() { hasFill() {
return ( return this._calculate(
this.fillEnabled() && 'hasFill',
!!( [
this.fill() || 'fillEnabled',
this.fillPatternImage() || 'fill',
this.fillLinearGradientColorStops() || 'fillPatternImage',
this.fillRadialGradientColorStops() 'fillLinearGradientColorStops',
) 'fillRadialGradientColorStops',
],
() => {
return (
this.fillEnabled() &&
!!(
this.fill() ||
this.fillPatternImage() ||
this.fillLinearGradientColorStops() ||
this.fillRadialGradientColorStops()
)
);
}
); );
} }
/** /**
@@ -368,12 +380,29 @@ export class Shape<Config extends ShapeConfig = ShapeConfig> extends Node<
* @returns {Boolean} * @returns {Boolean}
*/ */
hasStroke() { hasStroke() {
return ( return this._calculate(
this.strokeEnabled() && 'hasStroke',
this.strokeWidth() && [
!!(this.stroke() || this.strokeLinearGradientColorStops()) 'strokeEnabled',
// this.getStrokeRadialGradientColorStops() 'strokeWidth',
'stroke',
'strokeLinearGradientColorStops',
],
() => {
return (
this.strokeEnabled() &&
this.strokeWidth() &&
!!(this.stroke() || this.strokeLinearGradientColorStops())
// this.getStrokeRadialGradientColorStops()
);
}
); );
// return (
// this.strokeEnabled() &&
// this.strokeWidth() &&
// !!(this.stroke() || this.strokeLinearGradientColorStops())
// // this.getStrokeRadialGradientColorStops()
// );
} }
hasHitStroke() { hasHitStroke() {
const width = this.hitStrokeWidth(); const width = this.hitStrokeWidth();

View File

@@ -316,7 +316,7 @@ export class Transformer extends Group {
let lastPos; let lastPos;
node.on(`dragstart.${EVENTS_NAME}`, (e) => { node.on(`dragstart.${EVENTS_NAME}`, (e) => {
lastPos = node.getAbsolutePosition(); lastPos = node.getAbsolutePosition();
this.fire('dragstart', e); // this.fire('dragstart', e);
}); });
node.on(`dragmove.${EVENTS_NAME}`, (e) => { node.on(`dragmove.${EVENTS_NAME}`, (e) => {
if (!lastPos) { if (!lastPos) {
@@ -338,12 +338,10 @@ export class Transformer extends Group {
y: otherAbs.y + dy, y: otherAbs.y + dy,
}); });
otherNode.startDrag(); otherNode.startDrag();
// TODO: how to trigger event after all nodes are dragged?
this.fire('dragmove', e);
});
node.on(`dragend.${EVENTS_NAME}`, (e) => {
this.fire('dragend', e);
}); });
// node.on(`dragend.${EVENTS_NAME}`, (e) => {
// this.fire('dragend', e);
// });
lastPos = null; lastPos = null;
}); });
} }

View File

@@ -92,6 +92,7 @@
transformsEnabled: 'position', transformsEnabled: 'position',
x: 10, x: 10,
y: 10, y: 10,
perfectDrawEnabled: false,
}); });
bunny.speedX = Math.random() * 10; bunny.speedX = Math.random() * 10;
@@ -122,6 +123,7 @@
transformsEnabled: 'position', transformsEnabled: 'position',
x: 0, x: 0,
y: 0, y: 0,
perfectDrawEnabled: false,
}); });
bunny.speedX = Math.random() * 10; bunny.speedX = Math.random() * 10;
bunny.speedY = Math.random() * 10 - 5; bunny.speedY = Math.random() * 10 - 5;

View File

@@ -3861,9 +3861,9 @@ suite('Transformer', function () {
// proxy drag to other nodes // proxy drag to other nodes
assert.equal(rect2.x(), 105); assert.equal(rect2.x(), 105);
assert.equal(rect2.y(), 105); assert.equal(rect2.y(), 105);
assert.equal(dragstart, 2); assert.equal(dragstart, 1);
assert.equal(dragmove, 2); assert.equal(dragmove, 1);
assert.equal(dragend, 2); assert.equal(dragend, 1);
}); });
test('reattach from several and drag one', function () { test('reattach from several and drag one', function () {