worked through some synchronous / asynchronous issues with toDataURL and toImage(). stage toDataURL() is now asynchronous, and all other node toDataURLs is still synchronous. toImage() is now asynchronous. Kinetic.Image once again only accepts image objects, and can no longer be instantiated with a data URL or image data due to asynchronous issues. It's much cleaner for the developer to load an image however they like, and then instantiate a Kinetic.Image shape synchronously

This commit is contained in:
Eric Rowell
2012-07-15 20:12:18 -07:00
parent acc6b6e14e
commit 384a686740
11 changed files with 233 additions and 267 deletions

119
dist/kinetic-core.js vendored
View File

@@ -277,21 +277,28 @@ Kinetic.Type = {
/* /*
* arg can be an image object or image data * arg can be an image object or image data
*/ */
_getImage: function(arg) { _getImage: function(arg, callback) {
// if arg is already an image object, just return it // if arg is null or undefined
if(this._isElement(arg)) { if(!arg) {
return arg; callback(null);
}
// if arg is already an image object
else if(this._isElement(arg)) {
callback(arg);
} }
// if arg is a string, then it's a data url // if arg is a string, then it's a data url
if(this._isString(arg)) { else if(this._isString(arg)) {
var imageObj = new Image(); var imageObj = new Image();
imageObj.onload = function() {
callback(imageObj);
}
imageObj.src = arg; imageObj.src = arg;
return imageObj;
} }
//if arg is an object that contains the data property, it's an image object //if arg is an object that contains the data property, it's an image object
if(arg.data) { else if(arg.data) {
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
canvas.width = arg.width; canvas.width = arg.width;
canvas.height = arg.height; canvas.height = arg.height;
@@ -299,12 +306,15 @@ Kinetic.Type = {
context.putImageData(arg, 0, 0); context.putImageData(arg, 0, 0);
var dataUrl = canvas.toDataURL(); var dataUrl = canvas.toDataURL();
var imageObj = new Image(); var imageObj = new Image();
imageObj.onload = function() {
callback(imageObj);
}
imageObj.src = dataUrl; imageObj.src = dataUrl;
return imageObj;
} }
// default else {
return null; callback(null);
}
} }
}; };
@@ -717,10 +727,6 @@ Kinetic.Node = Kinetic.Class.extend({
that._setAttr(obj[key], 'width', size.width); that._setAttr(obj[key], 'width', size.width);
that._setAttr(obj[key], 'height', size.height); that._setAttr(obj[key], 'height', size.height);
break; break;
case 'image':
var img = type._getImage(val);
that._setAttr(obj, key, img);
break;
default: default:
that._setAttr(obj, key, val); that._setAttr(obj, key, val);
break; break;
@@ -1320,10 +1326,15 @@ Kinetic.Node = Kinetic.Class.extend({
} }
}, },
/** /**
* to image * converts node into an image. Since the toImage
* method is asynchronous, a callback is required
* @name toImage
* @methodOf Kinetic.Stage.prototype
*/ */
toImage: function() { toImage: function(callback) {
return Kinetic.Type._getImage(this.toDataURL()); Kinetic.Type._getImage(this.toDataURL(), function(img) {
callback(img);
});
}, },
_setImageData: function(imageData) { _setImageData: function(imageData) {
if(imageData && imageData.data) { if(imageData && imageData.data) {
@@ -2190,7 +2201,8 @@ Kinetic.Stage = Kinetic.Container.extend({
return this.content; return this.content;
}, },
/** /**
* Creates a composite data URL. If MIME type is not * Creates a composite data URL and requires a callback because the stage
* toDataURL method is asynchronous. If MIME type is not
* specified, then "image/png" will result. For "image/jpeg", specify a quality * specified, then "image/png" will result. For "image/jpeg", specify a quality
* level as quality (range 0.0 - 1.0). Note that this method works * level as quality (range 0.0 - 1.0). Note that this method works
* differently from toDataURL() for other nodes because it generates an absolute dataURL * differently from toDataURL() for other nodes because it generates an absolute dataURL
@@ -2198,17 +2210,28 @@ 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 {String} [mimeType] * @param {String} [mimeType]
* @param {Number} [quality] * @param {Number} [quality]
*/ */
toDataURL: function(mimeType, quality) { toDataURL: function(callback, mimeType, quality) {
var bufferLayer = this.bufferLayer; /*
var bufferCanvas = bufferLayer.getCanvas(); * we need to create a temp layer rather than using
var bufferContext = bufferLayer.getContext(); * the bufferLayer because the stage toDataURL method
var layers = this.children; * is asynchronous, which means that other parts of the
bufferLayer.clear(); * code base could be updating or clearing the bufferLayer
* while the stage toDataURL method is processing
*/
var tempLayer = new Kinetic.Layer();
tempLayer.getCanvas().width = this.attrs.width;
tempLayer.getCanvas().height = this.attrs.height;
tempLayer.parent = this;
var tempCanvas = tempLayer.getCanvas();
var tempContext = tempLayer.getContext();
for(var n = 0; n < layers.length; n++) { var layers = this.children;
function drawLayer(n) {
var layer = layers[n]; var layer = layers[n];
var layerUrl; var layerUrl;
try { try {
@@ -2221,18 +2244,40 @@ Kinetic.Stage = Kinetic.Container.extend({
} }
var imageObj = new Image(); var imageObj = new Image();
imageObj.src = layerUrl; imageObj.onload = function() {
bufferContext.drawImage(imageObj, 0, 0); tempContext.drawImage(imageObj, 0, 0);
}
if(n < layers.length - 1) {
drawLayer(n + 1);
}
else {
try { try {
// If this call fails (due to browser bug, like in Firefox 3.6), // If this call fails (due to browser bug, like in Firefox 3.6),
// then revert to previous no-parameter image/png behavior // then revert to previous no-parameter image/png behavior
return bufferLayer.getCanvas().toDataURL(mimeType, quality); callback(tempLayer.getCanvas().toDataURL(mimeType, quality));
} }
catch(e) { catch(e) {
return bufferLayer.getCanvas().toDataURL(); callback(tempLayer.getCanvas().toDataURL());
} }
}
};
imageObj.src = layerUrl;
}
drawLayer(0);
},
/**
* converts stage into an image. Since the stage toImage() method
* is asynchronous, a callback function is required
* @name toImage
* @methodOf Kinetic.Stage.prototype
* @param {Function} callback
*/
toImage: function(callback) {
this.toDataURL(function(dataUrl) {
Kinetic.Type._getImage(dataUrl, function(img) {
callback(img);
});
});
}, },
_resizeDOM: function() { _resizeDOM: function() {
var width = this.attrs.width; var width = this.attrs.width;
@@ -3864,20 +3909,6 @@ Kinetic.Image = Kinetic.Shape.extend({
}; };
// call super constructor // call super constructor
this._super(config); this._super(config);
/*
* if image property is ever changed, check and see
* if it was set to image data, and if it was, go ahead
* and save it
*/
this.on('beforeImageChange.kinetic', function(evt) {
this._setImageData(evt.newVal);
});
/*
* if image property was set with image data,
* go ahead and save it
*/
this._setImageData(config.image);
}, },
/** /**
* set width and height * set width and height

File diff suppressed because one or more lines are too long

View File

@@ -251,10 +251,6 @@ Kinetic.Node = Kinetic.Class.extend({
that._setAttr(obj[key], 'width', size.width); that._setAttr(obj[key], 'width', size.width);
that._setAttr(obj[key], 'height', size.height); that._setAttr(obj[key], 'height', size.height);
break; break;
case 'image':
var img = type._getImage(val);
that._setAttr(obj, key, img);
break;
default: default:
that._setAttr(obj, key, val); that._setAttr(obj, key, val);
break; break;
@@ -854,10 +850,15 @@ Kinetic.Node = Kinetic.Class.extend({
} }
}, },
/** /**
* to image * converts node into an image. Since the toImage
* method is asynchronous, a callback is required
* @name toImage
* @methodOf Kinetic.Stage.prototype
*/ */
toImage: function() { toImage: function(callback) {
return Kinetic.Type._getImage(this.toDataURL()); Kinetic.Type._getImage(this.toDataURL(), function(img) {
callback(img);
});
}, },
_setImageData: function(imageData) { _setImageData: function(imageData) {
if(imageData && imageData.data) { if(imageData && imageData.data) {

View File

@@ -274,7 +274,8 @@ Kinetic.Stage = Kinetic.Container.extend({
return this.content; return this.content;
}, },
/** /**
* Creates a composite data URL. If MIME type is not * Creates a composite data URL and requires a callback because the stage
* toDataURL method is asynchronous. If MIME type is not
* specified, then "image/png" will result. For "image/jpeg", specify a quality * specified, then "image/png" will result. For "image/jpeg", specify a quality
* level as quality (range 0.0 - 1.0). Note that this method works * level as quality (range 0.0 - 1.0). Note that this method works
* differently from toDataURL() for other nodes because it generates an absolute dataURL * differently from toDataURL() for other nodes because it generates an absolute dataURL
@@ -282,17 +283,28 @@ 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 {String} [mimeType] * @param {String} [mimeType]
* @param {Number} [quality] * @param {Number} [quality]
*/ */
toDataURL: function(mimeType, quality) { toDataURL: function(callback, mimeType, quality) {
var bufferLayer = this.bufferLayer; /*
var bufferCanvas = bufferLayer.getCanvas(); * we need to create a temp layer rather than using
var bufferContext = bufferLayer.getContext(); * the bufferLayer because the stage toDataURL method
var layers = this.children; * is asynchronous, which means that other parts of the
bufferLayer.clear(); * code base could be updating or clearing the bufferLayer
* while the stage toDataURL method is processing
*/
var tempLayer = new Kinetic.Layer();
tempLayer.getCanvas().width = this.attrs.width;
tempLayer.getCanvas().height = this.attrs.height;
tempLayer.parent = this;
var tempCanvas = tempLayer.getCanvas();
var tempContext = tempLayer.getContext();
for(var n = 0; n < layers.length; n++) { var layers = this.children;
function drawLayer(n) {
var layer = layers[n]; var layer = layers[n];
var layerUrl; var layerUrl;
try { try {
@@ -305,18 +317,40 @@ Kinetic.Stage = Kinetic.Container.extend({
} }
var imageObj = new Image(); var imageObj = new Image();
imageObj.src = layerUrl; imageObj.onload = function() {
bufferContext.drawImage(imageObj, 0, 0); tempContext.drawImage(imageObj, 0, 0);
}
if(n < layers.length - 1) {
drawLayer(n + 1);
}
else {
try { try {
// If this call fails (due to browser bug, like in Firefox 3.6), // If this call fails (due to browser bug, like in Firefox 3.6),
// then revert to previous no-parameter image/png behavior // then revert to previous no-parameter image/png behavior
return bufferLayer.getCanvas().toDataURL(mimeType, quality); callback(tempLayer.getCanvas().toDataURL(mimeType, quality));
} }
catch(e) { catch(e) {
return bufferLayer.getCanvas().toDataURL(); callback(tempLayer.getCanvas().toDataURL());
} }
}
};
imageObj.src = layerUrl;
}
drawLayer(0);
},
/**
* converts stage into an image. Since the stage toImage() method
* is asynchronous, a callback function is required
* @name toImage
* @methodOf Kinetic.Stage.prototype
* @param {Function} callback
*/
toImage: function(callback) {
this.toDataURL(function(dataUrl) {
Kinetic.Type._getImage(dataUrl, function(img) {
callback(img);
});
});
}, },
_resizeDOM: function() { _resizeDOM: function() {
var width = this.attrs.width; var width = this.attrs.width;

View File

@@ -43,20 +43,6 @@ Kinetic.Image = Kinetic.Shape.extend({
}; };
// call super constructor // call super constructor
this._super(config); this._super(config);
/*
* if image property is ever changed, check and see
* if it was set to image data, and if it was, go ahead
* and save it
*/
this.on('beforeImageChange.kinetic', function(evt) {
this._setImageData(evt.newVal);
});
/*
* if image property was set with image data,
* go ahead and save it
*/
this._setImageData(config.image);
}, },
/** /**
* set width and height * set width and height

View File

@@ -212,21 +212,28 @@ Kinetic.Type = {
/* /*
* arg can be an image object or image data * arg can be an image object or image data
*/ */
_getImage: function(arg) { _getImage: function(arg, callback) {
// if arg is already an image object, just return it // if arg is null or undefined
if(this._isElement(arg)) { if(!arg) {
return arg; callback(null);
}
// if arg is already an image object
else if(this._isElement(arg)) {
callback(arg);
} }
// if arg is a string, then it's a data url // if arg is a string, then it's a data url
if(this._isString(arg)) { else if(this._isString(arg)) {
var imageObj = new Image(); var imageObj = new Image();
imageObj.onload = function() {
callback(imageObj);
}
imageObj.src = arg; imageObj.src = arg;
return imageObj;
} }
//if arg is an object that contains the data property, it's an image object //if arg is an object that contains the data property, it's an image object
if(arg.data) { else if(arg.data) {
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
canvas.width = arg.width; canvas.width = arg.width;
canvas.height = arg.height; canvas.height = arg.height;
@@ -234,11 +241,14 @@ Kinetic.Type = {
context.putImageData(arg, 0, 0); context.putImageData(arg, 0, 0);
var dataUrl = canvas.toDataURL(); var dataUrl = canvas.toDataURL();
var imageObj = new Image(); var imageObj = new Image();
imageObj.onload = function() {
callback(imageObj);
}
imageObj.src = dataUrl; imageObj.src = dataUrl;
return imageObj;
} }
// default else {
return null; callback(null);
}
} }
}; };

File diff suppressed because one or more lines are too long

View File

@@ -38,7 +38,7 @@ Test.prototype.tests = {
circle.on('dragend', function() { circle.on('dragend', function() {
dragEnd = true; dragEnd = true;
}); });
startDataUrl = stage.toDataURL(); startDataUrl = layer.toDataURL();
warn(urls[0] === startDataUrl, 'start data url is incorrect'); warn(urls[0] === startDataUrl, 'start data url is incorrect');
/* /*
* simulate drag and drop * simulate drag and drop
@@ -70,7 +70,7 @@ Test.prototype.tests = {
test(dragMove, 'dragmove event was not triggered'); test(dragMove, 'dragmove event was not triggered');
test(dragEnd, 'dragend event was not triggered'); test(dragEnd, 'dragend event was not triggered');
var endDataUrl = stage.toDataURL(); var endDataUrl = layer.toDataURL();
warn(urls[1] === endDataUrl, 'end data url is incorrect'); warn(urls[1] === endDataUrl, 'end data url is incorrect');
}, },
'DRAG AND DROP - cancel drag and drop by setting draggable to false': function(containerId) { 'DRAG AND DROP - cancel drag and drop by setting draggable to false': function(containerId) {
@@ -176,7 +176,7 @@ Test.prototype.tests = {
stage.add(layer); stage.add(layer);
var startDataUrl = stage.toDataURL(); var startDataUrl = layer.toDataURL();
warn(urls[0] === startDataUrl, 'start data url is incorrect'); warn(urls[0] === startDataUrl, 'start data url is incorrect');
/* /*
@@ -197,7 +197,7 @@ Test.prototype.tests = {
clientY: 109 clientY: 109
}); });
var endDataUrl = stage.toDataURL() var endDataUrl = layer.toDataURL()
warn(urls[1] === endDataUrl, 'end data url is incorrect'); warn(urls[1] === endDataUrl, 'end data url is incorrect');
}, },
@@ -240,14 +240,15 @@ Test.prototype.tests = {
layer.add(circle); layer.add(circle);
stage.add(layer); stage.add(layer);
warn(stage.toDataURL() === urls[0], 'start data url is incorrect'); warn(layer.toDataURL() === urls[0], 'start data url is incorrect');
stage._mousemove({ stage._mousemove({
clientX: 377, clientX: 377,
clientY: 101 clientY: 101
}); });
warn(stage.toDataURL() === urls[1], 'mid data url is incorrect'); console.log(layer.toDataURL())
warn(layer.toDataURL() === urls[1], 'mid data url is incorrect');
// move mouse back out of circle // move mouse back out of circle
stage._mousemove({ stage._mousemove({
@@ -259,7 +260,7 @@ Test.prototype.tests = {
clientY: 138 clientY: 138
}); });
warn(stage.toDataURL() === urls[0], 'end data url is incorrect'); warn(layer.toDataURL() === urls[0], 'end data url is incorrect');
}, },
'EVENTS - path detection mousedown mouseup mouseover mouseout mousemove click dblclick / touchstart touchend touchmove tap dbltap': function(containerId) { 'EVENTS - path detection mousedown mouseup mouseover mouseout mousemove click dblclick / touchstart touchend touchmove tap dbltap': function(containerId) {
var stage = new Kinetic.Stage({ var stage = new Kinetic.Stage({

View File

@@ -1468,7 +1468,7 @@ Test.prototype.tests = {
}); });
Ellipse.on('click', function() { Ellipse.on('click', function() {
window.open(stage.toDataURL()); window.open(layer.toDataURL());
}); });
layer.add(Ellipse); layer.add(Ellipse);
@@ -1492,7 +1492,7 @@ Test.prototype.tests = {
}); });
Ellipse.on('click', function() { Ellipse.on('click', function() {
window.open(stage.toDataURL('image/jpeg', 0)); window.open(layer.toDataURL('image/jpeg', 0));
}); });
layer.add(Ellipse); layer.add(Ellipse);
@@ -1516,7 +1516,7 @@ Test.prototype.tests = {
}); });
Ellipse.on('click', function() { Ellipse.on('click', function() {
window.open(stage.toDataURL('image/jpeg', 1)); window.open(layer.toDataURL('image/jpeg', 1));
}); });
layer.add(Ellipse); layer.add(Ellipse);

View File

@@ -1,5 +1,5 @@
Test.prototype.tests = { Test.prototype.tests = {
'PERFORMANCE - draw rect vs image from image data': function(containerId) { 'DRAWING - draw rect vs image from image data': function(containerId) {
var stage = new Kinetic.Stage({ var stage = new Kinetic.Stage({
container: containerId, container: containerId,
width: 578, width: 578,
@@ -34,7 +34,7 @@ Test.prototype.tests = {
endTimer('draw 10,000 images with image object from image data'); endTimer('draw 10,000 images with image object from image data');
}, },
'PERFORMANCE - draw rect vs image from data url': function(containerId) { 'DRAWING - draw rect vs image from data url': function(containerId) {
var stage = new Kinetic.Stage({ var stage = new Kinetic.Stage({
container: containerId, container: containerId,
width: 578, width: 578,
@@ -57,7 +57,7 @@ Test.prototype.tests = {
endTimer('draw 10,000 rects with canvas API'); endTimer('draw 10,000 rects with canvas API');
startTimer(); startTimer();
var url = canvas.toDataURL(); var url = layer.toDataURL();
endTimer('create data url'); endTimer('create data url');
var imageObj = new Image(); var imageObj = new Image();
@@ -71,7 +71,7 @@ Test.prototype.tests = {
} }
endTimer('draw 10,000 images with image object from data url'); endTimer('draw 10,000 images with image object from data url');
}, },
'*ANIMATION - draw 1,000 stars': function(containerId) { 'DRAWING - draw 1,000 stars': function(containerId) {
var stage = new Kinetic.Stage({ var stage = new Kinetic.Stage({
container: containerId, container: containerId,
width: 578, width: 578,
@@ -99,7 +99,7 @@ Test.prototype.tests = {
endTimer('draw 1,000 stars'); endTimer('draw 1,000 stars');
}, },
'*ANIMATION - draw 1,000 cached stars': function(containerId) { 'DRAWING - draw 1,000 cached stars': function(containerId) {
var stage = new Kinetic.Stage({ var stage = new Kinetic.Stage({
container: containerId, container: containerId,
width: 578, width: 578,
@@ -107,8 +107,6 @@ Test.prototype.tests = {
}); });
var layer = new Kinetic.Layer(); var layer = new Kinetic.Layer();
startTimer();
var star = new Kinetic.Star({ var star = new Kinetic.Star({
innerRadius: 20, innerRadius: 20,
outerRadius: 50, outerRadius: 50,
@@ -123,8 +121,9 @@ Test.prototype.tests = {
layer.add(star); layer.add(star);
stage.add(layer); stage.add(layer);
var img = star.toImage(); console.log('call toImage')
star.toImage(function(img) {
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({
image: img, image: img,
@@ -138,6 +137,7 @@ Test.prototype.tests = {
layer.draw(); layer.draw();
endTimer('draw 1,000 stars'); endTimer('draw 1,000 cached stars');
});
} }
}; };

View File

@@ -362,7 +362,7 @@ Test.prototype.tests = {
layer.add(group); layer.add(group);
stage.add(layer); stage.add(layer);
var startDataUrl = stage.toDataURL(); var startDataUrl = layer.toDataURL();
warn(startDataUrl === urls[0], 'start data url is incorrect'); warn(startDataUrl === urls[0], 'start data url is incorrect');
test(triangle.getId() === 'myTriangle', 'triangle id should be myTriangle'); test(triangle.getId() === 'myTriangle', 'triangle id should be myTriangle');
@@ -377,7 +377,7 @@ Test.prototype.tests = {
*/ */
layer.draw(); layer.draw();
var endDataUrl = stage.toDataURL(); var endDataUrl = layer.toDataURL();
warn(endDataUrl === urls[0], 'end data url is incorrect'); warn(endDataUrl === urls[0], 'end data url is incorrect');
}, },
@@ -1042,7 +1042,9 @@ Test.prototype.tests = {
layer.draw(); layer.draw();
} }
warn(urls[0] === stage.toDataURL(), 'stage data url is incorrect'); stage.toDataURL(function(dataUrl) {
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');
@@ -1989,96 +1991,6 @@ Test.prototype.tests = {
}; };
imageObj.src = '../darth-vader.jpg'; imageObj.src = '../darth-vader.jpg';
}, },
'SHAPE - add image with image data': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var group = new Kinetic.Group();
var circle = new Kinetic.Ellipse({
x: 100,
y: stage.getHeight() / 2,
radius: 70,
fill: 'green',
stroke: 'black',
strokeWidth: 4
});
var circle2 = new Kinetic.Ellipse({
x: 150,
y: stage.getHeight() / 2,
radius: 70,
fill: 'yellow',
stroke: 'black',
strokeWidth: 4
});
group.add(circle);
group.add(circle2);
layer.add(group);
stage.add(layer);
group.saveImageData();
var image = new Kinetic.Image({
image: group.getImageData(),
x: 200,
y: 0,
draggable: true
});
layer.add(image);
layer.draw();
test(Kinetic.Type._isElement(image.getImage()), 'image property should have been converted to an image element');
},
'SHAPE - add image with data url': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var group = new Kinetic.Group();
var circle = new Kinetic.Ellipse({
x: 100,
y: stage.getHeight() / 2,
radius: 70,
fill: 'green',
stroke: 'black',
strokeWidth: 4
});
var circle2 = new Kinetic.Ellipse({
x: 150,
y: stage.getHeight() / 2,
radius: 70,
fill: 'yellow',
stroke: 'black',
strokeWidth: 4
});
group.add(circle);
group.add(circle2);
layer.add(group);
stage.add(layer);
var image = new Kinetic.Image({
image: layer.toDataURL(),
x: 200,
y: 0,
draggable: true
});
layer.add(image);
layer.draw();
test(Kinetic.Type._isElement(image.getImage()), 'image property should have been converted to an image element');
},
'SHAPE - set image fill to color then image': function(containerId) { 'SHAPE - set image fill to color then image': function(containerId) {
var imageObj = new Image(); var imageObj = new Image();
imageObj.onload = function() { imageObj.onload = function() {
@@ -2272,10 +2184,18 @@ Test.prototype.tests = {
layer.add(group); layer.add(group);
stage.add(layer); stage.add(layer);
test(Kinetic.Type._isElement(poly.toImage()), 'shape toImage() should be an image object'); poly.toImage(function(imageObj) {
test(Kinetic.Type._isElement(group.toImage()), 'group toImage() should be an image object'); test(Kinetic.Type._isElement(imageObj), 'shape toImage() should be an image object');
test(Kinetic.Type._isElement(layer.toImage()), 'layer toImage() should be an image object'); });
test(Kinetic.Type._isElement(stage.toImage()), 'stage toImage() should be an image object'); group.toImage(function(imageObj) {
test(Kinetic.Type._isElement(imageObj), 'group toImage() should be an image object');
});
layer.toImage(function(imageObj) {
test(Kinetic.Type._isElement(imageObj), 'layer toImage() should be an image object');
});
stage.toImage(function(imageObj) {
test(Kinetic.Type._isElement(imageObj), 'stage toImage() should be an image object');
});
}, },
'SHAPE - add polygon': function(containerId) { 'SHAPE - add polygon': function(containerId) {
var stage = new Kinetic.Stage({ var stage = new Kinetic.Stage({