mirror of
https://github.com/konvajs/konva.git
synced 2025-12-19 10:58:20 +08:00
perf optimizations
This commit is contained in:
71
konva.js
71
konva.js
@@ -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
2
konva.min.js
vendored
File diff suppressed because one or more lines are too long
19
src/Node.ts
19
src/Node.ts
@@ -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()),
|
||||||
|
|||||||
55
src/Shape.ts
55
src/Shape.ts
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 () {
|
||||||
|
|||||||
Reference in New Issue
Block a user