mirror of
https://github.com/konvajs/konva.git
synced 2026-03-03 16:58:33 +08:00
absolute transforms are now cached
This commit is contained in:
@@ -218,6 +218,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
_applyAncestorTransforms: function(node) {
|
_applyAncestorTransforms: function(node) {
|
||||||
|
var m = node.getAbsoluteTransform().getMatrix();
|
||||||
|
this.context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||||
|
|
||||||
|
/*
|
||||||
var context = this.context,
|
var context = this.context,
|
||||||
t, m;
|
t, m;
|
||||||
|
|
||||||
@@ -226,6 +230,7 @@
|
|||||||
m = t.getMatrix();
|
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);
|
||||||
|
*/
|
||||||
},
|
},
|
||||||
_clip: function(container) {
|
_clip: function(container) {
|
||||||
var context = this.getContext();
|
var context = this.getContext();
|
||||||
|
|||||||
120
src/Node.js
120
src/Node.js
@@ -1,6 +1,7 @@
|
|||||||
(function() {
|
(function() {
|
||||||
// CONSTANTS
|
// CONSTANTS
|
||||||
var ADD = 'add',
|
var ABSOLUTE_TRANSFORM = 'absoluteTransform',
|
||||||
|
ADD = 'add',
|
||||||
B = 'b',
|
B = 'b',
|
||||||
BEFORE = 'before',
|
BEFORE = 'before',
|
||||||
BLACK = 'black',
|
BLACK = 'black',
|
||||||
@@ -34,20 +35,29 @@
|
|||||||
UPPER_Y = 'Y',
|
UPPER_Y = 'Y',
|
||||||
VISIBLE = 'visible',
|
VISIBLE = 'visible',
|
||||||
X = 'x',
|
X = 'x',
|
||||||
Y = 'y',
|
Y = 'y';
|
||||||
|
|
||||||
CACHE_MAP = {
|
function _clearTransformCacheEachChild(node) {
|
||||||
x: TRANSFORM,
|
_clearTransformCache.call(node);
|
||||||
y: TRANSFORM,
|
}
|
||||||
rotation: TRANSFORM,
|
function _clearTransformCache() {
|
||||||
rotationDeg: TRANSFORM,
|
this._clearCache(TRANSFORM);
|
||||||
scaleX: TRANSFORM,
|
this._clearCache(ABSOLUTE_TRANSFORM);
|
||||||
scaleY: TRANSFORM,
|
|
||||||
skewX: TRANSFORM,
|
|
||||||
skewY: TRANSFORM,
|
|
||||||
|
|
||||||
visible: VISIBLE
|
if (this.children) {
|
||||||
};
|
this.getChildren().each(_clearTransformCacheEachChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function _clearVisibleCacheEachChild(node) {
|
||||||
|
_clearVisibleCache.call(node);
|
||||||
|
}
|
||||||
|
function _clearVisibleCache() {
|
||||||
|
this._clearCache(VISIBLE);
|
||||||
|
|
||||||
|
if (this.children) {
|
||||||
|
this.getChildren().each(_clearVisibleCacheEachChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Kinetic.Util.addMethods(Kinetic.Node, {
|
Kinetic.Util.addMethods(Kinetic.Node, {
|
||||||
_init: function(config) {
|
_init: function(config) {
|
||||||
@@ -58,10 +68,7 @@
|
|||||||
this.setAttrs(config);
|
this.setAttrs(config);
|
||||||
},
|
},
|
||||||
_clearCache: function(attr){
|
_clearCache: function(attr){
|
||||||
var cacheAttr = CACHE_MAP[attr];
|
delete this.cache[attr];
|
||||||
if (cacheAttr) {
|
|
||||||
delete this.cache[cacheAttr];
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_getCache: function(attr, privateGetter){
|
_getCache: function(attr, privateGetter){
|
||||||
var cache = this.cache[attr];
|
var cache = this.cache[attr];
|
||||||
@@ -234,6 +241,26 @@
|
|||||||
return this.attrs[attr];
|
return this.attrs[attr];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* get ancestors
|
||||||
|
* @method
|
||||||
|
* @memberof Kinetic.Node.prototype
|
||||||
|
* @example
|
||||||
|
* shape.getAncestors().each(function(node) {
|
||||||
|
* console.log(node.getId());
|
||||||
|
* })
|
||||||
|
*/
|
||||||
|
getAncestors: function() {
|
||||||
|
var parent = this.getParent(),
|
||||||
|
ancestors = new Kinetic.Collection();
|
||||||
|
|
||||||
|
while (parent) {
|
||||||
|
ancestors.push(parent);
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ancestors;
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* set attr
|
* set attr
|
||||||
* @method
|
* @method
|
||||||
@@ -758,6 +785,9 @@
|
|||||||
* @memberof Kinetic.Node.prototype
|
* @memberof Kinetic.Node.prototype
|
||||||
*/
|
*/
|
||||||
getAbsoluteTransform: function() {
|
getAbsoluteTransform: function() {
|
||||||
|
return this._getCache(ABSOLUTE_TRANSFORM, this._getAbsoluteTransform);
|
||||||
|
},
|
||||||
|
_getAbsoluteTransform: function() {
|
||||||
// absolute transform
|
// absolute transform
|
||||||
var am = new Kinetic.Transform(),
|
var am = new Kinetic.Transform(),
|
||||||
m;
|
m;
|
||||||
@@ -1153,28 +1183,28 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// getter setter adders
|
// getter setter adders
|
||||||
Kinetic.Node.addGetterSetter = function(constructor, attr, def) {
|
Kinetic.Node.addGetterSetter = function(constructor, attr, def, before) {
|
||||||
this.addGetter(constructor, attr, def);
|
this.addGetter(constructor, attr, def);
|
||||||
this.addSetter(constructor, attr);
|
this.addSetter(constructor, attr, before);
|
||||||
};
|
};
|
||||||
Kinetic.Node.addPointGetterSetter = function(constructor, attr, def) {
|
Kinetic.Node.addPointGetterSetter = function(constructor, attr, def, before) {
|
||||||
this.addPointGetter(constructor, attr);
|
this.addPointGetter(constructor, attr, def);
|
||||||
this.addPointSetter(constructor, attr);
|
this.addPointSetter(constructor, attr, before);
|
||||||
|
|
||||||
// add invdividual component getters and setters
|
// add invdividual component getters and setters
|
||||||
this.addGetter(constructor, attr + UPPER_X, def);
|
this.addGetter(constructor, attr + UPPER_X, def);
|
||||||
this.addGetter(constructor, attr + UPPER_Y, def);
|
this.addGetter(constructor, attr + UPPER_Y, def);
|
||||||
this.addSetter(constructor, attr + UPPER_X);
|
this.addSetter(constructor, attr + UPPER_X, before);
|
||||||
this.addSetter(constructor, attr + UPPER_Y);
|
this.addSetter(constructor, attr + UPPER_Y, before);
|
||||||
};
|
};
|
||||||
Kinetic.Node.addPointsGetterSetter = function(constructor, attr) {
|
Kinetic.Node.addPointsGetterSetter = function(constructor, attr) {
|
||||||
this.addPointsGetter(constructor, attr);
|
this.addPointsGetter(constructor, attr);
|
||||||
this.addPointsSetter(constructor, attr);
|
this.addPointsSetter(constructor, attr);
|
||||||
this.addPointAdder(constructor, attr);
|
this.addPointAdder(constructor, attr);
|
||||||
};
|
};
|
||||||
Kinetic.Node.addRotationGetterSetter = function(constructor, attr, def) {
|
Kinetic.Node.addRotationGetterSetter = function(constructor, attr, def, before) {
|
||||||
this.addRotationGetter(constructor, attr, def);
|
this.addRotationGetter(constructor, attr, def);
|
||||||
this.addRotationSetter(constructor, attr);
|
this.addRotationSetter(constructor, attr, before);
|
||||||
};
|
};
|
||||||
Kinetic.Node.addColorGetterSetter = function(constructor, attr) {
|
Kinetic.Node.addColorGetterSetter = function(constructor, attr) {
|
||||||
this.addGetter(constructor, attr);
|
this.addGetter(constructor, attr);
|
||||||
@@ -1289,16 +1319,17 @@
|
|||||||
this._setAttr('points', points);
|
this._setAttr('points', points);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
Kinetic.Node.addSetter = function(constructor, attr) {
|
Kinetic.Node.addSetter = function(constructor, attr, before) {
|
||||||
var that = this,
|
var method = SET + Kinetic.Util._capitalize(attr);
|
||||||
method = SET + Kinetic.Util._capitalize(attr);
|
|
||||||
|
|
||||||
constructor.prototype[method] = function(val) {
|
constructor.prototype[method] = function(val) {
|
||||||
this._clearCache(attr);
|
if (before) {
|
||||||
|
before.call(this);
|
||||||
|
}
|
||||||
this._setAttr(attr, val);
|
this._setAttr(attr, val);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
Kinetic.Node.addPointSetter = function(constructor, attr) {
|
Kinetic.Node.addPointSetter = function(constructor, attr, before) {
|
||||||
var that = this,
|
var that = this,
|
||||||
baseMethod = SET + Kinetic.Util._capitalize(attr);
|
baseMethod = SET + Kinetic.Util._capitalize(attr);
|
||||||
|
|
||||||
@@ -1313,6 +1344,9 @@
|
|||||||
y = pos.y;
|
y = pos.y;
|
||||||
|
|
||||||
this._fireBeforeChangeEvent(attr, oldVal, pos);
|
this._fireBeforeChangeEvent(attr, oldVal, pos);
|
||||||
|
if (before) {
|
||||||
|
before.call(this);
|
||||||
|
}
|
||||||
if (x !== undefined) {
|
if (x !== undefined) {
|
||||||
this[baseMethod + UPPER_X](x);
|
this[baseMethod + UPPER_X](x);
|
||||||
}
|
}
|
||||||
@@ -1323,18 +1357,22 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
Kinetic.Node.addRotationSetter = function(constructor, attr) {
|
Kinetic.Node.addRotationSetter = function(constructor, attr, before) {
|
||||||
var that = this,
|
var that = this,
|
||||||
method = SET + Kinetic.Util._capitalize(attr);
|
method = SET + Kinetic.Util._capitalize(attr);
|
||||||
|
|
||||||
// radians
|
// radians
|
||||||
constructor.prototype[method] = function(val) {
|
constructor.prototype[method] = function(val) {
|
||||||
this._clearCache(attr);
|
if (before) {
|
||||||
|
before.call(this);
|
||||||
|
}
|
||||||
this._setAttr(attr, val);
|
this._setAttr(attr, val);
|
||||||
};
|
};
|
||||||
// degrees
|
// degrees
|
||||||
constructor.prototype[method + DEG] = function(deg) {
|
constructor.prototype[method + DEG] = function(deg) {
|
||||||
this._clearCache(attr);
|
if (before) {
|
||||||
|
before.call(this);
|
||||||
|
}
|
||||||
this._setAttr(attr, Kinetic.Util._degToRad(deg));
|
this._setAttr(attr, Kinetic.Util._degToRad(deg));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -1394,7 +1432,7 @@
|
|||||||
};
|
};
|
||||||
// add getters setters
|
// add getters setters
|
||||||
|
|
||||||
Kinetic.Node.addGetterSetter(Kinetic.Node, 'x', 0);
|
Kinetic.Node.addGetterSetter(Kinetic.Node, 'x', 0, _clearTransformCache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set x position
|
* set x position
|
||||||
@@ -1411,7 +1449,7 @@
|
|||||||
* @memberof Kinetic.Node.prototype
|
* @memberof Kinetic.Node.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Kinetic.Node.addGetterSetter(Kinetic.Node, 'y', 0);
|
Kinetic.Node.addGetterSetter(Kinetic.Node, 'y', 0, _clearTransformCache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set y position
|
* set y position
|
||||||
@@ -1465,7 +1503,7 @@
|
|||||||
* @memberof Kinetic.Node.prototype
|
* @memberof Kinetic.Node.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Kinetic.Node.addRotationGetterSetter(Kinetic.Node, 'rotation', 0);
|
Kinetic.Node.addRotationGetterSetter(Kinetic.Node, 'rotation', 0, _clearTransformCache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set rotation in radians
|
* set rotation in radians
|
||||||
@@ -1497,7 +1535,7 @@
|
|||||||
* @memberof Kinetic.Node.prototype
|
* @memberof Kinetic.Node.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Kinetic.Node.addPointGetterSetter(Kinetic.Node, 'scale', 1);
|
Kinetic.Node.addPointGetterSetter(Kinetic.Node, 'scale', 1, _clearTransformCache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set scale
|
* set scale
|
||||||
@@ -1558,7 +1596,7 @@
|
|||||||
* @memberof Kinetic.Node.prototype
|
* @memberof Kinetic.Node.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Kinetic.Node.addPointGetterSetter(Kinetic.Node, 'skew', 0);
|
Kinetic.Node.addPointGetterSetter(Kinetic.Node, 'skew', 0, _clearTransformCache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set skew
|
* set skew
|
||||||
@@ -1620,7 +1658,7 @@
|
|||||||
* @memberof Kinetic.Node.prototype
|
* @memberof Kinetic.Node.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Kinetic.Node.addPointGetterSetter(Kinetic.Node, 'offset', 0);
|
Kinetic.Node.addPointGetterSetter(Kinetic.Node, 'offset', 0, _clearTransformCache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set offset. A node's offset defines the position and rotation point
|
* set offset. A node's offset defines the position and rotation point
|
||||||
@@ -1719,7 +1757,7 @@
|
|||||||
* @memberof Kinetic.Node.prototype
|
* @memberof Kinetic.Node.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Kinetic.Node.addSetter(Kinetic.Node, 'visible');
|
Kinetic.Node.addSetter(Kinetic.Node, 'visible', _clearVisibleCache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set visible
|
* set visible
|
||||||
|
|||||||
16
src/Shape.js
16
src/Shape.js
@@ -1,4 +1,6 @@
|
|||||||
(function() {
|
(function() {
|
||||||
|
var HAS_SHADOW = 'hasShadow';
|
||||||
|
|
||||||
function _fillFunc(context) {
|
function _fillFunc(context) {
|
||||||
context.fill();
|
context.fill();
|
||||||
}
|
}
|
||||||
@@ -11,6 +13,9 @@
|
|||||||
function _strokeFuncHit(context) {
|
function _strokeFuncHit(context) {
|
||||||
context.stroke();
|
context.stroke();
|
||||||
}
|
}
|
||||||
|
function _clearHasShadowCache() {
|
||||||
|
this._clearCache(HAS_SHADOW);
|
||||||
|
}
|
||||||
|
|
||||||
Kinetic.Util.addMethods(Kinetic.Shape, {
|
Kinetic.Util.addMethods(Kinetic.Shape, {
|
||||||
__init: function(config) {
|
__init: function(config) {
|
||||||
@@ -67,6 +72,9 @@
|
|||||||
* @memberof Kinetic.Shape.prototype
|
* @memberof Kinetic.Shape.prototype
|
||||||
*/
|
*/
|
||||||
hasShadow: function() {
|
hasShadow: function() {
|
||||||
|
return this._getCache(HAS_SHADOW, this._hasShadow);
|
||||||
|
},
|
||||||
|
_hasShadow: function() {
|
||||||
return (this.getShadowOpacity() !== 0 && !!(this.getShadowColor() || this.getShadowBlur() || this.getShadowOffsetX() || this.getShadowOffsetY()));
|
return (this.getShadowOpacity() !== 0 && !!(this.getShadowColor() || this.getShadowBlur() || this.getShadowOffsetX() || this.getShadowOffsetY()));
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -433,7 +441,7 @@
|
|||||||
* @memberof Kinetic.Shape.prototype
|
* @memberof Kinetic.Shape.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Kinetic.Node.addColorGetterSetter(Kinetic.Shape, 'shadowColor');
|
Kinetic.Node.addColorGetterSetter(Kinetic.Shape, 'shadowColor', undefined, _clearHasShadowCache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set shadow color
|
* set shadow color
|
||||||
@@ -516,7 +524,7 @@
|
|||||||
* @memberof Kinetic.Shape.prototype
|
* @memberof Kinetic.Shape.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Kinetic.Node.addGetterSetter(Kinetic.Shape, 'shadowBlur');
|
Kinetic.Node.addGetterSetter(Kinetic.Shape, 'shadowBlur', undefined, _clearHasShadowCache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set shadow blur
|
* set shadow blur
|
||||||
@@ -533,7 +541,7 @@
|
|||||||
* @memberof Kinetic.Shape.prototype
|
* @memberof Kinetic.Shape.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Kinetic.Node.addGetterSetter(Kinetic.Shape, 'shadowOpacity');
|
Kinetic.Node.addGetterSetter(Kinetic.Shape, 'shadowOpacity', undefined, _clearHasShadowCache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set shadow opacity
|
* set shadow opacity
|
||||||
@@ -1239,7 +1247,7 @@
|
|||||||
* @memberof Kinetic.Shape.prototype
|
* @memberof Kinetic.Shape.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Kinetic.Node.addPointGetterSetter(Kinetic.Shape, 'shadowOffset', 0);
|
Kinetic.Node.addPointGetterSetter(Kinetic.Shape, 'shadowOffset', 0, _clearHasShadowCache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set shadow offset
|
* set shadow offset
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ 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');
|
||||||
},
|
},
|
||||||
'*caching': function(containerId) {
|
'caching': function(containerId) {
|
||||||
var stage = new Kinetic.Stage({
|
var stage = new Kinetic.Stage({
|
||||||
container: containerId,
|
container: containerId,
|
||||||
width: 578,
|
width: 578,
|
||||||
@@ -105,7 +105,7 @@ Test.Modules.NODE = {
|
|||||||
strokeWidth: 4
|
strokeWidth: 4
|
||||||
});
|
});
|
||||||
|
|
||||||
test(!circle.cache.transform, '1) circle transform cache should be empty');
|
test(circle.cache.transform === undefined, '1) circle transform cache should be empty');
|
||||||
|
|
||||||
layer.add(circle);
|
layer.add(circle);
|
||||||
stage.add(layer);
|
stage.add(layer);
|
||||||
@@ -113,7 +113,7 @@ Test.Modules.NODE = {
|
|||||||
// transform cache
|
// transform cache
|
||||||
test(circle.cache.transform, '2) circle transform cache should be primed');
|
test(circle.cache.transform, '2) circle transform cache should be primed');
|
||||||
circle.setX(100);
|
circle.setX(100);
|
||||||
test(!circle.cache.transform, '3) circle transform cache should be empty');
|
test(circle.cache.transform === undefined, '3) circle transform cache should be empty');
|
||||||
layer.draw();
|
layer.draw();
|
||||||
test(circle.cache.transform, '4) circle transform cache should be primed');
|
test(circle.cache.transform, '4) circle transform cache should be primed');
|
||||||
|
|
||||||
@@ -128,6 +128,16 @@ Test.Modules.NODE = {
|
|||||||
stage.draw();
|
stage.draw();
|
||||||
test(circle.cache.visible === true, '9) circle visible cache should be primed');
|
test(circle.cache.visible === true, '9) circle visible cache should be primed');
|
||||||
|
|
||||||
|
// shadow cache
|
||||||
|
test(circle.cache.hasShadow === false, '10) circle shadow cache should be primed');
|
||||||
|
circle.setShadowColor('red');
|
||||||
|
circle.setShadowOffset(10);
|
||||||
|
test(circle.cache.hasShadow === undefined, '11) circle shadow cache should be empty');
|
||||||
|
layer.draw();
|
||||||
|
test(circle.cache.hasShadow === true, '12) circle shadow cache should be primed');
|
||||||
|
layer.draw();
|
||||||
|
test(circle.cache.hasShadow === true, '13) circle shadow cache should still be primed after redraw');
|
||||||
|
|
||||||
},
|
},
|
||||||
'test pixel ratio toDataURL': function(containerId) {
|
'test pixel ratio toDataURL': function(containerId) {
|
||||||
var stage = new Kinetic.Stage({
|
var stage = new Kinetic.Stage({
|
||||||
|
|||||||
Reference in New Issue
Block a user