mirror of
https://github.com/konvajs/konva.git
synced 2025-09-19 19:07:59 +08:00
first pass at new drawing caching mechanism
This commit is contained in:
@@ -223,7 +223,7 @@
|
||||
this.setAttr('lineJoin', lineJoin);
|
||||
}
|
||||
},
|
||||
_applyAncestorTransforms: function(shape) {
|
||||
_applyTransform: function(shape) {
|
||||
var transformsEnabled = shape.getTransformsEnabled(),
|
||||
m;
|
||||
|
||||
@@ -235,7 +235,6 @@
|
||||
// best performance for position only transforms
|
||||
this.translate(shape.getX(), shape.getY());
|
||||
}
|
||||
|
||||
},
|
||||
_clip: function(container) {
|
||||
var clipX = container.getClipX(),
|
||||
@@ -244,7 +243,7 @@
|
||||
clipHeight = container.getClipHeight();
|
||||
|
||||
this.save();
|
||||
this._applyAncestorTransforms(container);
|
||||
this._applyTransform(container);
|
||||
this.beginPath();
|
||||
this.rect(clipX, clipY, clipWidth, clipHeight);
|
||||
this.clip();
|
||||
|
103
src/Node.js
103
src/Node.js
@@ -109,22 +109,39 @@
|
||||
* node.cache();
|
||||
*/
|
||||
cache: function(box) {
|
||||
var sceneCanvasCache = new Kinetic.SceneCanvas({
|
||||
var x = box.x || 0,
|
||||
y = box.y || 0,
|
||||
sceneCanvasCache = new Kinetic.SceneCanvas({
|
||||
pixelRatio: 1,
|
||||
width: box.width,
|
||||
height: box.height
|
||||
});
|
||||
var hitCanvasCache = new Kinetic.HitCanvas({
|
||||
}),
|
||||
hitCanvasCache = new Kinetic.HitCanvas({
|
||||
pixelRatio: 1,
|
||||
width: box.width,
|
||||
height: box.height
|
||||
});
|
||||
}),
|
||||
origTransEnabled = this.transformsEnabled(),
|
||||
origX = this.x(),
|
||||
origY = this.y();
|
||||
|
||||
this.transformsEnabled('position');
|
||||
this.x(x * -1);
|
||||
this.y(y * -1);
|
||||
|
||||
this.drawScene(sceneCanvasCache);
|
||||
this.drawHit(hitCanvasCache);
|
||||
|
||||
this._cache.sceneCanvas = sceneCanvasCache;
|
||||
this._cache.hitCanvas = hitCanvasCache;
|
||||
this.x(origX);
|
||||
this.y(origY);
|
||||
this.transformsEnabled(origTransEnabled);
|
||||
|
||||
this._cache.canvas = {
|
||||
scene: sceneCanvasCache,
|
||||
hit: hitCanvasCache,
|
||||
x: x,
|
||||
y: y
|
||||
};
|
||||
},
|
||||
/*
|
||||
* the default isDraggable method returns false.
|
||||
@@ -599,14 +616,14 @@
|
||||
* @returns {Kinetic.Node}
|
||||
*/
|
||||
setAbsolutePosition: function(pos) {
|
||||
var trans = this._clearTransform(),
|
||||
var origTrans = this._clearTransform(),
|
||||
it;
|
||||
|
||||
// don't clear translation
|
||||
this.attrs.x = trans.x;
|
||||
this.attrs.y = trans.y;
|
||||
delete trans.x;
|
||||
delete trans.y;
|
||||
this.attrs.x = origTrans.x;
|
||||
this.attrs.y = origTrans.y;
|
||||
delete origTrans.x;
|
||||
delete origTrans.y;
|
||||
|
||||
// unravel transform
|
||||
it = this.getAbsoluteTransform();
|
||||
@@ -619,7 +636,8 @@
|
||||
};
|
||||
|
||||
this.setPosition({x:pos.x, y:pos.y});
|
||||
this._setTransform(trans);
|
||||
this._setTransform(origTrans);
|
||||
|
||||
return this;
|
||||
},
|
||||
_setTransform: function(trans) {
|
||||
@@ -658,6 +676,7 @@
|
||||
this._clearCache(TRANSFORM);
|
||||
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
|
||||
|
||||
// return original transform
|
||||
return trans;
|
||||
},
|
||||
/**
|
||||
@@ -984,6 +1003,7 @@
|
||||
},
|
||||
_getTransform: function() {
|
||||
var m = new Kinetic.Transform(),
|
||||
cachedCanvas = this._cache.canvas,
|
||||
x = this.getX(),
|
||||
y = this.getY(),
|
||||
rotation = this.getRotation(),
|
||||
@@ -994,6 +1014,16 @@
|
||||
offsetX = this.getOffsetX(),
|
||||
offsetY = this.getOffsetY();
|
||||
|
||||
// NOTE: the cached canvas offsets must be handled in this method
|
||||
// because there are situations where we need to access the original
|
||||
// offset positions, i.e. setAbsolutePosition() and drag and drop
|
||||
if (cachedCanvas) {
|
||||
offsetX -= cachedCanvas.x;
|
||||
}
|
||||
if (cachedCanvas) {
|
||||
offsetY -= cachedCanvas.y;
|
||||
}
|
||||
|
||||
if(x !== 0 || y !== 0) {
|
||||
m.translate(x, y);
|
||||
}
|
||||
@@ -1649,61 +1679,36 @@
|
||||
Kinetic.Factory.addPointGetterSetter(Kinetic.Node, 'offset', 0);
|
||||
|
||||
/**
|
||||
* set offset. A node's offset defines the position and rotation point
|
||||
* @name setOffset
|
||||
* get/set offset. A node's offset defines the position and rotation point
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
* @returns {Kinetic.Node}
|
||||
* @param {Object} offset
|
||||
* @param {Number} offset.x
|
||||
* @param {Number} offset.y
|
||||
* @returns {Object}
|
||||
* @example
|
||||
* // set x and y <br>
|
||||
* shape.setOffset({<br>
|
||||
* shape.offset({<br>
|
||||
* x: 20<br>
|
||||
* y: 10<br>
|
||||
* });<br><br>
|
||||
*/
|
||||
|
||||
/**
|
||||
* get offset
|
||||
* @name getOffset
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
/**
|
||||
* set offset x
|
||||
* @name setOffsetX
|
||||
* @method
|
||||
* get/set offset x
|
||||
* @name offsetX
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @param {Number} x
|
||||
* @returns {Kinetic.Node}
|
||||
* @returns {Integer}
|
||||
*/
|
||||
|
||||
/**
|
||||
* get offset x
|
||||
* @name getOffsetX
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
/**
|
||||
* set offset y
|
||||
* @name setOffsetY
|
||||
* get/set offset y
|
||||
* @name offsetY
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @param {Number} y
|
||||
* @returns {Kinetic.Node}
|
||||
*/
|
||||
|
||||
/**
|
||||
* get offset y
|
||||
* @name getOffsetY
|
||||
* @method
|
||||
* @memberof Kinetic.Node.prototype
|
||||
* @returns {Number}
|
||||
* @returns {Integer}
|
||||
*/
|
||||
|
||||
Kinetic.Factory.addSetter(Kinetic.Node, 'width', 0);
|
||||
|
46
src/Shape.js
46
src/Shape.js
@@ -235,28 +235,20 @@
|
||||
drawScene: function(can) {
|
||||
var canvas = can || this.getLayer().getCanvas(),
|
||||
context = canvas.getContext(),
|
||||
cachedCanvas = this._cache.canvas,
|
||||
cachedSceneCanvas = cachedCanvas && cachedCanvas.scene,
|
||||
drawFunc = this.getDrawFunc(),
|
||||
cachedSceneCanvas = this._cache.sceneCanvas;
|
||||
|
||||
if(this.isVisible()) {
|
||||
context.save();
|
||||
// if cache is available
|
||||
if (cachedSceneCanvas) {
|
||||
context.drawImage(cachedSceneCanvas._canvas, 0, 0);
|
||||
}
|
||||
else if (drawFunc) {
|
||||
this._drawScene(context);
|
||||
}
|
||||
context.restore();
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
_drawScene: function(context) {
|
||||
var drawFunc = this.getDrawFunc(),
|
||||
hasShadow = this.hasShadow(),
|
||||
stage, bufferCanvas, bufferContext;
|
||||
|
||||
if(this.isVisible()) {
|
||||
context.save();
|
||||
|
||||
if (cachedSceneCanvas) {
|
||||
context._applyTransform(this);
|
||||
context.drawImage(cachedSceneCanvas._canvas, 0, 0);
|
||||
}
|
||||
else if (drawFunc) {
|
||||
// if buffer canvas is needed
|
||||
if (this._useBufferCanvas()) {
|
||||
stage = this.getStage();
|
||||
@@ -265,7 +257,8 @@
|
||||
bufferContext.clear();
|
||||
bufferContext.save();
|
||||
bufferContext._applyLineJoin(this);
|
||||
bufferContext._applyAncestorTransforms(this);
|
||||
bufferContext._applyTransform(this);
|
||||
|
||||
drawFunc.call(this, bufferContext);
|
||||
bufferContext.restore();
|
||||
|
||||
@@ -282,7 +275,7 @@
|
||||
// if buffer canvas is not needed
|
||||
else {
|
||||
context._applyLineJoin(this);
|
||||
context._applyAncestorTransforms(this);
|
||||
context._applyTransform(this);
|
||||
|
||||
if (hasShadow) {
|
||||
context.save();
|
||||
@@ -294,21 +287,30 @@
|
||||
context._applyOpacity(this);
|
||||
drawFunc.call(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
context.restore();
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
drawHit: function(can) {
|
||||
var canvas = can || this.getLayer().hitCanvas,
|
||||
context = canvas.getContext(),
|
||||
drawFunc = this.getDrawHitFunc() || this.getDrawFunc(),
|
||||
cachedHitCanvas = this._cache.hitCanvas;
|
||||
cachedCanvas = this._cache.canvas,
|
||||
cachedHitCanvas = cachedCanvas && cachedCanvas.hit;
|
||||
|
||||
if(this.shouldDrawHit()) {
|
||||
context.save();
|
||||
if (cachedHitCanvas) {
|
||||
context._applyTransform(this);
|
||||
context.drawImage(cachedHitCanvas._canvas, 0, 0);
|
||||
}
|
||||
else if (drawFunc) {
|
||||
context._applyLineJoin(this);
|
||||
context._applyAncestorTransforms(this);
|
||||
context._applyTransform(this);
|
||||
|
||||
drawFunc.call(this, context);
|
||||
}
|
||||
context.restore();
|
||||
|
@@ -2897,8 +2897,8 @@ suite('Node', function() {
|
||||
var layer = new Kinetic.Layer();
|
||||
var group = new Kinetic.Group();
|
||||
var circle = new Kinetic.Circle({
|
||||
x: 100,
|
||||
y: 100,
|
||||
x: 70,
|
||||
y: 70,
|
||||
radius: 70,
|
||||
fill: 'green',
|
||||
stroke: 'black',
|
||||
@@ -2911,29 +2911,48 @@ suite('Node', function() {
|
||||
layer.add(group);
|
||||
stage.add(layer);
|
||||
|
||||
console.log('-- before cache')
|
||||
|
||||
assert.equal(circle._cache['sceneCanvas'], undefined);
|
||||
assert.equal(circle._cache['hitCanvas'], undefined);
|
||||
assert.equal(circle._cache.canvas, undefined);
|
||||
|
||||
circle.cache({
|
||||
width: 100,
|
||||
height: 100
|
||||
x: -74,
|
||||
y: -74,
|
||||
width: 148,
|
||||
height: 148
|
||||
});
|
||||
|
||||
assert.notEqual(circle._cache['sceneCanvas'], undefined);
|
||||
assert.notEqual(circle._cache['hitCanvas'], undefined);
|
||||
assert.notEqual(circle._cache.canvas.scene, undefined);
|
||||
assert.notEqual(circle._cache.canvas.hit, undefined);
|
||||
assert.equal(circle._cache.canvas.x, -74);
|
||||
assert.equal(circle._cache.canvas.y, -74);
|
||||
|
||||
|
||||
|
||||
layer.draw();
|
||||
|
||||
|
||||
document.body.appendChild(circle._cache.sceneCanvas._canvas);
|
||||
document.body.appendChild(circle._cache.hitCanvas._canvas);
|
||||
//document.body.appendChild(circle._cache.canvas.scene._canvas);
|
||||
// document.body.appendChild(circle._cache.canvas.hit._canvas);
|
||||
|
||||
showHit(layer)
|
||||
|
||||
|
||||
console.log(layer.getContext().getTrace());
|
||||
//console.log(layer.getContext().getTrace());
|
||||
|
||||
assert.equal(layer.getContext().getTrace(), 'clearRect(0,0,578,200);save();transform(1,0,0,1,70,70);beginPath();arc(0,0,70,0,6.283,false);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();clearRect(0,0,578,200);save();transform(1,0,0,1,-4,-4);drawImage([object HTMLCanvasElement],0,0);restore();');
|
||||
|
||||
// setTimeout(function() {
|
||||
// console.log('draw')
|
||||
// layer.draw();
|
||||
// }, 1000)
|
||||
|
||||
// setTimeout(function() {
|
||||
// console.log('draw')
|
||||
// layer.draw();
|
||||
// }, 2000)
|
||||
|
||||
// setTimeout(function() {
|
||||
// console.log('draw')
|
||||
// layer.draw();
|
||||
// }, 3000)
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user