Skip to content
This repository
Browse code

toDataURL() is now synchronous, and works with all nodes, including t…

…he stage, layers, groups, and shapes. This also sets things up nicely for node caching. You can now cache anything, including the whole stage, layers, groups, or shapes, manifested as Kinetic Images that were instantiated with data urls
  • Loading branch information...
commit 4692c51c74fd896bddfac417246875a48aee24de 1 parent d62df7b
Eric Rowell authored July 14, 2012
145  dist/kinetic-core.js
@@ -288,9 +288,9 @@ Kinetic.Type = {
288 288
             var context = canvas.getContext('2d');
289 289
             context.putImageData(arg, 0, 0);
290 290
             var dataUrl = canvas.toDataURL();
291  
-			var imageObj = new Image();
292  
-			imageObj.src = dataUrl;
293  
-			return imageObj;
  291
+            var imageObj = new Image();
  292
+            imageObj.src = dataUrl;
  293
+            return imageObj;
294 294
         }
295 295
 
296 296
         // default
@@ -1284,6 +1284,31 @@ Kinetic.Node = Kinetic.Class.extend({
1284 1284
     getImageData: function() {
1285 1285
         return this.imageData;
1286 1286
     },
  1287
+    /**
  1288
+     * Creates a composite data URL. If MIME type is not
  1289
+     * specified, then "image/png" will result. For "image/jpeg", specify a quality
  1290
+     * level as quality (range 0.0 - 1.0)
  1291
+     * @name toDataURL
  1292
+     * @methodOf Kinetic.Stage.prototype
  1293
+     * @param {String} [mimeType]
  1294
+     * @param {Number} [quality]
  1295
+     */
  1296
+    toDataURL: function(mimeType, quality) {
  1297
+        var bufferLayer = this.getStage().bufferLayer;
  1298
+        var bufferCanvas = bufferLayer.getCanvas();
  1299
+        var bufferContext = bufferLayer.getContext();
  1300
+        bufferLayer.clear();
  1301
+        this._draw(bufferLayer);
  1302
+
  1303
+        try {
  1304
+            // If this call fails (due to browser bug, like in Firefox 3.6),
  1305
+            // then revert to previous no-parameter image/png behavior
  1306
+            return bufferLayer.getCanvas().toDataURL(mimeType, quality);
  1307
+        }
  1308
+        catch(e) {
  1309
+            return bufferLayer.getCanvas().toDataURL();
  1310
+        }
  1311
+    },
1287 1312
     _setImageData: function(imageData) {
1288 1313
         if(imageData && imageData.data) {
1289 1314
             this.imageData = imageData;
@@ -1836,7 +1861,7 @@ Kinetic.Container = Kinetic.Node.extend({
1836 1861
             var child = children[n];
1837 1862
             if(child.nodeType === 'Shape') {
1838 1863
                 if(child.isVisible() && stage.isVisible()) {
1839  
-                    child._draw(layer ? layer : child.getLayer());
  1864
+                    child._draw( layer ? layer : child.getLayer());
1840 1865
                 }
1841 1866
             }
1842 1867
             else {
@@ -1996,48 +2021,6 @@ Kinetic.Stage = Kinetic.Container.extend({
1996 2021
         }
1997 2022
     },
1998 2023
     /**
1999  
-     * Creates a composite data URL and passes it to a callback. If MIME type is not
2000  
-     * specified, then "image/png" will result. For "image/jpeg", specify a quality
2001  
-     * level as quality (range 0.0 - 1.0)
2002  
-     * @name toDataURL
2003  
-     * @methodOf Kinetic.Stage.prototype
2004  
-     * @param {function} callback
2005  
-     * @param {String} mimeType (optional)
2006  
-     * @param {Number} quality (optional)
2007  
-     */
2008  
-    toDataURL: function(callback, mimeType, quality) {
2009  
-        var bufferLayer = this.bufferLayer;
2010  
-        var bufferContext = bufferLayer.getContext();
2011  
-        var layers = this.children;
2012  
-        var that = this;
2013  
-
2014  
-        function addLayer(n) {
2015  
-            var dataURL = layers[n].getCanvas().toDataURL();
2016  
-            var imageObj = new Image();
2017  
-            imageObj.onload = function() {
2018  
-                bufferContext.drawImage(this, 0, 0);
2019  
-                n++;
2020  
-                if(n < layers.length) {
2021  
-                    addLayer(n);
2022  
-                }
2023  
-                else {
2024  
-                    try {
2025  
-                        // If this call fails (due to browser bug, like in Firefox 3.6),
2026  
-                        // then revert to previous no-parameter image/png behavior
2027  
-                        callback(bufferLayer.getCanvas().toDataURL(mimeType, quality));
2028  
-                    }
2029  
-                    catch(exception) {
2030  
-                        callback(bufferLayer.getCanvas().toDataURL());
2031  
-                    }
2032  
-                }
2033  
-            };
2034  
-            imageObj.src = dataURL;
2035  
-        }
2036  
-
2037  
-        bufferLayer.clear();
2038  
-        addLayer(0);
2039  
-    },
2040  
-    /**
2041 2024
      * serialize stage and children as a JSON object
2042 2025
      * @name toJSON
2043 2026
      * @methodOf Kinetic.Stage.prototype
@@ -2190,6 +2173,51 @@ Kinetic.Stage = Kinetic.Container.extend({
2190 2173
     getDOM: function() {
2191 2174
         return this.content;
2192 2175
     },
  2176
+    /**
  2177
+     * Creates a composite data URL. If MIME type is not
  2178
+     * specified, then "image/png" will result. For "image/jpeg", specify a quality
  2179
+     * level as quality (range 0.0 - 1.0).  Note that this method works
  2180
+     * differently from toDataURL() for other nodes because it generates an absolute dataURL
  2181
+     * based on what's draw onto the canvases for each layer, rather than drawing
  2182
+     * the current state of each node
  2183
+     * @name toDataURL
  2184
+     * @methodOf Kinetic.Stage.prototype
  2185
+     * @param {String} [mimeType]
  2186
+     * @param {Number} [quality]
  2187
+     */
  2188
+    toDataURL: function(mimeType, quality) {
  2189
+        var bufferLayer = this.bufferLayer;
  2190
+        var bufferCanvas = bufferLayer.getCanvas();
  2191
+        var bufferContext = bufferLayer.getContext();
  2192
+        var layers = this.children;
  2193
+        bufferLayer.clear();
  2194
+        
  2195
+        for(var n = 0; n < layers.length; n++) {
  2196
+            var layer = layers[n];
  2197
+            var layerUrl;
  2198
+            try {
  2199
+                // If this call fails (due to browser bug, like in Firefox 3.6),
  2200
+                // then revert to previous no-parameter image/png behavior
  2201
+                layerUrl = layer.getCanvas().toDataURL(mimeType, quality);
  2202
+            }
  2203
+            catch(e) {
  2204
+                layerUrl = layer.getCanvas().toDataURL();
  2205
+            }
  2206
+
  2207
+            var imageObj = new Image();
  2208
+            imageObj.src = layerUrl;
  2209
+            bufferContext.drawImage(imageObj, 0, 0);
  2210
+        }
  2211
+
  2212
+        try {
  2213
+            // If this call fails (due to browser bug, like in Firefox 3.6),
  2214
+            // then revert to previous no-parameter image/png behavior
  2215
+            return bufferLayer.getCanvas().toDataURL(mimeType, quality);
  2216
+        }
  2217
+        catch(e) {
  2218
+            return bufferLayer.getCanvas().toDataURL();
  2219
+        }
  2220
+    },
2193 2221
     _resizeDOM: function() {
2194 2222
         var width = this.attrs.width;
2195 2223
         var height = this.attrs.height;
@@ -3015,6 +3043,28 @@ Kinetic.Layer = Kinetic.Container.extend({
3015 3043
         return this.context;
3016 3044
     },
3017 3045
     /**
  3046
+     * Creates a composite data URL. If MIME type is not
  3047
+     * specified, then "image/png" will result. For "image/jpeg", specify a quality
  3048
+     * level as quality (range 0.0 - 1.0).  Note that this method works
  3049
+     * differently from toDataURL() for other nodes because it generates an absolute dataURL
  3050
+     * based on what's draw on the layer, rather than drawing
  3051
+     * the current state of each child node
  3052
+     * @name toDataURL
  3053
+     * @methodOf Kinetic.Stage.prototype
  3054
+     * @param {String} [mimeType]
  3055
+     * @param {Number} [quality]
  3056
+     */
  3057
+    toDataURL: function(mimeType, quality) {
  3058
+        try {
  3059
+            // If this call fails (due to browser bug, like in Firefox 3.6),
  3060
+            // then revert to previous no-parameter image/png behavior
  3061
+            return this.getCanvas().toDataURL(mimeType, quality);
  3062
+        }
  3063
+        catch(e) {
  3064
+            return this.getCanvas().toDataURL();
  3065
+        }
  3066
+    },
  3067
+    /**
3018 3068
      * private draw children
3019 3069
      */
3020 3070
     _draw: function(layer) {
@@ -3028,7 +3078,8 @@ Kinetic.Layer = Kinetic.Container.extend({
3028 3078
         }
3029 3079
 
3030 3080
         if(this.attrs.clearBeforeDraw) {
3031  
-            this.clear();
  3081
+            var clearLayer = layer ? layer : this;
  3082
+            clearLayer.clear();
3032 3083
         }
3033 3084
 
3034 3085
         if(this.isVisible()) {
4  dist/kinetic-core.min.js
2 additions, 2 deletions not shown
2  src/Container.js
@@ -218,7 +218,7 @@ Kinetic.Container = Kinetic.Node.extend({
218 218
             var child = children[n];
219 219
             if(child.nodeType === 'Shape') {
220 220
                 if(child.isVisible() && stage.isVisible()) {
221  
-                    child._draw(layer ? layer : child.getLayer());
  221
+                    child._draw( layer ? layer : child.getLayer());
222 222
                 }
223 223
             }
224 224
             else {
25  src/Layer.js
@@ -108,6 +108,28 @@ Kinetic.Layer = Kinetic.Container.extend({
108 108
         return this.context;
109 109
     },
110 110
     /**
  111
+     * Creates a composite data URL. If MIME type is not
  112
+     * specified, then "image/png" will result. For "image/jpeg", specify a quality
  113
+     * level as quality (range 0.0 - 1.0).  Note that this method works
  114
+     * differently from toDataURL() for other nodes because it generates an absolute dataURL
  115
+     * based on what's draw on the layer, rather than drawing
  116
+     * the current state of each child node
  117
+     * @name toDataURL
  118
+     * @methodOf Kinetic.Stage.prototype
  119
+     * @param {String} [mimeType]
  120
+     * @param {Number} [quality]
  121
+     */
  122
+    toDataURL: function(mimeType, quality) {
  123
+        try {
  124
+            // If this call fails (due to browser bug, like in Firefox 3.6),
  125
+            // then revert to previous no-parameter image/png behavior
  126
+            return this.getCanvas().toDataURL(mimeType, quality);
  127
+        }
  128
+        catch(e) {
  129
+            return this.getCanvas().toDataURL();
  130
+        }
  131
+    },
  132
+    /**
111 133
      * private draw children
112 134
      */
113 135
     _draw: function(layer) {
@@ -121,7 +143,8 @@ Kinetic.Layer = Kinetic.Container.extend({
121 143
         }
122 144
 
123 145
         if(this.attrs.clearBeforeDraw) {
124  
-            this.clear();
  146
+            var clearLayer = layer ? layer : this;
  147
+            clearLayer.clear();
125 148
         }
126 149
 
127 150
         if(this.isVisible()) {
25  src/Node.js
@@ -828,6 +828,31 @@ Kinetic.Node = Kinetic.Class.extend({
828 828
     getImageData: function() {
829 829
         return this.imageData;
830 830
     },
  831
+    /**
  832
+     * Creates a composite data URL. If MIME type is not
  833
+     * specified, then "image/png" will result. For "image/jpeg", specify a quality
  834
+     * level as quality (range 0.0 - 1.0)
  835
+     * @name toDataURL
  836
+     * @methodOf Kinetic.Stage.prototype
  837
+     * @param {String} [mimeType]
  838
+     * @param {Number} [quality]
  839
+     */
  840
+    toDataURL: function(mimeType, quality) {
  841
+        var bufferLayer = this.getStage().bufferLayer;
  842
+        var bufferCanvas = bufferLayer.getCanvas();
  843
+        var bufferContext = bufferLayer.getContext();
  844
+        bufferLayer.clear();
  845
+        this._draw(bufferLayer);
  846
+
  847
+        try {
  848
+            // If this call fails (due to browser bug, like in Firefox 3.6),
  849
+            // then revert to previous no-parameter image/png behavior
  850
+            return bufferLayer.getCanvas().toDataURL(mimeType, quality);
  851
+        }
  852
+        catch(e) {
  853
+            return bufferLayer.getCanvas().toDataURL();
  854
+        }
  855
+    },
831 856
     _setImageData: function(imageData) {
832 857
         if(imageData && imageData.data) {
833 858
             this.imageData = imageData;
87  src/Stage.js
@@ -121,48 +121,6 @@ Kinetic.Stage = Kinetic.Container.extend({
121 121
         }
122 122
     },
123 123
     /**
124  
-     * Creates a composite data URL and passes it to a callback. If MIME type is not
125  
-     * specified, then "image/png" will result. For "image/jpeg", specify a quality
126  
-     * level as quality (range 0.0 - 1.0)
127  
-     * @name toDataURL
128  
-     * @methodOf Kinetic.Stage.prototype
129  
-     * @param {function} callback
130  
-     * @param {String} mimeType (optional)
131  
-     * @param {Number} quality (optional)
132  
-     */
133  
-    toDataURL: function(callback, mimeType, quality) {
134  
-        var bufferLayer = this.bufferLayer;
135  
-        var bufferContext = bufferLayer.getContext();
136  
-        var layers = this.children;
137  
-        var that = this;
138  
-
139  
-        function addLayer(n) {
140  
-            var dataURL = layers[n].getCanvas().toDataURL();
141  
-            var imageObj = new Image();
142  
-            imageObj.onload = function() {
143  
-                bufferContext.drawImage(this, 0, 0);
144  
-                n++;
145  
-                if(n < layers.length) {
146  
-                    addLayer(n);
147  
-                }
148  
-                else {
149  
-                    try {
150  
-                        // If this call fails (due to browser bug, like in Firefox 3.6),
151  
-                        // then revert to previous no-parameter image/png behavior
152  
-                        callback(bufferLayer.getCanvas().toDataURL(mimeType, quality));
153  
-                    }
154  
-                    catch(exception) {
155  
-                        callback(bufferLayer.getCanvas().toDataURL());
156  
-                    }
157  
-                }
158  
-            };
159  
-            imageObj.src = dataURL;
160  
-        }
161  
-
162  
-        bufferLayer.clear();
163  
-        addLayer(0);
164  
-    },
165  
-    /**
166 124
      * serialize stage and children as a JSON object
167 125
      * @name toJSON
168 126
      * @methodOf Kinetic.Stage.prototype
@@ -315,6 +273,51 @@ Kinetic.Stage = Kinetic.Container.extend({
315 273
     getDOM: function() {
316 274
         return this.content;
317 275
     },
  276
+    /**
  277
+     * Creates a composite data URL. If MIME type is not
  278
+     * specified, then "image/png" will result. For "image/jpeg", specify a quality
  279
+     * level as quality (range 0.0 - 1.0).  Note that this method works
  280
+     * differently from toDataURL() for other nodes because it generates an absolute dataURL
  281
+     * based on what's draw onto the canvases for each layer, rather than drawing
  282
+     * the current state of each node
  283
+     * @name toDataURL
  284
+     * @methodOf Kinetic.Stage.prototype
  285
+     * @param {String} [mimeType]
  286
+     * @param {Number} [quality]
  287
+     */
  288
+    toDataURL: function(mimeType, quality) {
  289
+        var bufferLayer = this.bufferLayer;
  290
+        var bufferCanvas = bufferLayer.getCanvas();
  291
+        var bufferContext = bufferLayer.getContext();
  292
+        var layers = this.children;
  293
+        bufferLayer.clear();
  294
+        
  295
+        for(var n = 0; n < layers.length; n++) {
  296
+            var layer = layers[n];
  297
+            var layerUrl;
  298
+            try {
  299
+                // If this call fails (due to browser bug, like in Firefox 3.6),
  300
+                // then revert to previous no-parameter image/png behavior
  301
+                layerUrl = layer.getCanvas().toDataURL(mimeType, quality);
  302
+            }
  303
+            catch(e) {
  304
+                layerUrl = layer.getCanvas().toDataURL();
  305
+            }
  306
+
  307
+            var imageObj = new Image();
  308
+            imageObj.src = layerUrl;
  309
+            bufferContext.drawImage(imageObj, 0, 0);
  310
+        }
  311
+
  312
+        try {
  313
+            // If this call fails (due to browser bug, like in Firefox 3.6),
  314
+            // then revert to previous no-parameter image/png behavior
  315
+            return bufferLayer.getCanvas().toDataURL(mimeType, quality);
  316
+        }
  317
+        catch(e) {
  318
+            return bufferLayer.getCanvas().toDataURL();
  319
+        }
  320
+    },
318 321
     _resizeDOM: function() {
319 322
         var width = this.attrs.width;
320 323
         var height = this.attrs.height;
6  src/util/Type.js
@@ -223,9 +223,9 @@ Kinetic.Type = {
223 223
             var context = canvas.getContext('2d');
224 224
             context.putImageData(arg, 0, 0);
225 225
             var dataUrl = canvas.toDataURL();
226  
-			var imageObj = new Image();
227  
-			imageObj.src = dataUrl;
228  
-			return imageObj;
  226
+            var imageObj = new Image();
  227
+            imageObj.src = dataUrl;
  228
+            return imageObj;
229 229
         }
230 230
 
231 231
         // default
2  tests/assets/unitDataUrls.js
@@ -5,5 +5,5 @@
5 5
  */
6 6
 var dataUrls = {
7 7
     'STAGE - serialize stage with custom shape': ['data:image/png;base64,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'],
8  
-    'LAYER - set clearBeforeDraw to false': ['data:image/png;base64,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']
  8
+    'LAYER - set clearBeforeDraw to false': ['data:image/png;base64,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', 'data:image/png;base64,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']
9 9
 };
126  tests/js/functionalTests.js
@@ -38,43 +38,40 @@ Test.prototype.tests = {
38 38
         circle.on('dragend', function() {
39 39
             dragEnd = true;
40 40
         });
  41
+        startDataUrl = stage.toDataURL();
  42
+        warn(urls[0] === startDataUrl, 'start data url is incorrect');
  43
+        /*
  44
+         * simulate drag and drop
  45
+         */
  46
+        stage._mousedown({
  47
+            clientX: 380,
  48
+            clientY: 98
  49
+        });
41 50
 
42  
-        stage.toDataURL(function(startDataUrl) {
43  
-            warn(urls[0] === startDataUrl, 'start data url is incorrect');
44  
-            /*
45  
-             * simulate drag and drop
46  
-             */
47  
-            stage._mousedown({
48  
-                clientX: 380,
49  
-                clientY: 98
50  
-            });
51  
-
52  
-            test(!dragStart, 'dragstart event should not have been triggered');
53  
-            test(!dragMove, 'dragmove event should not have been triggered');
54  
-            test(!dragEnd, 'dragend event should not have been triggered');
55  
-
56  
-            stage._mousemove({
57  
-                clientX: 100,
58  
-                clientY: 98
59  
-            });
60  
-
61  
-            test(dragStart, 'dragstart event was not triggered');
62  
-            test(dragMove, 'dragmove event was not triggered');
63  
-            test(!dragEnd, 'dragend event should not have been triggered');
64  
-
65  
-            stage._mouseup({
66  
-                clientX: 100,
67  
-                clientY: 98
68  
-            });
69  
-
70  
-            test(dragStart, 'dragstart event was not triggered');
71  
-            test(dragMove, 'dragmove event was not triggered');
72  
-            test(dragEnd, 'dragend event was not triggered');
73  
-
74  
-            stage.toDataURL(function(endDataUrl) {
75  
-                warn(urls[1] === endDataUrl, 'end data url is incorrect');
76  
-            });
  51
+        test(!dragStart, 'dragstart event should not have been triggered');
  52
+        test(!dragMove, 'dragmove event should not have been triggered');
  53
+        test(!dragEnd, 'dragend event should not have been triggered');
  54
+
  55
+        stage._mousemove({
  56
+            clientX: 100,
  57
+            clientY: 98
77 58
         });
  59
+
  60
+        test(dragStart, 'dragstart event was not triggered');
  61
+        test(dragMove, 'dragmove event was not triggered');
  62
+        test(!dragEnd, 'dragend event should not have been triggered');
  63
+
  64
+        stage._mouseup({
  65
+            clientX: 100,
  66
+            clientY: 98
  67
+        });
  68
+
  69
+        test(dragStart, 'dragstart event was not triggered');
  70
+        test(dragMove, 'dragmove event was not triggered');
  71
+        test(dragEnd, 'dragend event was not triggered');
  72
+
  73
+        var endDataUrl = stage.toDataURL();
  74
+        warn(urls[1] === endDataUrl, 'end data url is incorrect');
78 75
     },
79 76
     'DRAG AND DROP - cancel drag and drop by setting draggable to false': function(containerId) {
80 77
         var stage = new Kinetic.Stage({
@@ -179,31 +176,30 @@ Test.prototype.tests = {
179 176
 
180 177
         stage.add(layer);
181 178
 
182  
-        stage.toDataURL(function(startDataUrl) {
183  
-            warn(urls[0] === startDataUrl, 'start data url is incorrect');
184  
-
185  
-            /*
186  
-             * simulate drag and drop
187  
-             */
188  
-            stage._mousedown({
189  
-                clientX: 399,
190  
-                clientY: 96
191  
-            });
  179
+        var startDataUrl = stage.toDataURL();
  180
+        warn(urls[0] === startDataUrl, 'start data url is incorrect');
192 181
 
193  
-            stage._mousemove({
194  
-                clientX: 210,
195  
-                clientY: 109
196  
-            });
  182
+        /*
  183
+         * simulate drag and drop
  184
+         */
  185
+        stage._mousedown({
  186
+            clientX: 399,
  187
+            clientY: 96
  188
+        });
197 189
 
198  
-            stage._mouseup({
199  
-                clientX: 210,
200  
-                clientY: 109
201  
-            });
  190
+        stage._mousemove({
  191
+            clientX: 210,
  192
+            clientY: 109
  193
+        });
202 194
 
203  
-            stage.toDataURL(function(endDataUrl) {
204  
-                warn(urls[1] === endDataUrl, 'end data url is incorrect');
205  
-            });
  195
+        stage._mouseup({
  196
+            clientX: 210,
  197
+            clientY: 109
206 198
         });
  199
+
  200
+        var endDataUrl = stage.toDataURL()
  201
+        warn(urls[1] === endDataUrl, 'end data url is incorrect');
  202
+
207 203
     },
208 204
     'EVENTS - modify fill stroke and stroke width on hover with circle': function(containerId) {
209 205
         var urls = dataUrls['EVENTS - modify fill stroke and stroke width on hover with circle'];
@@ -239,18 +235,16 @@ Test.prototype.tests = {
239 235
         layer.add(circle);
240 236
         stage.add(layer);
241 237
 
242  
-        stage.toDataURL(function(startDataUrl) {
243  
-            warn(startDataUrl === urls[0], 'start data url is incorrect');
  238
+        var startDataUrl = stage.toDataURL();
  239
+        warn(startDataUrl === urls[0], 'start data url is incorrect');
244 240
 
245  
-            stage._mousemove({
246  
-                clientX: 377,
247  
-                clientY: 101
248  
-            });
249  
-
250  
-            stage.toDataURL(function(endDataUrl) {
251  
-                warn(urls[1] === endDataUrl, 'end data url is incorrect');
252  
-            });
  241
+        stage._mousemove({
  242
+            clientX: 377,
  243
+            clientY: 101
253 244
         });
  245
+
  246
+        var endDataUrl = stage.toDataURL();
  247
+        warn(urls[1] === endDataUrl, 'end data url is incorrect');
254 248
     },
255 249
     'EVENTS - path detection mousedown mouseup mouseover mouseout mousemove click dblclick / touchstart touchend touchmove tap dbltap': function(containerId) {
256 250
         var stage = new Kinetic.Stage({
27  tests/js/manualTests.js
@@ -1468,14 +1468,7 @@ Test.prototype.tests = {
1468 1468
         });
1469 1469
 
1470 1470
         Ellipse.on('click', function() {
1471  
-            stage.toDataURL(function(dataUrl) {
1472  
-                /*
1473  
-                 * here you can do anything you like with the data url.
1474  
-                 * In this tutorial we'll just open the url with the browser
1475  
-                 * so that you can see the result as an image
1476  
-                 */
1477  
-                window.open(dataUrl);
1478  
-            });
  1471
+            window.open(stage.toDataURL());
1479 1472
         });
1480 1473
 
1481 1474
         layer.add(Ellipse);
@@ -1499,14 +1492,7 @@ Test.prototype.tests = {
1499 1492
         });
1500 1493
 
1501 1494
         Ellipse.on('click', function() {
1502  
-            stage.toDataURL(function(dataUrl) {
1503  
-                /*
1504  
-                 * here you can do anything you like with the data url.
1505  
-                 * In this tutorial we'll just open the url with the browser
1506  
-                 * so that you can see the result as an image
1507  
-                 */
1508  
-                window.open(dataUrl);
1509  
-            }, 'image/jpeg', 0);
  1495
+        	window.open(stage.toDataURL('image/jpeg', 0));
1510 1496
         });
1511 1497
 
1512 1498
         layer.add(Ellipse);
@@ -1530,14 +1516,7 @@ Test.prototype.tests = {
1530 1516
         });
1531 1517
 
1532 1518
         Ellipse.on('click', function() {
1533  
-            stage.toDataURL(function(dataUrl) {
1534  
-                /*
1535  
-                 * here you can do anything you like with the data url.
1536  
-                 * In this tutorial we'll just open the url with the browser
1537  
-                 * so that you can see the result as an image
1538  
-                 */
1539  
-                window.open(dataUrl);
1540  
-            }, 'image/jpeg', 1);
  1519
+        	window.open(stage.toDataURL('image/jpeg', 1));
1541 1520
         });
1542 1521
 
1543 1522
         layer.add(Ellipse);
53  tests/js/unitTests.js
@@ -358,31 +358,28 @@ Test.prototype.tests = {
358 358
             id: 'myTriangle'
359 359
         });
360 360
 
361  
-        stage.add(layer);
362  
-        layer.add(group);
363 361
         group.add(triangle);
364  
-        layer.draw();
  362
+        layer.add(group);
  363
+        stage.add(layer);
365 364
 
366  
-        stage.toDataURL(function(startDataUrl) {
367  
-            warn(startDataUrl === urls[0], 'start data url is incorrect');
  365
+        var startDataUrl = stage.toDataURL();
368 366
 
369  
-            test(triangle.getId() === 'myTriangle', 'triangle id should be myTriangle');
  367
+        warn(startDataUrl === urls[0], 'start data url is incorrect');
  368
+        test(triangle.getId() === 'myTriangle', 'triangle id should be myTriangle');
370 369
 
371  
-            //console.log(stage.toJSON())
  370
+        //console.log(stage.toJSON())
  371
+        var expectedJson = '{"attrs":{"width":578,"height":200,"throttle":80,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":80,"clearBeforeDraw":true,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Layer","children":[{"attrs":{"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Group","children":[{"attrs":{"detectionType":"path","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false,"fill":"#00D2FF","stroke":"black","strokeWidth":4,"id":"myTriangle"},"nodeType":"Shape"}]}]}]}';
  372
+        test(stage.toJSON() === expectedJson, "problem serializing stage with custom shape");
372 373
 
373  
-            var expectedJson = '{"attrs":{"width":578,"height":200,"throttle":80,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Stage","children":[{"attrs":{"throttle":80,"clearBeforeDraw":true,"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Layer","children":[{"attrs":{"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"nodeType":"Group","children":[{"attrs":{"detectionType":"path","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false,"fill":"#00D2FF","stroke":"black","strokeWidth":4,"id":"myTriangle"},"nodeType":"Shape"}]}]}]}';
374  
-            test(stage.toJSON() === expectedJson, "problem serializing stage with custom shape");
  374
+        /*
  375
+         * test redrawing layer after serialization
  376
+         * drawing should be the same
  377
+         */
  378
+        layer.draw();
375 379
 
376  
-            /*
377  
-             * test redrawing layer after serialization
378  
-             * drawing should be the same
379  
-             */
380  
-            layer.draw();
  380
+        var endDataUrl = stage.toDataURL();
  381
+        warn(endDataUrl === urls[0], 'end data url is incorrect');
381 382
 
382  
-            stage.toDataURL(function(endDataUrl) {
383  
-                warn(endDataUrl === urls[0], 'end data url is incorrect');
384  
-            });
385  
-        });
386 383
     },
387 384
     'STAGE - load stage with custom shape using json': function(containerId) {
388 385
         var stage = new Kinetic.Stage({
@@ -1011,7 +1008,7 @@ Test.prototype.tests = {
1011 1008
 
1012 1009
         layer.draw();
1013 1010
     },
1014  
-    'LAYER - set clearBeforeDraw to false': function(containerId) {
  1011
+    'LAYER - set clearBeforeDraw to false, and test toDataURL for stage, layer, group, and shape': function(containerId) {
1015 1012
         var urls = dataUrls['LAYER - set clearBeforeDraw to false'];
1016 1013
 
1017 1014
         var stage = new Kinetic.Stage({
@@ -1025,6 +1022,8 @@ Test.prototype.tests = {
1025 1022
             throttle: 999
1026 1023
         });
1027 1024
 
  1025
+        var group = new Kinetic.Group();
  1026
+
1028 1027
         var circle = new Kinetic.Ellipse({
1029 1028
             x: 100,
1030 1029
             y: stage.getHeight() / 2,
@@ -1034,7 +1033,8 @@ Test.prototype.tests = {
1034 1033
             strokeWidth: 4
1035 1034
         });
1036 1035
 
1037  
-        layer.add(circle);
  1036
+        group.add(circle);
  1037
+        layer.add(group);
1038 1038
         stage.add(layer);
1039 1039
 
1040 1040
         for(var n = 0; n < 20; n++) {
@@ -1042,9 +1042,10 @@ Test.prototype.tests = {
1042 1042
             layer.draw();
1043 1043
         }
1044 1044
 
1045  
-        stage.toDataURL(function(dataUrl) {
1046  
-            warn(urls[0] === dataUrl, 'data url is incorrect');
1047  
-        });
  1045
+        warn(urls[0] === stage.toDataURL(), 'stage data url is incorrect');
  1046
+        warn(urls[0] === layer.toDataURL(), 'layer data url is incorrect');
  1047
+        warn(urls[1] === group.toDataURL(), 'group data url is incorrect');
  1048
+        warn(urls[1] === circle.toDataURL(), 'shape data url is incorrect');
1048 1049
     },
1049 1050
     'LAYER - throttling': function(containerId) {
1050 1051
         var stage = new Kinetic.Stage({
@@ -2021,16 +2022,16 @@ Test.prototype.tests = {
2021 2022
         stage.add(layer);
2022 2023
 
2023 2024
         group.saveImageData();
2024  
-        
  2025
+
2025 2026
         var image = new Kinetic.Image({
2026 2027
             image: group.getImageData(),
2027 2028
             x: 200,
2028 2029
             y: 0,
2029 2030
             draggable: true
2030 2031
         });
2031  
-        
  2032
+
2032 2033
         layer.add(image);
2033  
-        layer.draw(); 
  2034
+        layer.draw();
2034 2035
     },
2035 2036
     'SHAPE - set image fill to color then image': function(containerId) {
2036 2037
         var imageObj = new Image();

0 notes on commit 4692c51

Please sign in to comment.
Something went wrong with that request. Please try again.