you can now cache regions of a node outside of the stage viewport. added more unit tests

This commit is contained in:
Eric Rowell 2012-07-21 15:38:25 -07:00
parent d74ec8ab06
commit f1cb695e1f
8 changed files with 176 additions and 102 deletions

72
dist/kinetic-core.js vendored
View File

@ -1433,25 +1433,34 @@ Kinetic.Node = Kinetic.Class.extend({
* level as quality (range 0.0 - 1.0) * level as quality (range 0.0 - 1.0)
* @name toDataURL * @name toDataURL
* @methodOf Kinetic.Node.prototype * @methodOf Kinetic.Node.prototype
* @param {String} [mimeType] * @param {Object} config
* @param {Number} [quality]
*/ */
toDataURL: function(mimeType, quality) { toDataURL: function(config) {
var bufferCanvas = this.getStage().bufferCanvas; var mimeType = config && config.mimeType ? config.mimeType : null;
var bufferContext = bufferCanvas.getContext(); var quality = config && config.quality ? config.quality : null;
bufferCanvas.clear(); var canvas;
this._draw(bufferCanvas); if(config && config.width && config.height) {
return bufferCanvas.toDataURL(mimeType, quality); canvas = new Kinetic.Canvas(config.width, config.height);
}
else {
canvas = this.getStage().bufferCanvas;
}
var context = canvas.getContext();
canvas.clear();
this._draw(canvas);
return canvas.toDataURL(mimeType, quality);
}, },
/** /**
* converts node into an image. Since the toImage * converts node into an image. Since the toImage
* method is asynchronous, a callback is required * method is asynchronous, a callback is required
* @name toImage * @name toImage
* @methodOf Kinetic.Stage.prototype * @methodOf Kinetic.Stage.prototype
* @param {Object} config
*/ */
toImage: function(callback) { toImage: function(config) {
Kinetic.Type._getImage(this.toDataURL(), function(img) { Kinetic.Type._getImage(this.toDataURL(config), function(img) {
callback(img); config.callback(img);
}); });
}, },
_clearTransform: function() { _clearTransform: function() {
@ -2344,17 +2353,19 @@ Kinetic.Stage = Kinetic.Container.extend({
* the current state of each node * the current state of each node
* @name toDataURL * @name toDataURL
* @methodOf Kinetic.Stage.prototype * @methodOf Kinetic.Stage.prototype
* @param {Function} callback * @param {Object} config
* @param {String} [mimeType]
* @param {Number} [quality]
*/ */
toDataURL: function(callback, mimeType, quality) { toDataURL: function(config) {
var mimeType = config && config.mimeType ? config.mimeType : null;
var quality = config && config.quality ? config.quality : null;
/* /*
* need to create a canvas element rather than using the buffer canvas * need to create a canvas element rather than using the buffer canvas
* because this method is asynchonous which means that other parts of the * because this method is asynchonous which means that other parts of the
* code could modify the buffer canvas before it's finished * code could modify the buffer canvas before it's finished
*/ */
var canvas = new Kinetic.Canvas(this.attrs.width, this.attrs.height); var width = config && config.width ? config.width : this.attrs.width;
var height = config && config.height ? config.height : this.attrs.height;
var canvas = new Kinetic.Canvas(width, height);
var context = canvas.getContext(); var context = canvas.getContext();
var layers = this.children; var layers = this.children;
@ -2369,7 +2380,7 @@ Kinetic.Stage = Kinetic.Container.extend({
drawLayer(n + 1); drawLayer(n + 1);
} }
else { else {
callback(canvas.toDataURL(mimeType, quality)); config.callback(canvas.toDataURL(mimeType, quality));
} }
}; };
imageObj.src = layerUrl; imageObj.src = layerUrl;
@ -2381,13 +2392,15 @@ Kinetic.Stage = Kinetic.Container.extend({
* is asynchronous, a callback function is required * is asynchronous, a callback function is required
* @name toImage * @name toImage
* @methodOf Kinetic.Stage.prototype * @methodOf Kinetic.Stage.prototype
* @param {Function} callback * @param {Object} config
*/ */
toImage: function(callback) { toImage: function(config) {
this.toDataURL(function(dataUrl) { this.toDataURL({
callback: function(dataUrl) {
Kinetic.Type._getImage(dataUrl, function(img) { Kinetic.Type._getImage(dataUrl, function(img) {
callback(img); config.callback(img);
}); });
}
}); });
}, },
_resizeDOM: function() { _resizeDOM: function() {
@ -3157,11 +3170,20 @@ Kinetic.Layer = Kinetic.Container.extend({
* the current state of each child node * the current state of each child node
* @name toDataURL * @name toDataURL
* @methodOf Kinetic.Layer.prototype * @methodOf Kinetic.Layer.prototype
* @param {String} [mimeType] * @param {Object} config
* @param {Number} [quality]
*/ */
toDataURL: function(mimeType, quality) { toDataURL: function(config) {
return this.getCanvas().toDataURL(mimeType, quality); var canvas;
var mimeType = config && config.mimeType ? config.mimeType : null;
var quality = config && config.quality ? config.quality : null;
if(config && config.width && config.height) {
canvas = new Kinetic.Canvas(config.width, config.height);
}
else {
canvas = this.getCanvas();
}
return canvas.toDataURL(mimeType, quality);
}, },
/** /**
* private draw children * private draw children

File diff suppressed because one or more lines are too long

View File

@ -102,11 +102,20 @@ Kinetic.Layer = Kinetic.Container.extend({
* the current state of each child node * the current state of each child node
* @name toDataURL * @name toDataURL
* @methodOf Kinetic.Layer.prototype * @methodOf Kinetic.Layer.prototype
* @param {String} [mimeType] * @param {Object} config
* @param {Number} [quality]
*/ */
toDataURL: function(mimeType, quality) { toDataURL: function(config) {
return this.getCanvas().toDataURL(mimeType, quality); var canvas;
var mimeType = config && config.mimeType ? config.mimeType : null;
var quality = config && config.quality ? config.quality : null;
if(config && config.width && config.height) {
canvas = new Kinetic.Canvas(config.width, config.height);
}
else {
canvas = this.getCanvas();
}
return canvas.toDataURL(mimeType, quality);
}, },
/** /**
* private draw children * private draw children

View File

@ -826,25 +826,34 @@ Kinetic.Node = Kinetic.Class.extend({
* level as quality (range 0.0 - 1.0) * level as quality (range 0.0 - 1.0)
* @name toDataURL * @name toDataURL
* @methodOf Kinetic.Node.prototype * @methodOf Kinetic.Node.prototype
* @param {String} [mimeType] * @param {Object} config
* @param {Number} [quality]
*/ */
toDataURL: function(mimeType, quality) { toDataURL: function(config) {
var bufferCanvas = this.getStage().bufferCanvas; var mimeType = config && config.mimeType ? config.mimeType : null;
var bufferContext = bufferCanvas.getContext(); var quality = config && config.quality ? config.quality : null;
bufferCanvas.clear(); var canvas;
this._draw(bufferCanvas); if(config && config.width && config.height) {
return bufferCanvas.toDataURL(mimeType, quality); canvas = new Kinetic.Canvas(config.width, config.height);
}
else {
canvas = this.getStage().bufferCanvas;
}
var context = canvas.getContext();
canvas.clear();
this._draw(canvas);
return canvas.toDataURL(mimeType, quality);
}, },
/** /**
* converts node into an image. Since the toImage * converts node into an image. Since the toImage
* method is asynchronous, a callback is required * method is asynchronous, a callback is required
* @name toImage * @name toImage
* @methodOf Kinetic.Stage.prototype * @methodOf Kinetic.Stage.prototype
* @param {Object} config
*/ */
toImage: function(callback) { toImage: function(config) {
Kinetic.Type._getImage(this.toDataURL(), function(img) { Kinetic.Type._getImage(this.toDataURL(config), function(img) {
callback(img); config.callback(img);
}); });
}, },
_clearTransform: function() { _clearTransform: function() {

View File

@ -283,17 +283,19 @@ Kinetic.Stage = Kinetic.Container.extend({
* the current state of each node * the current state of each node
* @name toDataURL * @name toDataURL
* @methodOf Kinetic.Stage.prototype * @methodOf Kinetic.Stage.prototype
* @param {Function} callback * @param {Object} config
* @param {String} [mimeType]
* @param {Number} [quality]
*/ */
toDataURL: function(callback, mimeType, quality) { toDataURL: function(config) {
var mimeType = config && config.mimeType ? config.mimeType : null;
var quality = config && config.quality ? config.quality : null;
/* /*
* need to create a canvas element rather than using the buffer canvas * need to create a canvas element rather than using the buffer canvas
* because this method is asynchonous which means that other parts of the * because this method is asynchonous which means that other parts of the
* code could modify the buffer canvas before it's finished * code could modify the buffer canvas before it's finished
*/ */
var canvas = new Kinetic.Canvas(this.attrs.width, this.attrs.height); var width = config && config.width ? config.width : this.attrs.width;
var height = config && config.height ? config.height : this.attrs.height;
var canvas = new Kinetic.Canvas(width, height);
var context = canvas.getContext(); var context = canvas.getContext();
var layers = this.children; var layers = this.children;
@ -308,7 +310,7 @@ Kinetic.Stage = Kinetic.Container.extend({
drawLayer(n + 1); drawLayer(n + 1);
} }
else { else {
callback(canvas.toDataURL(mimeType, quality)); config.callback(canvas.toDataURL(mimeType, quality));
} }
}; };
imageObj.src = layerUrl; imageObj.src = layerUrl;
@ -320,13 +322,15 @@ Kinetic.Stage = Kinetic.Container.extend({
* is asynchronous, a callback function is required * is asynchronous, a callback function is required
* @name toImage * @name toImage
* @methodOf Kinetic.Stage.prototype * @methodOf Kinetic.Stage.prototype
* @param {Function} callback * @param {Object} config
*/ */
toImage: function(callback) { toImage: function(config) {
this.toDataURL(function(dataUrl) { this.toDataURL({
callback: function(dataUrl) {
Kinetic.Type._getImage(dataUrl, function(img) { Kinetic.Type._getImage(dataUrl, function(img) {
callback(img); config.callback(img);
}); });
}
}); });
}, },
_resizeDOM: function() { _resizeDOM: function() {

File diff suppressed because one or more lines are too long

View File

@ -124,7 +124,8 @@ Test.prototype.tests = {
stage.add(layer); stage.add(layer);
console.log('call toImage') console.log('call toImage')
star.toImage(function(img) { star.toImage({
callback: function(img) {
startTimer(); startTimer();
for(var n = 0; n < 1000; n++) { for(var n = 0; n < 1000; n++) {
var image = new Kinetic.Image({ var image = new Kinetic.Image({
@ -140,6 +141,7 @@ Test.prototype.tests = {
layer.draw(); layer.draw();
endTimer('draw 1,000 cached stars'); endTimer('draw 1,000 cached stars');
}
}); });
} }
}; };

View File

@ -1040,9 +1040,11 @@ Test.prototype.tests = {
layer.draw(); layer.draw();
} }
stage.toDataURL(function(dataUrl) { stage.toDataURL({
callback: function(dataUrl) {
warn(urls[0] === dataUrl, 'stage data url is incorrect'); warn(urls[0] === dataUrl, 'stage data url is incorrect');
}) }
});
warn(urls[0] === layer.toDataURL(), 'layer data url is incorrect'); warn(urls[0] === layer.toDataURL(), 'layer data url is incorrect');
warn(urls[1] === group.toDataURL(), 'group data url is incorrect'); warn(urls[1] === group.toDataURL(), 'group data url is incorrect');
warn(urls[1] === circle.toDataURL(), 'shape data url is incorrect'); warn(urls[1] === circle.toDataURL(), 'shape data url is incorrect');
@ -2227,7 +2229,8 @@ Test.prototype.tests = {
}; };
imageObj.src = '../assets/scorpion-sprite.png'; imageObj.src = '../assets/scorpion-sprite.png';
}, },
'Node - shape caching': function(containerId) { 'Node - node caching': function(containerId) {
var urls = dataUrls['Node - node caching'];
var stage = new Kinetic.Stage({ var stage = new Kinetic.Stage({
container: containerId, container: containerId,
width: 578, width: 578,
@ -2238,7 +2241,7 @@ Test.prototype.tests = {
var points = [{ var points = [{
x: 73, x: 73,
y: 192 y: 250
}, { }, {
x: 73, x: 73,
y: 160 y: 160
@ -2260,24 +2263,50 @@ Test.prototype.tests = {
points: points, points: points,
fill: 'green', fill: 'green',
stroke: 'blue', stroke: 'blue',
strokeWidth: 5 strokeWidth: 5,
draggable: true
}); });
group.add(poly); group.add(poly);
layer.add(group); layer.add(group);
stage.add(layer); stage.add(layer);
poly.toImage(function(imageObj) { poly.toImage({
width: 500,
height: 300,
callback: function(imageObj) {
test(Kinetic.Type._isElement(imageObj), 'shape toImage() should be an image object'); test(Kinetic.Type._isElement(imageObj), 'shape toImage() should be an image object');
var cachedShape = new Kinetic.Image({
image: imageObj,
draggable: true,
stroke: 'red',
strokeWidth: 5,
x: 50,
y: -120
}); });
group.toImage(function(imageObj) {
layer.add(cachedShape);
layer.draw();
warn(urls[0] === layer.toDataURL(), 'layer data url is incorrect');
}
});
group.toImage({
callback: function(imageObj) {
test(Kinetic.Type._isElement(imageObj), 'group toImage() should be an image object'); test(Kinetic.Type._isElement(imageObj), 'group toImage() should be an image object');
}
}); });
layer.toImage(function(imageObj) { layer.toImage({
callback: function(imageObj) {
test(Kinetic.Type._isElement(imageObj), 'layer toImage() should be an image object'); test(Kinetic.Type._isElement(imageObj), 'layer toImage() should be an image object');
}
}); });
stage.toImage(function(imageObj) { stage.toImage({
callback: function(imageObj) {
test(Kinetic.Type._isElement(imageObj), 'stage toImage() should be an image object'); test(Kinetic.Type._isElement(imageObj), 'stage toImage() should be an image object');
}
}); });
}, },
'SHAPE - add polygon': function(containerId) { 'SHAPE - add polygon': function(containerId) {