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