mirror of
https://github.com/konvajs/konva.git
synced 2025-09-19 19:07:59 +08:00
added matrix transform caching, and optimized the clear() method. This has improved rendering performance by about 17%
This commit is contained in:
@@ -29,8 +29,6 @@
|
|||||||
contextType = config.contextType || '2d';
|
contextType = config.contextType || '2d';
|
||||||
|
|
||||||
this.pixelRatio = pixelRatio;
|
this.pixelRatio = pixelRatio;
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.element = document.createElement('canvas');
|
this.element = document.createElement('canvas');
|
||||||
this.element.style.padding = 0;
|
this.element.style.padding = 0;
|
||||||
this.element.style.margin = 0;
|
this.element.style.margin = 0;
|
||||||
@@ -62,9 +60,8 @@
|
|||||||
* @param {Number} width
|
* @param {Number} width
|
||||||
*/
|
*/
|
||||||
setWidth: function(width) {
|
setWidth: function(width) {
|
||||||
this.width = width;
|
|
||||||
// take into account pixel ratio
|
// take into account pixel ratio
|
||||||
this.element.width = width * this.pixelRatio;
|
this.width = this.element.width = width * this.pixelRatio;
|
||||||
this.element.style.width = width + 'px';
|
this.element.style.width = width + 'px';
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -74,9 +71,8 @@
|
|||||||
* @param {Number} height
|
* @param {Number} height
|
||||||
*/
|
*/
|
||||||
setHeight: function(height) {
|
setHeight: function(height) {
|
||||||
this.height = height;
|
|
||||||
// take into account pixel ratio
|
// take into account pixel ratio
|
||||||
this.element.height = height * this.pixelRatio;
|
this.height = this.element.height = height * this.pixelRatio;
|
||||||
this.element.style.height = height + 'px';
|
this.element.style.height = height + 'px';
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -127,7 +123,7 @@
|
|||||||
clear: function() {
|
clear: function() {
|
||||||
var context = this.getContext();
|
var context = this.getContext();
|
||||||
var el = this.getElement();
|
var el = this.getElement();
|
||||||
context.clearRect(0, 0, el.width, el.height);
|
context.clearRect(0, 0, this.getWidth(), this.getHeight());
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* to data url
|
* to data url
|
||||||
@@ -226,9 +222,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
_applyAncestorTransforms: function(node) {
|
_applyAncestorTransforms: function(node) {
|
||||||
var context = this.context;
|
var context = this.context,
|
||||||
|
t, m;
|
||||||
|
|
||||||
node._eachAncestorReverse(function(no) {
|
node._eachAncestorReverse(function(no) {
|
||||||
var t = no.getTransform(), m = t.getMatrix();
|
t = no.getTransform(true);
|
||||||
|
m = t.getMatrix();
|
||||||
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||||
}, true);
|
}, true);
|
||||||
},
|
},
|
||||||
|
@@ -199,8 +199,7 @@
|
|||||||
drawScene: function(canvas) {
|
drawScene: function(canvas) {
|
||||||
var layer = this.getLayer(),
|
var layer = this.getLayer(),
|
||||||
clip = !!this.getClipFunc(),
|
clip = !!this.getClipFunc(),
|
||||||
stage = this.getStage(),
|
children, n, len;
|
||||||
children, len;
|
|
||||||
|
|
||||||
if (!canvas && layer) {
|
if (!canvas && layer) {
|
||||||
canvas = layer.getCanvas();
|
canvas = layer.getCanvas();
|
||||||
@@ -214,7 +213,7 @@
|
|||||||
children = this.children;
|
children = this.children;
|
||||||
len = children.length;
|
len = children.length;
|
||||||
|
|
||||||
for(var n = 0; n < len; n++) {
|
for(n = 0; n < len; n++) {
|
||||||
children[n].drawScene(canvas);
|
children[n].drawScene(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
65
src/Node.js
65
src/Node.js
@@ -645,12 +645,7 @@
|
|||||||
}, true);
|
}, true);
|
||||||
return am;
|
return am;
|
||||||
},
|
},
|
||||||
/**
|
_getAndCacheTransform: function() {
|
||||||
* get transform of the node
|
|
||||||
* @name getTransform
|
|
||||||
* @methodOf Kinetic.Node.prototype
|
|
||||||
*/
|
|
||||||
getTransform: function() {
|
|
||||||
var m = new Kinetic.Transform(),
|
var m = new Kinetic.Transform(),
|
||||||
x = this.getX(),
|
x = this.getX(),
|
||||||
y = this.getY(),
|
y = this.getY(),
|
||||||
@@ -675,8 +670,24 @@
|
|||||||
m.translate(-1 * offsetX, -1 * offsetY);
|
m.translate(-1 * offsetX, -1 * offsetY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cache result
|
||||||
|
this.cachedTransform = m;
|
||||||
return m;
|
return m;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* get transform of the node
|
||||||
|
* @name getTransform
|
||||||
|
* @methodOf Kinetic.Node.prototype
|
||||||
|
*/
|
||||||
|
getTransform: function(useCache) {
|
||||||
|
var cachedTransform = this.cachedTransform;
|
||||||
|
if (useCache && cachedTransform) {
|
||||||
|
return cachedTransform;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return this._getAndCacheTransform();
|
||||||
|
}
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* clone node. Returns a new Node instance with identical attributes
|
* clone node. Returns a new Node instance with identical attributes
|
||||||
* @name clone
|
* @name clone
|
||||||
@@ -996,28 +1007,30 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// add getter and setter methods
|
// add getter and setter methods
|
||||||
|
Kinetic.Node.addGetterSetter = function(constructor, arr, def, isTransform) {
|
||||||
Kinetic.Node.addGetterSetter = function(constructor, arr, def) {
|
|
||||||
this.addGetter(constructor, arr, def);
|
this.addGetter(constructor, arr, def);
|
||||||
this.addSetter(constructor, arr);
|
this.addSetter(constructor, arr, isTransform);
|
||||||
};
|
};
|
||||||
Kinetic.Node.addPointGetterSetter = function(constructor, arr, def) {
|
Kinetic.Node.addPointGetterSetter = function(constructor, arr, def, isTransform) {
|
||||||
this.addGetter(constructor, arr, def);
|
this.addGetter(constructor, arr, def);
|
||||||
this.addPointSetter(constructor, arr);
|
this.addPointSetter(constructor, arr, isTransform);
|
||||||
};
|
};
|
||||||
Kinetic.Node.addRotationGetterSetter = function(constructor, arr, def) {
|
Kinetic.Node.addRotationGetterSetter = function(constructor, arr, def, isTransform) {
|
||||||
this.addRotationGetter(constructor, arr, def);
|
this.addRotationGetter(constructor, arr, def);
|
||||||
this.addRotationSetter(constructor, arr);
|
this.addRotationSetter(constructor, arr, isTransform);
|
||||||
};
|
};
|
||||||
Kinetic.Node.addSetter = function(constructor, attr) {
|
Kinetic.Node.addSetter = function(constructor, attr, isTransform) {
|
||||||
var that = this,
|
var that = this,
|
||||||
method = SET + Kinetic.Type._capitalize(attr);
|
method = SET + Kinetic.Type._capitalize(attr);
|
||||||
|
|
||||||
constructor.prototype[method] = function(val) {
|
constructor.prototype[method] = function(val) {
|
||||||
this.setAttr(attr, val);
|
this.setAttr(attr, val);
|
||||||
|
if (isTransform) {
|
||||||
|
this.cachedTransform = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
Kinetic.Node.addPointSetter = function(constructor, attr) {
|
Kinetic.Node.addPointSetter = function(constructor, attr, isTransform) {
|
||||||
var that = this,
|
var that = this,
|
||||||
method = SET + Kinetic.Type._capitalize(attr);
|
method = SET + Kinetic.Type._capitalize(attr);
|
||||||
|
|
||||||
@@ -1036,19 +1049,29 @@
|
|||||||
pos.y = this.attrs[attr].y;
|
pos.y = this.attrs[attr].y;
|
||||||
}
|
}
|
||||||
this.setAttr(attr, pos);
|
this.setAttr(attr, pos);
|
||||||
|
|
||||||
|
if (isTransform) {
|
||||||
|
this.cachedTransform = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
Kinetic.Node.addRotationSetter = function(constructor, attr) {
|
Kinetic.Node.addRotationSetter = function(constructor, attr, isTransform) {
|
||||||
var that = this,
|
var that = this,
|
||||||
method = SET + Kinetic.Type._capitalize(attr);
|
method = SET + Kinetic.Type._capitalize(attr);
|
||||||
|
|
||||||
// radians
|
// radians
|
||||||
constructor.prototype[method] = function(val) {
|
constructor.prototype[method] = function(val) {
|
||||||
this.setAttr(attr, val);
|
this.setAttr(attr, val);
|
||||||
|
if (isTransform) {
|
||||||
|
this.cachedTransform = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// degrees
|
// degrees
|
||||||
constructor.prototype[method + DEG] = function(deg) {
|
constructor.prototype[method + DEG] = function(deg) {
|
||||||
this.setAttr(attr, Kinetic.Type._degToRad(deg));
|
this.setAttr(attr, Kinetic.Type._degToRad(deg));
|
||||||
|
if (isTransform) {
|
||||||
|
this.cachedTransform = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
Kinetic.Node.addGetter = function(constructor, attr, def) {
|
Kinetic.Node.addGetter = function(constructor, attr, def) {
|
||||||
@@ -1134,8 +1157,8 @@
|
|||||||
return no;
|
return no;
|
||||||
};
|
};
|
||||||
// add getters setters
|
// add getters setters
|
||||||
Kinetic.Node.addGetterSetter(Kinetic.Node, 'x', 0);
|
Kinetic.Node.addGetterSetter(Kinetic.Node, 'x', 0, true);
|
||||||
Kinetic.Node.addGetterSetter(Kinetic.Node, 'y', 0);
|
Kinetic.Node.addGetterSetter(Kinetic.Node, 'y', 0, true);
|
||||||
Kinetic.Node.addGetterSetter(Kinetic.Node, 'opacity', 1);
|
Kinetic.Node.addGetterSetter(Kinetic.Node, 'opacity', 1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1194,7 +1217,7 @@
|
|||||||
* @methodOf Kinetic.Node.prototype
|
* @methodOf Kinetic.Node.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Kinetic.Node.addRotationGetterSetter(Kinetic.Node, 'rotation', 0);
|
Kinetic.Node.addRotationGetterSetter(Kinetic.Node, 'rotation', 0, true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set rotation in radians
|
* set rotation in radians
|
||||||
@@ -1222,8 +1245,8 @@
|
|||||||
* @methodOf Kinetic.Node.prototype
|
* @methodOf Kinetic.Node.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Kinetic.Node.addPointGetterSetter(Kinetic.Node, 'scale', {x:1,y:1});
|
Kinetic.Node.addPointGetterSetter(Kinetic.Node, 'scale', {x:1,y:1}, true);
|
||||||
Kinetic.Node.addPointGetterSetter(Kinetic.Node, 'offset', {x:0,y:0});
|
Kinetic.Node.addPointGetterSetter(Kinetic.Node, 'offset', {x:0,y:0}, true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set scale
|
* set scale
|
||||||
|
@@ -178,8 +178,7 @@
|
|||||||
delete Kinetic.Global.shapes[this.colorKey];
|
delete Kinetic.Global.shapes[this.colorKey];
|
||||||
},
|
},
|
||||||
drawScene: function(canvas) {
|
drawScene: function(canvas) {
|
||||||
var attrs = this.getAttrs(),
|
var drawFunc = this.getDrawFunc(),
|
||||||
drawFunc = attrs.drawFunc,
|
|
||||||
canvas = canvas || this.getLayer().getCanvas(),
|
canvas = canvas || this.getLayer().getCanvas(),
|
||||||
context = canvas.getContext();
|
context = canvas.getContext();
|
||||||
|
|
||||||
|
@@ -23,6 +23,38 @@ Test.Modules.NODE = {
|
|||||||
test(circle.getAbsoluteOpacity() === 0.25, 'abs opacity should be 0.25');
|
test(circle.getAbsoluteOpacity() === 0.25, 'abs opacity should be 0.25');
|
||||||
test(layer.getAbsoluteOpacity() === 0.5, 'abs opacity should be 0.5');
|
test(layer.getAbsoluteOpacity() === 0.5, 'abs opacity should be 0.5');
|
||||||
},
|
},
|
||||||
|
'transformation matrix caching': function(containerId) {
|
||||||
|
var stage = new Kinetic.Stage({
|
||||||
|
container: containerId,
|
||||||
|
width: 578,
|
||||||
|
height: 200
|
||||||
|
});
|
||||||
|
var layer = new Kinetic.Layer();
|
||||||
|
var circle = new Kinetic.Circle({
|
||||||
|
x: stage.getWidth() / 2,
|
||||||
|
y: stage.getHeight() / 2,
|
||||||
|
radius: 70,
|
||||||
|
fill: 'green',
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 4
|
||||||
|
});
|
||||||
|
|
||||||
|
test(!circle.cachedTransform, 'circle transform cache should be empty');
|
||||||
|
|
||||||
|
layer.add(circle);
|
||||||
|
stage.add(layer);
|
||||||
|
|
||||||
|
test(circle.cachedTransform, 'circle transform cache should be present');
|
||||||
|
|
||||||
|
circle.setX(100);
|
||||||
|
|
||||||
|
test(!circle.cachedTransform, 'circle transform cache should be empty');
|
||||||
|
|
||||||
|
layer.draw();
|
||||||
|
|
||||||
|
test(circle.cachedTransform, 'circle transform cache should be present');
|
||||||
|
|
||||||
|
},
|
||||||
'test pixel ratio toDataURL': function(containerId) {
|
'test pixel ratio toDataURL': function(containerId) {
|
||||||
var stage = new Kinetic.Stage({
|
var stage = new Kinetic.Stage({
|
||||||
container: containerId,
|
container: containerId,
|
||||||
|
Reference in New Issue
Block a user