From cb8d36c3937add27ebd169bdd5a08bf661b9e5ac Mon Sep 17 00:00:00 2001 From: Eric Rowell Date: Tue, 11 Dec 2012 00:08:59 -0800 Subject: [PATCH] fixed several bugs with toImage(). toImage() can now also accept x and y params. added extensive caching unit test. removed drawBuffer logic as it is no longer needed --- src/Container.js | 12 +--- src/Layer.js | 48 ++----------- src/Node.js | 17 +++-- src/Shape.js | 31 +-------- src/Stage.js | 2 + tests/assets/unitDataUrls.js | 1 + tests/js/unit/nodeTests.js | 131 ++++++++++++++++++++++++++++++----- 7 files changed, 135 insertions(+), 107 deletions(-) diff --git a/src/Container.js b/src/Container.js index 5caf22a4..b6fda05f 100644 --- a/src/Container.js +++ b/src/Container.js @@ -241,11 +241,11 @@ this.drawScene(); this.drawHit(); }, - drawScene: function() { + drawScene: function(canvas) { if(this.isVisible()) { var children = this.children, len = children.length; for(var n = 0; n < len; n++) { - children[n].drawScene(); + children[n].drawScene(canvas); } } }, @@ -256,14 +256,6 @@ children[n].drawHit(); } } - }, - drawBuffer: function(canvas) { - if(this.isVisible()) { - var children = this.children, len = children.length; - for(var n = 0; n < len; n++) { - children[n].drawBuffer(canvas); - } - } } }; Kinetic.Global.extend(Kinetic.Container, Kinetic.Node); diff --git a/src/Layer.js b/src/Layer.js index e55eb389..d3f45677 100644 --- a/src/Layer.js +++ b/src/Layer.js @@ -81,11 +81,12 @@ * @methodOf Kinetic.Layer.prototype * @param {Kinetic.Canvas} [canvas] */ - drawScene: function() { + drawScene: function(canvas) { + canvas = canvas || this.getCanvas(); if(this.attrs.clearBeforeDraw) { - this.getCanvas().clear(); + canvas.clear(); } - Kinetic.Container.prototype.drawScene.call(this); + Kinetic.Container.prototype.drawScene.call(this, canvas); }, /** * set before draw handler @@ -201,47 +202,6 @@ getLayer: function() { return this; }, - /** - * Creates a composite data URL. If MIME type is not - * 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 - * differently from toDataURL() for other nodes because it generates an absolute dataURL - * based on what's currently drawn on the layer, rather than drawing - * the current state of each child node - * @name toDataURL - * @methodOf Kinetic.Layer.prototype - * @param {Object} config - * @param {String} [config.mimeType] mime type. can be "image/png" or "image/jpeg". - * "image/png" is the default - * @param {Number} [config.width] data url image width - * @param {Number} [config.height] data url image height - * @param {Number} [config.quality] jpeg quality. If using an "image/jpeg" mimeType, - * you can specify the quality from 0 to 1, where 0 is very poor quality and 1 - * is very high quality - */ - toDataURL: function(config) { - var canvas; - var mimeType = config && config.mimeType ? config.mimeType : null; - var quality = config && config.quality ? config.quality : null; - - /* - * if layer is hidden, return blank canvas - * else if width and height are defined, create blank canvas and draw onto it - * else return canvas as is - */ - if(!this.isVisible()) { - var stage = this.getStage(); - canvas = new Kinetic.SceneCanvas(stage.getWidth(), stage.getHeight()); - } - else if(config && config.width && config.height) { - canvas = new Kinetic.SceneCanvas(config.width, config.height); - this.draw(canvas); - } - else { - canvas = this.getCanvas(); - } - return canvas.toDataURL(mimeType, quality); - }, /** * remove layer from stage */ diff --git a/src/Node.js b/src/Node.js index 696bf2c1..bb35844a 100644 --- a/src/Node.js +++ b/src/Node.js @@ -738,20 +738,25 @@ * is very high quality */ toDataURL: function(config) { - var mimeType = config && config.mimeType ? config.mimeType : null; - var quality = config && config.quality ? config.quality : null; - var canvas; + config = config || {}; + var mimeType = config.mimeType || null, quality = config.quality || null, canvas, context, x = config.x || 0, y = config.y || 0; - //if width and height are defined, create new canvas to draw on, else reuse stage hit canvas - if(config && config.width && config.height) { + //if width and height are defined, create new canvas to draw on, else reuse stage buffer canvas + if(config.width && config.height) { canvas = new Kinetic.SceneCanvas(config.width, config.height); } else { canvas = this.getStage().bufferCanvas; canvas.clear(); } + context = canvas.getContext(); + context.save(); + if(x || y) { + context.translate(-1 * x, -1 * y); + } + this.drawScene(canvas); + context.restore(); - this.drawBuffer(canvas); return canvas.toDataURL(mimeType, quality); }, /** diff --git a/src/Shape.js b/src/Shape.js index 56e6ff7c..063fada4 100644 --- a/src/Shape.js +++ b/src/Shape.js @@ -209,7 +209,7 @@ var stage = this.getStage(); var hitCanvas = stage.hitCanvas; hitCanvas.clear(); - this.drawBuffer(hitCanvas); + this.drawScene(hitCanvas); var p = hitCanvas.context.getImageData(Math.round(pos.x), Math.round(pos.y), 1, 1).data; return p[3] > 0; }, @@ -217,33 +217,8 @@ Kinetic.Node.prototype.remove.call(this); delete Kinetic.Global.shapes[this.colorKey]; }, - drawBuffer: function(canvas) { - var attrs = this.attrs, drawFunc = attrs.drawFunc, context = canvas.getContext(); - - if(drawFunc && this.isVisible()) { - var stage = this.getStage(), family = [], parent = this.parent; - - family.unshift(this); - while(parent) { - family.unshift(parent); - parent = parent.parent; - } - - context.save(); - canvas._applyOpacity(this); - canvas._applyLineJoin(this); - var len = family.length; - for(var n = 0; n < len; n++) { - var node = family[n], t = node.getTransform(), m = t.getMatrix(); - context.transform(m[0], m[1], m[2], m[3], m[4], m[5]); - } - - drawFunc.call(this, canvas); - context.restore(); - } - }, - drawScene: function() { - var attrs = this.attrs, drawFunc = attrs.drawFunc, canvas = this.getLayer().getCanvas(), context = canvas.getContext(); + drawScene: function(canvas) { + var attrs = this.attrs, drawFunc = attrs.drawFunc, canvas = canvas || this.getLayer().getCanvas(), context = canvas.getContext(); if(drawFunc && this.isVisible()) { var stage = this.getStage(), family = [], parent = this.parent; diff --git a/src/Stage.js b/src/Stage.js index 13db2946..62ef9cc4 100644 --- a/src/Stage.js +++ b/src/Stage.js @@ -193,6 +193,8 @@ var height = config && config.height ? config.height : this.attrs.height; var canvas = new Kinetic.SceneCanvas(width, height); var context = canvas.getContext(); + + var layers = this.children; function drawLayer(n) { diff --git a/tests/assets/unitDataUrls.js b/tests/assets/unitDataUrls.js index cc2b18a8..a42c3fab 100644 --- a/tests/assets/unitDataUrls.js +++ b/tests/assets/unitDataUrls.js @@ -4,6 +4,7 @@ * urls will be slightly different from browser to browser */ var dataUrls = { + 'cache shape, group, layer, and stage': 'data:image/png;base64,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', 'crop and scale image' : 'data:image/png;base64,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', 'rotate wedge': 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAkIAAADICAYAAAAEE46XAAAQFklEQVR4Xu3dP6xkVR0HcOgshWqtfEDhn2aRkGglixaGhmUjUSvYKIk0AlELC/8QbSgkgjSQSBQqY0TAhoRo6EgoUGiIjUoHlVDS6e/Ivrfv7p19+97vzcw9vzmfSSb73s6cO7/z+Z2XfDPn3pnrr3MjQIAAAQIECAwqcP2g8zZtAgQIECBAgMB1gpBFQIAAAQIECAwrIAgN23oTJ0CAAAECBAQha4AAAQIECBAYVkAQGrb1Jk6AAAECBAgIQtYAAQIECBAgMKyAIDRs602cAAECBAgQEISsAQIECBAgQGBYAUFo2NabOAECBAgQICAIWQMECBAgQIDAsAKC0LCtN3ECBAgQIEBAELIGCBAgQIAAgWEFBKFhW2/iBAgQIECAgCBkDRAgQIAAAQLDCghCw7bexAkQIECAAAFByBogQIAAAQIEhhUQhIZtvYkTIECAAAECgpA1QIAAAQIECAwrIAgN23oTJ0CAAAECBAQha4AAAQIECBAYVkAQGrb1Jk6AAAECBAgIQtYAAQIECBAgMKyAIDRs602cAAECBAgQEISsAQIECBAgQGBYAUFo2NabOAECBAgQICAIWQMECBAgQIDAsAKC0LCtN3ECBAgQIEBAELIGCBAgQIAAgWEFBKFhW2/iBAgQIECAgCBkDRAgQIAAAQLDCghCJ2/9J2PI3XG/J+5n437LyQ9hBAECBAgQINCDgCB0vC4cDj8Xrhjyhfj9reMdxrMIECBAgACBngQEoaO78el4+GeX3v254SpPfSj+/6memqoWAgQIECBA4HgCgtBqpzsuBaA7j8H4Zjzn9mM8z1MIECBAgACBzgQEoWlDzsevD8f9OAHo8Mib4pd3O+utcggQIECAAIFrCAhCHwO1d4B+G/cWaFbf2llCt166vxr/vjN5mu0xf2oECBAgQKCgwOhBqJ0D9Ku4X3kC9OVW7sWP5+Le/t2/vR0/vDjptu2xgotfyQQIECBAYOQg9NNo/yNxX30S9P67P4cD0P56+TB+eGK2eGyP+XsiQIAAAQLFBEYMQkdvg7UA1N4BalthR92eiQffmzzB9lixxa9cAgQIECAwWhB6PFr+/ZVtb+/8tI9IvFYA2h/8RvzwyuRItsf8PREgQIAAgWICowShdi7Qn+J+26w/LfjcFffPnLBztsdOCObpBAgQIECgP4ERglD7OozfxX1+LtC5+N8vxf0TycbYHkvCGUaAAAECBPoQ2PUgtHor7FOB3z4x6MwpmzDfHnshjnjvKY9qOAECBAgQILAlgV0NQm3D669xn2+FtW8G+9op3gU63JjV22Ptnaf2iBsBAgQIECDQucAuBqHV5wO17a92LlD7vvh13ubbY/fH4Z9f50s4FgECBAgQILAZgV0LQi3mvBb36flA69oKW9UD22ObWZmOSoAAAQIEtiCwS0FodQha51bYqoa8H//59OwB22NbWLxeggABAgQInFZgV4LQfQHRPut5+k5QC0HtpOhN356MF/hg8iK2xzZt7vgECBAgQGANArsQhFoIem5msa0Q1F64fQnr65MKXD22hsXpEAQIECBAYNMC1YPQ6u2w9hWq6z4p+qhO2B7b9Dp1fAIECBAgsBGBykGojxC03xbbYxtZoA5KgAABAgQ2KVA1CO0Fyt/iPj0naNvvBB3ujO2xTa5TxyZAgAABAhsRqBiEVn9Y4pIhqLVmvj3WTp++cSNdc1ACBAgQIEBgLQLVgtDqELTNE6OPYp9vj7Xvs395LZ1yEAIECBAgQGDtAtWC0LMh8O2JQi8hqBU13x5r9T6w9q45IAECBAgQILAWgUpBaH6ZfE8hqLXD9thaFqWDECBAgACBbQlUCULzK8Ta12a0jy1s3yHW0+2xKOajSUG2x3rqj1oIECBAgMAhgQpBaH5eUAs/F+N+psNe/jlqatezXb7ZHuuwTUoiQIAAAQJNoEIQmp8XtPQVYketnX/Eg7+fPMHVY/7WCBAgQIBApwK9B6G7w2161VVv5wWtaqztsU6Xu7IIECBAgMBUoOcg1LbE3oz7zQclt/OCvlughbbHCjRJiQQIECBAoO+tsZ9Eg35+0KR2XtCDcW/xqPfbfHvsX1HyLb2XrT4CBAgQIDCaQK/vCO1FI/49acad8dsdhdoz3x5rm3pvFZqBUgkQIECAwM4L9BqE/hLyXz3Qb98o9nCxXsy3xx6PGfyw2CyUS4AAAQIEdlqgxyA0/+DEi9GD9h5RpZvtsUrdUisBAgQIDCrQYxD6Z/Ti8gnSn4vfvlm0O7bHijZO2QQIECAwikBvQWj6blClE6RXrZg/xH++M3nA9tgof1nmSYAAAQIlBHoLQtN3g6qdIH1ly9+O/3hx8p+uHivxZ6FIAgQIEBhFoKcgNH836JFoQ2/fJXaSldG+c6xtj01vrh47iaHnEiBAgACBDQr0FISm7wbdFrNunytd/WZ7rHoH1U+AAAECOyzQSxA6H8YvTZzbu0EVPjzxWovD9ti1hDxOgAABAgQWE+glCE0/N2hX3g1qbV29PXZTPPLuYl33wgQIECBAgMD/BXoIQntRx/RTpHfl3aD9RTbfHnsoHnrKGiRAgAABAgSWFeghCH0vCH59wNDeK7l/WZS1v/p8e6x9mezta38dByRAgAABAgROJNBDEJqeJH0h6j97ojn0/2TbY/33SIUECBAgMKTA0kHo1lD/+0T+R/Fb5Uvmr7aMbI8N+Qdm0gQIECDQt8DSQeiXwfODA6LPx0/f6BssXd0bMfKVyWjbY2lMAwkQIECAwHoElg5C022xb8WkPrueiXV3lA+joidmVbl6rLtGKYgAAQIERhJYMghNt8XadljbFtvl2zMxufcmE3T12C7329wIECBAoHuBJYPQ9GqxXd4W218Gtse6/4NQIAECBAiMJbBkEPpjUH/9gPuu+OmLO45ve2zHG2x6BAgQIFBNYMkgND0/6MGgO1ONL1HvfHusfWrS84kjGUKAAAECBAicUmCpILQXdV/+NOkRzg/ab9R8e+yFeOjeU/bRcAIECBAgQCAhsFQQui9qfe6g3hHOD9qf7OrtsRvi4faIGwECBAgQILBFgaWC0G9ijt85mOcI5wcdbqrtsS0ucS9FgAABAgSuLrBUEJp+2/zFKHBvoDbZHhuo2aZKgAABAj0LLBWE/jtBebRnog3U9n4c8+nZcW2PbYDaIQkQIECAwFECgtBS6+PJeOEPJi/u6rGleuF1CRAgQGBYgSWC0LnQfu1A/Ob4qZ06Pdrt1Zjw65NJu3pstDVgvgQIECCwuMASQeh8zPqlg5mPdMXY4XbbHlt88SuAAAECBAgsEYR+HOy/OKD/Svz05UEbYXts0MabNgECBAj0IrBEEJpeOn8hKM72wrHlOubbY89GBQ9suQovR4AAAQIEhhVYIgiNfen80dtj7fTpG4ddjSZOgAABAgS2LCAIbRl89nLz7bF74jkvL12W1ydAgAABAiMICEJLd9n22NId8PoECBAgMLCAILR08+dXj9keW7onXp8AAQIEhhFYIgj9J3Tbpyh/fHt0GOurT/SxeOijycO2xywLAgQIECCwBYElgtD06zW2MMmCL+HqsYJNUzIBAgQI1BMQhPrsme2xPvuiKgIECBDYMQFBqN+G2h7rtzcqI0CAAIEdERCE+m2k7bF+e6MyAgQIENgRgSWC0I7QmQYBAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpAUEoTWcgAQIECBAgUF1AEKreQfUTIECAAAECaQFBKE1nIAECBAgQIFBdQBCq3kH1EyBAgAABAmkBQShNZyABAgQIECBQXUAQqt5B9RMgQIAAAQJpgf8BhIYJ2IsXVGgAAAAASUVORK5CYII=', 'wedge': 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAkIAAADICAYAAAAEE46XAAAP6klEQVR4Xu3dPaxlVRUH8EeHHXSE6kllaPiwIKEaxUxCIxISY8WQYAgNQtRECjUYLDTxg2CDBpOB0pAw0KCJItgoBSqNH83MsxE67LDTtYG5M5tzn7z9vB977/W7yU14j/POXeu3djL/3H3OvdcceBAgQIAAAQIEkgpck7RvbRMgQIAAAQIEDgQhi4AAAQIECBBIKyAIpR29xgkQIECAAAFByBogQIAAAQIE0goIQmlHr3ECBAgQIEBAELIGCBAgQIAAgbQCglDa0WucAAECBAgQEISsAQIECBAgQCCtgCCUdvQaJ0CAAAECBAQha4AAAQIECBBIKyAIpR29xgkQIECAAAFByBogQIAAAQIE0goIQmlHr3ECBAgQIEBAELIGCBAgQIAAgbQCglDa0WucAAECBAgQEISsAQIECBAgQCCtgCCUdvQaJ0CAAAECBAQha4AAAQIECBBIKyAIpR29xgkQIECAAAFByBogQIAAAQIE0goIQmlHr3ECBAgQIEBAELIGCBAgQIAAgbQCglDa0WucAAECBAgQEISsAQIECBAgQCCtgCCUdvQaJ0CAAAECBAQha4AAAQIECBBIKyAIpR29xgkQIECAAAFByBogQIAAAQIE0goIQmlHr3ECBAgQIEBAELIGCBAgQIAAgbQCglDa0WucAAECBAgQEISsAQIECBAgQCCtgCCUdvQaJ0CAAAECBAQha4AAAQIECBBIKyAIpR29xgkQIECAAAFByBogQIAAAQIE0goIQmlHr3ECBAgQIEBAELIGCBAgQIAAgbQCglDa0WucAAECBAgQEISsAQIECBAgQCCtgCCUdvQaJ0CAAAECBAQha4AAAQIECBBIKyAIpR29xgkQIECAAAFByBogQIAAAQIE0goIQmlHr3ECBAgQIEBAELIGCBAgQIAAgbQCglDa0WucAAECBAgQEISsAQIECBAgQCCtgCCUdvQaJ0CAAAECBAQha4AAAQIECBBIKyAIpR29xgkQIECAAAFByBogQIAAAQIE0goIQmlHr3ECBAgQIEBAELIGCBAgQIAAgbQCglDa0WucAAECBAgQEISsAQIECBAgQCCtgCCUdvQaJ0CAAAECBAQha4AAAQIECBBIKyAIpR29xgkQIECAAAFByBogQIAAAQIE0goIQmlHr3ECBAgQIEBAELIGCBAgQIAAgbQCglDa0WucAAECBAgQEISsAQIECBAgQCCtgCCUdvQaJ0CAAAECBAQha4AAAQIECBBIKyAIpR29xgkQIECAAAFByBogQIAAAQIE0goIQmlHr3ECBAgQIEBAELIGCBAgQIAAgbQCglDa0WucAAECBAgQEISsAQIECBAgQCCtgCCUdvQaJ0CAAAECBAQha4AAAQIECBBIKyAIpR29xgkQIECAAAFByBogQIAAAQIE0goIQmlHr3ECBAgQIEBAELIGCBAgQIAAgbQCglDa0WucAAECBAgQEISsAQIECBAgQCCtgCCUdvQaJ0CAAAECBAQha4AAAQIECBBIKyAIpR29xgkQIECAAAFByBogQIAAAQIE0goIQmlHr3ECBAgQIEBAELIGCBAgQIAAgbQCglDa0WucAAECBAgQEISsAQIECBAgQCCtgCCUdvQaJ0CAAAECBAQha4AAAQIECBBIKyAIpR29xgkQIECAAAFByBogQIAAAQIE0goIQmlHr3ECBAgQIEBAELIGCBAgQIAAgbQCglDa0WucAAECBAgQEISsAQIECBAgQCCtgCCUdvQaJ0CAAAECBAShPtbAs1HGg32U0n0V1mz3I1IgAQIExhHwj0ofs7onyrjQRyndV2HNdj8iBRIgQGAcAf+o9DOrd6OU6/opp9tKrNluR6MwAgQIjCfgH5V+ZmZ77GSzsGZP5uQoAgQIEDiBgH9UToC0o0Pq7bHr41Uf3dEr9/oy/47CvlcVdyl+uqnXctVFgAABAuMJCEJ9zazeHns4iruhrwJ3Ws1RvNr56hV/Ez99bqc1eDECBAgQmFpAEOprvPX22J1R3Nm+CtxpNYLQTrm9GAECBDIKCEJ9Td322NXzEIT6Wp2qIUCAwIQCglB/Q7U9dnkmglB/q1NFBAgQmExAEOpvoC9ESfetysq8PfZWKLxYDejn8dOX+xuZiggQIEBgVAFBqL/J3R8lPbcqK/PdY78LhVerAX0rfvpufyNTEQECBAiMKiAI9Te58qGKZXvsyiPr3WO/CIK/VBJfiJ9e6m9kKiJAgACBUQUEoT4nZ3uszOX5eF6sBvSZ+Om1PkemKgIECBAYUUAQ6nNqtsfKXJ5YDMd67XO9qooAAQLDCviHpc/RLbfHHotCM30T2fJTpf8VAuWKKQ8CBAgQILAxAUFoY5QbP1G9PXZ3nP+Ojb9Gvyc8itLOV+X5VOl+p6UyAgQIDCsgCPU7unp77MYo9KF+i914ZW/EGV+pzurW+Y0jOyEBAgQICEL9roHc22PLO8bOxajK5dMeBAgQIEBgYwKC0MYot3KivNtj3w/P9yrTT8ZPR1tRdlICBAgQSCsgCPU9+keivKdXJWbZHnsnOn6mGsyl+OmmvkelOgIECBAYUUAQ6ntqh1FeCQFXHhnuHnN9UN+rUnUECBCYSEAQ6n+Yb0aJt6/KzHD32PL6oK9E/z/pf1QqJECAAIHRBASh/ieWb3tseX3QbTGmP/c/KhUSIECAwGgCglD/EzuMEvNsjy2/cd71Qf2vURUSIEBgWAFBaIzR1dtj90bRt4xReHOVy22xH8Y5vt58Hn9AgAABAgROICAInQCpg0Pq7bGbo6IvdlDVpktYfq1GeQXbYpt2dj4CBAgQWAkIQmMshsMos94eezx+c+0YxZ+4yuW22B/jbz994r93IAECBAgQaBQQhBrB9nj4/NtjPwvdf1bC7hbb44Lz0gQIEMggIAiNM+W5t8fKd8s/tRiGT5MeZ32qlAABAkMKCELjjO3WKPVPVbkzbY+9HJ2VjbArj1fjP+8aZzwqJUCAAIERBQShsaZ2Mcot75J88Jjl7rH17wadiQ5fH2s8qiVAgACB0QQEobEm9oMo92urkme5e2z5bpDPDhprXaqWAAECwwoIQmONbr7tsfW3zJ+LsTw/1mhUS4AAAQIjCghC402t3h77UjTwqfGaWFVcNr9+W9Xv3aCBx6l0AgQIjCYgCI02sYODenusfB3r58dr4v2Ky7VBP43ne1X93g0adJzKJkCAwIgCgtB4U6u3xz4RDXxjvCber3j5dRreDRp0lMomQIDAqAKC0JiTG3977Cjgzy/w74nflEunPQgQIECAwE4EBKGdMG/8RcbeHisXSJctsXcrF58btPFl4oQECBAg8HECgtDHCfX5/89EWVcuMR5te2x5gXRR9inSfa41VREgQGBqAUFo3PGW91OuW5U/yt1j70TFzyzQvx2/eXLcUaicAAECBEYVEIRGndzBwbNR+oOr8ke4e6xsiT0Xz7cr9HKBdKm+3EPmQYAAAQIEdiogCO2Ue6MvVi4svrA64wjbYy9FtfW3pZXyXSC90WXhZAQIECDQIiAItWj1d+w422NvBd6LC8AfxW+ufGVIf74qIkCAAIHJBQShsQdcb4/dGc2c7bChcl1Q2RKrPzixvDdUtsQ8CBAgQIDA3gQEob3Rb+SF6+2x6+Ocj27kvJs7yfrrgsr1QLfF82hzL+RMBAgQIECgXUAQajfr7S/q7bGHo7wbOirRdUEdDUMpBAgQIPBRAUFo/DXR7/bY+hDkuqDx15wOCBAgMI2AIDT+KPvcHlsfglwXNP560wEBAgSmEhCE5hjnf6o29r09tv4OsRKCPhtPnxc0x5rTBQECBKYQEISmGOPBC9HGfatW9nn32PoQVMJP+QoNIWiO9aYLAgQITCMgCM0xyvujjXKD+gePfd09dnwIOhNVlf/rQYAAAQIEuhIQhLoax6mLKd85Vn+X+663x96ICl5Z1F/eARKCTj1Wf0iAAAEC2xYQhLYtvLvz7297bP2F0aVzX5+xu/l7JQIECBA4hYAgdAq0Tv+k3h67Map8aAeVrg9B5Z2gc/F8eQcVeAkCBAgQIHBqAUHo1HTd/eFye+yxqLH8dhuP8onRJQT9dXFy22Hb8HZOAgQIENiKgCC0Fda9nbTeHrs76rhjC7WU7w4rIehtIWgLuk5JgAABAjsUEIR2iL2Dl9r+9li59+uX8ay/QLW05nOCdjBgL0GAAAECmxUQhDbrue+zbW97rGyF/erDuLPsUgja9+S9PgECBAicSkAQOhVb13/066jurlWFm9geO34rrLzMj+P51a5FFEeAAAECBI4REITmWxqPREtPr9r6f+4eK+8CvR7P369FcmfYfGtHRwQIEEgnIAjNN/LDaOlS1dZp7h77e5yhXAtUf0zj5dOWrbB74/mP+fh0RIAAAQKZBAShOaf9ZrR1+6q1lu2x8j5PuSOsjlJXK9kKm3PN6IoAAQIpBQShOcfevj1WAlDZBivv9ax/HMWvH/jwqDnVdEWAAAEC6QQEoTlHfrh4T+fx+M21a5ot8aZ8T9jygxEvH1wi0lPx/M6cVLoiQIAAgcwCgtC806+3x8oVPbdc1ezfPgxAx2+BlYMvxLNcYeRaoHnXic4IECCQWkAQmnf89fbYzdHo2Xj+IZ7lQuj1F0Ff1jiK/3ggnmWzzIMAAQIECEwrIAhNO9qDw2jtf7/fs+z9tfjVEwLQvItCZwQIECBQCwhCc6+Ienvs+F4FoLnXge4IECBA4BgBQWjupfHNaO/JY1osF0GXa4DKO0CuAZp7HeiOAAECBAShlGvg1uj6ozfEl/BTnuXTgkoY8iBAgAABAmkFvCM0/+gvRovlO+OFn/lnrUMCBAgQaBQQhBrBHE6AAAECBAjMIyAIzTNLnRAgQIAAAQKNAoJQI5jDCRAgQIAAgXkEBKF5ZqkTAgQIECBAoFFAEGoEczgBAgQIECAwj4AgNM8sdUKAAAECBAg0CghCjWAOJ0CAAAECBOYREITmmaVOCBAgQIAAgUYBQagRzOEECBAgQIDAPAKC0Dyz1AkBAgQIECDQKCAINYI5nAABAgQIEJhHQBCaZ5Y6IUCAAAECBBoFBKFGMIcTIECAAAEC8wgIQvPMUicECBAgQIBAo4Ag1AjmcAIECBAgQGAeAUFonlnqhAABAgQIEGgUEIQawRxOgAABAgQIzCMgCM0zS50QIECAAAECjQKCUCOYwwkQIECAAIF5BASheWapEwIECBAgQKBRQBBqBHM4AQIECBAgMI+AIDTPLHVCgAABAgQINAoIQo1gDidAgAABAgTmERCE5pmlTggQIECAAIFGAUGoEczhBAgQIECAwDwCgtA8s9QJAQIECBAg0CggCDWCOZwAAQIECBCYR0AQmmeWOiFAgAABAgQaBQShRjCHEyBAgAABAvMICELzzFInBAgQIECAQKOAINQI5nACBAgQIEBgHoH/AqIULtgLfRnlAAAAAElFTkSuQmCC', diff --git a/tests/js/unit/nodeTests.js b/tests/js/unit/nodeTests.js index 7cbc457d..8f5a8d96 100644 --- a/tests/js/unit/nodeTests.js +++ b/tests/js/unit/nodeTests.js @@ -770,23 +770,116 @@ Test.Modules.NODE = { } }); - /* - group.toImage({ - callback: function(imageObj) { - test(Kinetic.Type._isElement(imageObj), 'group toImage() should be an image object'); - } - }); - layer.toImage({ - callback: function(imageObj) { - test(Kinetic.Type._isElement(imageObj), 'layer toImage() should be an image object'); - } - }); - stage.toImage({ - callback: function(imageObj) { - test(Kinetic.Type._isElement(imageObj), 'stage toImage() should be an image object'); - } - }); - */ + showHit(layer); + }, + 'cache shape, group, layer, and stage': function(containerId) { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + var layer = new Kinetic.Layer(); + var group = new Kinetic.Group(); + var rect = new Kinetic.Rect({ + x: 10, + y: 10, + width: 50, + height: 30, + fill: 'green', + stroke: 'black', + strokeWidth: 4, + draggable: true + }); + + group.add(rect); + layer.add(group); + stage.add(layer); + + // cache shape + rect.toImage({ + x: 8, + y: 8, + width: 54, + height: 34, + callback: function(imageObj) { + var cachedShape = new Kinetic.Image({ + image: imageObj, + x: 60, + y: 60, + draggable: true + }); + group.add(cachedShape); + layer.draw(); + + // cache group + group.toImage({ + x: 8, + y: 8, + width: 106, + height: 86, + callback: function(imageObj) { + var cachedGroup = new Kinetic.Image({ + image: imageObj, + x: 100, + y: 8, + draggable: true + }); + group.add(cachedGroup); + layer.draw(); + + + // cache layer + layer.toImage({ + x: 8, + y: 8, + width: 200, + height: 86, + callback: function(imageObj) { + + var cachedLayer = new Kinetic.Image({ + image: imageObj, + x: 190, + y: 8, + draggable: true + }); + group.add(cachedLayer); + layer.draw(); + + + var dataUrl = layer.toDataURL(); + + // cache stage + + stage.toImage({ + x: 8, + y: 8, + width: 400, + height: 86, + callback: function(imageObj) { + + var cachedStage = new Kinetic.Image({ + image: imageObj, + x: 8, + y: 100, + draggable: true + }); + group.add(cachedStage); + layer.draw(); + + var dataUrl = layer.toDataURL(); + //console.log(dataUrl); + + warn(dataUrl === dataUrls['cache shape, group, layer, and stage'], 'problem caching shape, group, layer, and stage'); + } + }); + + + } + }); + } + }); + } + }); showHit(layer); }, @@ -2009,7 +2102,7 @@ Test.Modules.NODE = { var group = new Kinetic.Group(); var drawTriangle = function(canvas) { - var context = canvas.getContext(); + var context = canvas.getContext(); context.beginPath(); context.moveTo(200, 50); context.lineTo(420, 80); @@ -2053,7 +2146,7 @@ Test.Modules.NODE = { }, 'load stage with custom shape using json': function(containerId) { var drawTriangle = function(canvas) { - var context = canvas.getContext(); + var context = canvas.getContext(); context.beginPath(); context.moveTo(200, 50); context.lineTo(420, 80);