From e39d7861c324948980c2ae51eb4fae0bff153f68 Mon Sep 17 00:00:00 2001 From: lavrton Date: Thu, 12 Feb 2015 14:10:36 +0700 Subject: [PATCH] Add new method `getClientRect()`. rethink caching. --- src/Canvas.js | 2 +- src/Container.js | 35 +- src/Node.js | 155 ++++--- src/Shape.js | 83 +++- src/Util.js | 2 +- src/plugins/Label.js | 28 ++ src/plugins/Path.js | 24 ++ src/plugins/RegularPolygon.js | 22 + src/plugins/Star.js | 23 + src/plugins/TextPath.js | 29 ++ src/shapes/Arc.js | 23 + src/shapes/Circle.js | 8 +- src/shapes/Ellipse.js | 1 + src/shapes/Line.js | 33 ++ src/shapes/Ring.js | 1 + src/shapes/Wedge.js | 23 + test/functional/MouseEvents-test.js | 12 +- test/manual/manual-test.js | 43 ++ test/runner.html | 3 +- test/runner.js | 44 +- test/unit/Layer-test.js | 9 + test/unit/Node-cache-test.js | 509 +++++++++++++++++++++++ test/unit/Node-test.js | 352 ---------------- test/unit/plugins/Label-test.js | 118 ++++++ test/unit/plugins/Path-test.js | 49 +++ test/unit/plugins/RegularPolygon-test.js | 60 +++ test/unit/plugins/Star-test.js | 75 +++- test/unit/plugins/TextPath-test.js | 27 ++ test/unit/shapes/Arc-test.js | 88 ++++ test/unit/shapes/Blob-test.js | 23 + test/unit/shapes/Circle-test.js | 52 ++- test/unit/shapes/Ellipse-test.js | 85 +++- test/unit/shapes/Image-test.js | 34 ++ test/unit/shapes/Line-test.js | 69 +++ test/unit/shapes/Ring-test.js | 48 ++- test/unit/shapes/Text-test.js | 22 + test/unit/shapes/Wedge-test.js | 52 +++ 37 files changed, 1813 insertions(+), 453 deletions(-) create mode 100644 test/unit/Node-cache-test.js diff --git a/src/Canvas.js b/src/Canvas.js index b600f949..7dd3fb14 100644 --- a/src/Canvas.js +++ b/src/Canvas.js @@ -80,7 +80,7 @@ * @memberof Konva.Canvas.prototype * @param {Number} pixelRatio KonvaJS automatically handles pixel ratio adustments in order to render crisp drawings * on all devices. Most desktops, low end tablets, and low end phones, have device pixel ratios - * of 1. Some high end tablets and phones, like iPhones and iPads (not the mini) have a device pixel ratio + * of 1. Some high end tablets and phones, like iPhones and iPads have a device pixel ratio * of 2. Some Macbook Pros, and iMacs also have a device pixel ratio of 2. Some high end Android devices have pixel * ratios of 2 or 3. Some browsers like Firefox allow you to configure the pixel ratio of the viewport. Unless otherwise * specificed, the pixel ratio will be defaulted to the actual device pixel ratio. You can override the device pixel diff --git a/src/Container.js b/src/Container.js index b432743f..14e6dbbc 100644 --- a/src/Container.js +++ b/src/Container.js @@ -303,7 +303,7 @@ child.index = n; }); }, - drawScene: function(can, top) { + drawScene: function(can, top, caching) { var layer = this.getLayer(), canvas = can || (layer && layer.getCanvas()), context = canvas && canvas.getContext(), @@ -311,8 +311,11 @@ cachedSceneCanvas = cachedCanvas && cachedCanvas.scene; if (this.isVisible()) { - if (cachedSceneCanvas) { + if (!caching && cachedSceneCanvas) { + context.save(); + layer._applyTransform(this, context, top); this._drawCachedSceneCanvas(context); + context.restore(); } else { this._drawChildren(canvas, 'drawScene', top); @@ -320,7 +323,7 @@ } return this; }, - drawHit: function(can, top) { + drawHit: function(can, top, caching) { var layer = this.getLayer(), canvas = can || (layer && layer.hitCanvas), context = canvas && canvas.getContext(), @@ -331,8 +334,11 @@ if (layer) { layer.clearHitCache(); } - if (cachedHitCanvas) { + if (!caching && cachedHitCanvas) { + context.save(); + layer._applyTransform(this, context, top); this._drawCachedHitCanvas(context); + context.restore(); } else { this._drawChildren(canvas, 'drawHit', top); @@ -374,6 +380,27 @@ var layerUnderDrag = dd && Konva.isDragging() && (Konva.DD.anim.getLayers().indexOf(layer) !== -1); return (canvas && canvas.isCache) || (layer && layer.hitGraphEnabled()) && this.isVisible() && !layerUnderDrag; + }, + getClientRect : function(skipTransform) { + var minX, minY, maxX, maxY; + this.children.each(function(child) { + var rect = child.getClientRect(); + minX = Math.min(minX, rect.x) || rect.x; + minY = Math.min(minY, rect.y) || rect.y; + maxX = Math.max(maxX, rect.x + rect.width) || (rect.x + rect.width); + maxY = Math.max(maxY, rect.y + rect.height) || (rect.y + rect.height); + }); + + var rect = { + x : minX, + y : minY, + width : maxX - minX, + height : maxY - minY + }; + if (!skipTransform) { + return this._transformedRect(rect); + } + return rect; } }); diff --git a/src/Node.js b/src/Node.js index 09eb4a77..b69efb43 100644 --- a/src/Node.js +++ b/src/Node.js @@ -139,37 +139,47 @@ * y: -30, * width: 100, * height: 200, + * offset : 10, * drawBorder: true * }); */ cache: function(config) { var conf = config || {}, - x = conf.x || 0, - y = conf.y || 0, - width = conf.width || this.width(), - height = conf.height || this.height(), + rect = this.getClientRect(true), + width = conf.width || rect.width, + height = conf.height || rect.height, + x = conf.x || rect.x, + y = conf.y || rect.y, + offset = conf.offset || 0, drawBorder = conf.drawBorder || false; - if (width === 0 || height === 0) { - Konva.Util.warn('Width or height of caching configuration equals 0. Cache is ignored.'); - return; + if (!width || !height) { + throw new Error('Width or height of caching configuration equals 0.'); } + + width += offset * 2; + height += offset * 2; + + x -= offset; + y -= offset; + + var cachedSceneCanvas = new Konva.SceneCanvas({ - pixelRatio: 1, - width: width, - height: height - }), - cachedFilterCanvas = new Konva.SceneCanvas({ - pixelRatio: 1, - width: width, - height: height - }), - cachedHitCanvas = new Konva.HitCanvas({ - width: width, - height: height - }), - sceneContext = cachedSceneCanvas.getContext(), - hitContext = cachedHitCanvas.getContext(); + pixelRatio: 1, + width: width, + height: height + }), + cachedFilterCanvas = new Konva.SceneCanvas({ + pixelRatio: 1, + width: width, + height: height + }), + cachedHitCanvas = new Konva.HitCanvas({ + width: width, + height: height + }), + sceneContext = cachedSceneCanvas.getContext(), + hitContext = cachedHitCanvas.getContext(); cachedHitCanvas.isCache = true; @@ -178,6 +188,15 @@ sceneContext.save(); hitContext.save(); + sceneContext.translate(-x, -y); + hitContext.translate(-x, -y); + + this.drawScene(cachedSceneCanvas, this, true); + this.drawHit(cachedHitCanvas, this, true); + + sceneContext.restore(); + hitContext.restore(); + // this will draw a red border around the cached box for // debugging purposes if (drawBorder) { @@ -191,36 +210,80 @@ sceneContext.restore(); } - sceneContext.translate(x * -1, y * -1); - hitContext.translate(x * -1, y * -1); - - // don't need to translate canvas if shape is not added to layer - if (this.nodeType === 'Shape') { - sceneContext.translate(this.x() * -1, this.y() * -1); - hitContext.translate(this.x() * -1, this.y() * -1); - } - - this.drawScene(cachedSceneCanvas, this); - this.drawHit(cachedHitCanvas, this); - - sceneContext.restore(); - hitContext.restore(); - this._cache.canvas = { scene: cachedSceneCanvas, filter: cachedFilterCanvas, - hit: cachedHitCanvas + hit: cachedHitCanvas, + x : x, + y : y }; return this; }, + /** + * return client rectangle (x, y, width, height) of node. This rectangle also include all styling (strokes, shadows, etc) + * @method + * @memberof Konva.Node.prototype + * @param {Boolean} [skipTransform] flag should we apply transformation to rectangle + * @returns {Object} rect with {x, y, width, height} properties + * @example + * + * circle.getClientRect(true); + */ + getClientRect : function() { + // abstract method + // redefine in Container and Shape + throw 'abstract "getClientRect" method call'; + }, + _transformedRect : function(rect) { + var points = [ + {x : rect.x, y : rect.y}, + {x : rect.x + rect.width, y : rect.y}, + {x : rect.x + rect.width, y : rect.y + rect.height}, + {x : rect.x, y : rect.y + rect.height} + ]; + var minX, minY, maxX, maxY; + var trans = this.getTransform(); + points.forEach(function(point) { + var transformed = trans.point(point); + if (minX === undefined) { + minX = maxX = transformed.x; + minY = maxY = transformed.y; + } + minX = Math.min(minX, transformed.x); + minY = Math.min(minY, transformed.y); + maxX = Math.max(maxX, transformed.x); + maxY = Math.max(maxY, transformed.y); + }); + return { + x : Math.round(minX), + y : Math.round(minY), + width : Math.round(maxX - minX), + height : Math.round(maxY - minY) + }; + }, _drawCachedSceneCanvas: function(context) { context.save(); - this.getLayer()._applyTransform(this, context); - context._applyOpacity(this); + + context.translate( + this._cache.canvas.x, + this._cache.canvas.y + ); + context.drawImage(this._getCachedSceneCanvas()._canvas, 0, 0); context.restore(); }, + _drawCachedHitCanvas: function(context) { + var cachedCanvas = this._cache.canvas, + hitCanvas = cachedCanvas.hit; + context.save(); + context.translate( + this._cache.canvas.x, + this._cache.canvas.y + ); + context.drawImage(hitCanvas._canvas, 0, 0); + context.restore(); + }, _getCachedSceneCanvas: function() { var filters = this.filters(), cachedCanvas = this._cache.canvas, @@ -258,15 +321,6 @@ return sceneCanvas; } }, - _drawCachedHitCanvas: function(context) { - var cachedCanvas = this._cache.canvas, - hitCanvas = cachedCanvas.hit; - - context.save(); - this.getLayer()._applyTransform(this, context); - context.drawImage(hitCanvas._canvas, 0, 0); - context.restore(); - }, /** * bind events to the node. KonvaJS supports mouseover, mousemove, * mouseout, mouseenter, mouseleave, mousedown, mouseup, mousewheel, click, dblclick, touchstart, touchmove, @@ -1348,6 +1402,9 @@ width: this.getWidth(), height: this.getHeight() }; + }, + getTransformedSize : function() { + }, getWidth: function() { return this.attrs.width || 0; diff --git a/src/Shape.js b/src/Shape.js index 3bca22c8..e70ae603 100644 --- a/src/Shape.js +++ b/src/Shape.js @@ -143,11 +143,58 @@ delete Konva.shapes[this.colorKey]; }, _useBufferCanvas: function() { -// return false; return (this.perfectDrawEnabled() && (this.getAbsoluteOpacity() !== 1) && this.hasFill() && this.hasStroke() && this.getStage()) || (this.perfectDrawEnabled() && this.hasShadow() && (this.getAbsoluteOpacity() !== 1) && this.hasFill() && this.hasStroke() && this.getStage()); }, - drawScene: function(can, top) { + /** + * return self rectangle (x, y, width, height) of shape. + * This method are not taken into account transformation and styles. + * @method + * @memberof Konva.Node.prototype + * @returns {Object} rect with {x, y, width, height} properties + * @example + * + * rect.getSelfRect(); // return {x:0, y:0, width:rect.width(), height:rect.height()} + * circle.getSelfRect(); // return {x: - circle.width() / 2, y: - circle.height() / 2, width:circle.width(), height:circle.height()} + * + */ + getSelfRect : function() { + var size = this.getSize(); + return { + x : this._centroid ? Math.round(-size.width / 2) : 0, + y : this._centroid ? Math.round(-size.height / 2) : 0, + width : size.width, + height : size.height + }; + }, + getClientRect : function(skipTransform) { + var fillRect = this.getSelfRect(); + var strokeWidth = (this.hasStroke() && this.strokeWidth()) || 0; + var fillAndStrokeWidth = fillRect.width + strokeWidth; + var fillAndStrokeHeight = fillRect.height + strokeWidth; + + var shadowOffsetX = this.shadowOffsetX(); + var shadowOffsetY = this.shadowOffsetY(); + + var preWidth = fillAndStrokeWidth + Math.abs(shadowOffsetX); + var preHeight = fillAndStrokeHeight + Math.abs(shadowOffsetY); + + var blurRadius = (this.hasShadow() && this.shadowBlur() || 0); + + var width = preWidth + blurRadius * 2; + var height = preHeight + blurRadius * 2; + var rect = { + width : width, + height : height, + x : -Math.round(strokeWidth / 2 + blurRadius) + Math.min(shadowOffsetX, 0) + fillRect.x, + y : -Math.round(strokeWidth / 2 + blurRadius) + Math.min(shadowOffsetY, 0) + fillRect.y + }; + if (!skipTransform) { + return this._transformedRect(rect); + } + return rect; + }, + drawScene: function(can, top, caching) { var layer = this.getLayer(), canvas = can || layer.getCanvas(), context = canvas.getContext(), @@ -159,7 +206,10 @@ if(this.isVisible()) { if (cachedCanvas) { + context.save(); + layer._applyTransform(this, context, top); this._drawCachedSceneCanvas(context); + context.restore(); } else if (drawFunc) { context.save(); @@ -210,11 +260,13 @@ else { context._applyLineJoin(this); // layer might be undefined if we are using cache before adding to layer - if (layer) { - layer._applyTransform(this, context, top); - } else { - var o = this.getAbsoluteTransform(top).getMatrix(); - context.transform(o[0], o[1], o[2], o[3], o[4], o[5]); + if (!caching) { + if (layer) { + layer._applyTransform(this, context, top); + } else { + var o = this.getAbsoluteTransform(top).getMatrix(); + context.transform(o[0], o[1], o[2], o[3], o[4], o[5]); + } } if (hasShadow && hasStroke && !canvas.hitCanvas) { @@ -247,7 +299,7 @@ return this; }, - drawHit: function(can, top) { + drawHit: function(can, top, caching) { var layer = this.getLayer(), canvas = can || layer.hitCanvas, context = canvas.getContext(), @@ -260,16 +312,21 @@ layer.clearHitCache(); } if (cachedHitCanvas) { + context.save(); + layer._applyTransform(this, context, top); this._drawCachedHitCanvas(context); + context.restore(); } else if (drawFunc) { context.save(); context._applyLineJoin(this); - if (layer) { - layer._applyTransform(this, context, top); - } else { - var m = this.getAbsoluteTransform(top).getMatrix(); - context.transform(m[0], m[1], m[2], m[3], m[4], m[5]); + if (!caching) { + if (layer) { + layer._applyTransform(this, context, top); + } else { + var o = this.getAbsoluteTransform(top).getMatrix(); + context.transform(o[0], o[1], o[2], o[3], o[4], o[5]); + } } drawFunc.call(this, context); diff --git a/src/Util.js b/src/Util.js index b31044f1..a55e9220 100644 --- a/src/Util.js +++ b/src/Util.js @@ -98,7 +98,7 @@ /* * The usage of this class was inspired by some of the work done by a forked - * project, KonvaJS-Ext by Wappworks, which is based on Simon's Transform + * project, KineticJS-Ext by Wappworks, which is based on Simon's Transform * class. Modified by Eric Rowell */ diff --git a/src/plugins/Label.js b/src/plugins/Label.js index d79cebc5..8f791560 100644 --- a/src/plugins/Label.js +++ b/src/plugins/Label.js @@ -241,6 +241,34 @@ context.closePath(); context.fillStrokeShape(this); + }, + getSelfRect : function() { + var x = 0, + y = 0, + pointerWidth = this.getPointerWidth(), + pointerHeight = this.getPointerHeight(), + direction = this.pointerDirection(), + width = this.getWidth(), + height = this.getHeight(); + + if (direction === UP) { + y -= pointerHeight; + height += pointerHeight; + } else if (direction === DOWN) { + height += pointerHeight; + } else if (direction === LEFT) { + // ARGH!!! I have no idea why should I used magic 1.5!!!!!!!!! + x -= pointerWidth * 1.5; + width += pointerWidth; + } else if (direction === RIGHT) { + width += pointerWidth * 1.5; + } + return { + x : x, + y : y, + width : width, + height : height + }; } }; diff --git a/src/plugins/Path.js b/src/plugins/Path.js index 5c20c162..c2b2000a 100644 --- a/src/plugins/Path.js +++ b/src/plugins/Path.js @@ -89,6 +89,30 @@ else { context.strokeShape(this); } + }, + getSelfRect : function() { + var points = []; + this.dataArray.forEach(function(data) { + points = points.concat(data.points); + }); + var minX = points[0]; + var maxX = points[0]; + var minY = points[0]; + var maxY = points[0]; + var x,y; + for (var i = 0; i - + + diff --git a/test/runner.js b/test/runner.js index 98cdc053..c823b02e 100644 --- a/test/runner.js +++ b/test/runner.js @@ -64,7 +64,7 @@ function init() { Konva.enableTrace = true; -Konva.showWarnings = false; +Konva.showWarnings = true; function addStats() { stats = new Stats(); @@ -115,15 +115,16 @@ function get (element, content) { } return element; } - -function compareLayerAndCanvas(layer, canvas, tol) { - var equal = imagediff.equal(layer.getCanvas()._canvas, canvas, tol); +function compareCanvases(canvas1, canvas2, tol) { + // don't test in PhantomJS as it use old chrome engine + // it it has opacity + shadow bug + var equal = imagediff.equal(canvas1, canvas2, tol); if (!equal) { var div = get('div'), b = get('div', '
Expected:
'), c = get('div', '
Diff:
'), - diff = imagediff.diff(layer.getCanvas()._canvas, canvas), + diff = imagediff.diff(canvas1, canvas2), diffCanvas = get('canvas'), context; @@ -134,18 +135,47 @@ function compareLayerAndCanvas(layer, canvas, tol) { b.style.float = 'left'; c.style.float = 'left'; + canvas2.style.position = ''; + canvas2.style.display = ''; + context = diffCanvas.getContext('2d'); context.putImageData(diff, 0, 0); - b.appendChild(canvas); + b.appendChild(canvas2); c.appendChild(diffCanvas); div.appendChild(b); div.appendChild(c); konvaContainer.appendChild(div); } - assert.equal(equal, true); + assert.equal(equal, true, 'Result from Konva is different with canvas result'); +} +function compareLayerAndCanvas(layer, canvas, tol) { + compareCanvases(layer.getCanvas()._canvas, canvas, tol); +} + +function compareLayers(layer1, layer2, tol) { + compareLayerAndCanvas(layer1, layer2.getCanvas()._canvas, tol); +} + +function cloneAndCompareLayer(layer, tol) { + var layer2 = layer.clone(); + layer.getStage().add(layer2); + layer2.hide(); + compareLayers(layer, layer2, tol); +} + +function cloneAndCompareLayerWithHit(layer, tol) { + var layer2 = layer.clone(); + layer.getStage().add(layer2); + layer2.hide(); + compareLayers(layer, layer2, tol); + compareCanvases(layer.getHitCanvas()._canvas, layer2.getHitCanvas()._canvas, tol); +} + +function compareSceneAndHit(layer) { + compareLayerAndCanvas(layer, layer.getHitCanvas()._canvas, 254); } function addContainer() { diff --git a/test/unit/Layer-test.js b/test/unit/Layer-test.js index 6df65a8e..93268cc0 100644 --- a/test/unit/Layer-test.js +++ b/test/unit/Layer-test.js @@ -350,4 +350,13 @@ suite('Layer', function() { // after drawing group hit cache should be cleared assert.equal(count, 2, 'while creating new cache getImageData should be called'); }); + + it('get/set layer size', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + stage.add(layer); + assert.deepEqual(layer.size(), stage.size()); + assert.equal(layer.width(), stage.width()); + assert.equal(layer.height(), stage.height()); + }); }); \ No newline at end of file diff --git a/test/unit/Node-cache-test.js b/test/unit/Node-cache-test.js new file mode 100644 index 00000000..b82cacc3 --- /dev/null +++ b/test/unit/Node-cache-test.js @@ -0,0 +1,509 @@ +suite('Caching', function() { + + // CACHING SHAPE + + test('cache simple rectangle', function() { + var stage = addStage(); + + var layer = new Konva.Layer(); + + var rect = new Konva.Rect({ + x: 100, + y: 50, + width: 100, + height: 50, + fill: 'green' + }); + rect.cache(); + + layer.add(rect); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + context.beginPath(); + context.rect(100, 50, 100, 50); + context.closePath(); + context.fillStyle = 'green'; + context.fill(); + compareLayerAndCanvas(layer, canvas, 10); + compareSceneAndHit(layer); + }); + + test('cache simple rectangle with transform', function() { + var stage = addStage(); + + var layer = new Konva.Layer(); + + var rect = new Konva.Rect({ + x: 100, + y: 50, + width: 100, + height: 50, + rotation : 45, + scaleY : 2, + fill: 'green' + }); + rect.cache(); + + layer.add(rect); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + context.translate(100, 50); + context.rotate(Math.PI / 4); + context.beginPath(); + context.rect(0, 0, 100, 100); + context.closePath(); + context.fillStyle = 'green'; + context.fill(); + + if (!window.mochaPhantomJS) { + compareLayerAndCanvas(layer, canvas, 40); + compareSceneAndHit(layer); + } + + }); + + test('cache rectangle with fill and stroke', function() { + var stage = addStage(); + + var layer = new Konva.Layer(); + + var rect = new Konva.Rect({ + x: 100, + y: 50, + width: 100, + height: 50, + fill: 'green', + stroke : 'black', + strokeWidth : 20 + }); + rect.cache(); + + layer.add(rect); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + context.beginPath(); + context.rect(100, 50, 100, 50); + context.closePath(); + context.fillStyle = 'green'; + context.fill(); + context.lineWidth = 20; + context.stroke(); + compareLayerAndCanvas(layer, canvas, 10); + compareSceneAndHit(layer); + }); + + test('cache rectangle with fill and simple shadow', function() { + var stage = addStage(); + + var layer = new Konva.Layer(); + + var rect = new Konva.Rect({ + x: 100, + y: 50, + width: 100, + height: 50, + fill: 'green', + shadowColor : 'black', + shadowBlur : 10 + }); + rect.cache(); + + layer.add(rect); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + context.beginPath(); + context.rect(100, 50, 100, 50); + context.closePath(); + context.fillStyle = 'green'; + context.shadowColor = 'black'; + context.shadowBlur = 10; + context.fill(); + compareLayerAndCanvas(layer, canvas, 10); + }); + + test('cache rectangle with fill and shadow with offset', function() { + var stage = addStage(); + + var layer = new Konva.Layer(); + + var rect = new Konva.Rect({ + x: 100, + y: 50, + width: 50, + height: 25, + fill: 'green', + shadowOffsetX : 10, + shadowOffsetY : 10, + shadowColor : 'black', + shadowBlur : 10 + }); + rect.cache(); + + layer.add(rect); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + + context.translate(100, 50); + context.beginPath(); + context.rect(0, 0, 50, 25); + context.closePath(); + context.fillStyle = 'green'; + context.shadowColor = 'black'; + context.shadowBlur = 10; + context.shadowOffsetX = 10; + context.shadowOffsetY = 10; + context.fill(); + compareLayerAndCanvas(layer, canvas, 50); + }); + + test('cache rectangle with fill and shadow with negative offset', function() { + var stage = addStage(); + + var layer = new Konva.Layer(); + + var rect = new Konva.Rect({ + x: 100, + y: 50, + width: 50, + height: 25, + fill: 'green', + shadowOffsetX : -10, + shadowOffsetY : -10, + shadowColor : 'black', + shadowBlur : 10 + }); + rect.cache(); + + layer.add(rect); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + + context.translate(100, 50); + context.beginPath(); + context.rect(0, 0, 50, 25); + context.closePath(); + context.fillStyle = 'green'; + context.shadowColor = 'black'; + context.shadowBlur = 10; + context.shadowOffsetX = -10; + context.shadowOffsetY = -10; + context.fill(); + compareLayerAndCanvas(layer, canvas, 50); + }); + + test('cache rectangle with fill and shadow and some transform', function() { + var stage = addStage(); + + var layer = new Konva.Layer(); + + var rect = new Konva.Rect({ + x: 100, + y: 50, + width: 50, + height: 25, + fill: 'green', + shadowOffsetX : -10, + shadowOffsetY : -10, + shadowColor : 'black', + shadowBlur : 10, + offsetX : 50, + offsetY : 25 + }); + rect.cache(); + + layer.add(rect); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + + context.translate(50, 25); + context.beginPath(); + context.rect(0, 0, 50, 25); + context.closePath(); + context.fillStyle = 'green'; + context.shadowColor = 'black'; + context.shadowBlur = 10; + context.shadowOffsetX = -10; + context.shadowOffsetY = -10; + context.fill(); + compareLayerAndCanvas(layer, canvas, 50); + }); + + + // CACHING CONTAINERS + test('cache group with simple rectangle', function() { + var stage = addStage(); + + var layer = new Konva.Layer(); + + var group = new Konva.Group({ + x: 100, + y: 50 + }); + + var rect = new Konva.Rect({ + width: 100, + height: 50, + fill: 'green' + }); + group.add(rect); + group.cache(); + + layer.add(group); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + context.beginPath(); + context.rect(100, 50, 100, 50); + context.closePath(); + context.fillStyle = 'green'; + context.fill(); + compareLayerAndCanvas(layer, canvas, 10); + compareSceneAndHit(layer); + }); + + test('cache group with simple rectangle with transform', function() { + var stage = addStage(); + + var layer = new Konva.Layer(); + + var group = new Konva.Group({ + x: 50, + y: 25 + }); + + var rect = new Konva.Rect({ + x : 50, + y : 25, + width: 100, + height: 50, + fill: 'green', + rotation : 45 + }); + group.add(rect); + group.cache(); + + layer.add(group); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + context.translate(100, 50); + context.rotate(Math.PI / 4); + context.beginPath(); + context.rect(0, 0, 100, 50); + context.closePath(); + context.fillStyle = 'green'; + context.fill(); + if (!window.mochaPhantomJS) { + compareLayerAndCanvas(layer, canvas, 150); + compareSceneAndHit(layer); + } + }); + + test('cache group with several shape with transform', function() { + var stage = addStage(); + + var layer = new Konva.Layer(); + + var group = new Konva.Group({ + x: 50, + y: 25 + }); + + var rect = new Konva.Rect({ + x : 50, + y : 25, + width: 100, + height: 50, + fill: 'green', + shadowOffsetX : 10, + shadowOffsetY : 10, + shadowBlur : 10 + }); + group.add(rect); + + var circle = new Konva.Circle({ + x : 250, + y : 50, + radius : 25, + fill: 'red', + // rotation on circle should not have any effects + rotation : 45, + stroke : 2, + scaleX : 2, + scaleY : 2 + }); + group.add(circle); + + group.cache(); + + layer.add(group); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + + // draw rect + context.save(); + context.beginPath(); + context.rect(100, 50, 100, 50); + context.closePath(); + context.fillStyle = 'green'; + context.shadowColor = 'black'; + context.shadowBlur = 10; + context.shadowOffsetX = 10; + context.shadowOffsetY = 10; + context.fill(); + context.restore(); + + // circle + context.save(); + context.beginPath(); + context.arc(300, 75, 50, 0, Math.PI * 2); + context.closePath(); + context.fillStyle = 'red'; + context.lineWidth = 4; + context.fill(); + context.stroke(); + context.restore(); + + + compareLayerAndCanvas(layer, canvas, 150); + + // recache + group.cache(); + layer.draw(); + compareLayerAndCanvas(layer, canvas, 150); + }); + + test('cache layer with several shape with transform', function() { + var stage = addStage(); + + var layer = new Konva.Layer({ + draggable : true + }); + + var group = new Konva.Group({ + x: 50, + y: 25 + }); + + var rect = new Konva.Rect({ + x : 50, + y : 25, + width: 100, + height: 50, + fill: 'green', + shadowOffsetX : 10, + shadowOffsetY : 10, + shadowBlur : 10 + }); + group.add(rect); + + var circle = new Konva.Circle({ + x : 250, + y : 50, + radius : 25, + fill: 'red', + // rotation on circle should not have any effects + rotation : 45, + stroke : 2, + scaleX : 2, + scaleY : 2 + }); + group.add(circle); + + group.cache(); + + layer.add(group); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + + // draw rect + context.save(); + context.beginPath(); + context.rect(100, 50, 100, 50); + context.closePath(); + context.fillStyle = 'green'; + context.shadowColor = 'black'; + context.shadowBlur = 10; + context.shadowOffsetX = 10; + context.shadowOffsetY = 10; + context.fill(); + context.restore(); + + // circle + context.save(); + context.beginPath(); + context.arc(300, 75, 50, 0, Math.PI * 2); + context.closePath(); + context.fillStyle = 'red'; + context.lineWidth = 4; + context.fill(); + context.stroke(); + context.restore(); + + + compareLayerAndCanvas(layer, canvas, 150); + + // recache + group.cache(); + layer.draw(); + compareLayerAndCanvas(layer, canvas, 150); + }); + + test('cache shape that is larger than stage', function(){ + var stage = addStage(); + var layer = new Konva.Layer(); + var group = new Konva.Group(); + var circle = new Konva.Circle({ + x: 74, + y: 74, + radius: 300, + fill: 'red', + stroke: 'black', + strokeWidth: 4, + scaleX : 1 /2, + scaleY : 1 / 2 + }); + + group.add(circle); + layer.add(group); + stage.add(layer); + + assert.equal(circle._cache.canvas, undefined); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + // circle + context.save(); + context.beginPath(); + context.arc(74, 74, 150, 0, Math.PI * 2); + context.closePath(); + context.fillStyle = 'red'; + context.lineWidth = 2; + context.fill(); + context.stroke(); + context.restore(); + + + compareLayerAndCanvas(layer, canvas, 50); + }); +}); \ No newline at end of file diff --git a/test/unit/Node-test.js b/test/unit/Node-test.js index e5930b96..fd9a27a4 100644 --- a/test/unit/Node-test.js +++ b/test/unit/Node-test.js @@ -2961,358 +2961,6 @@ suite('Node', function() { y : 35 }); assert.equal(shape, rect, 'rect found'); - - assert.equal(layer.canvas.getContext().getTrace(), 'clearRect(0,0,578,200);clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);drawImage([object HTMLCanvasElement],0,0);restore();'); - }); - - - test('cache shape inside transformed group', function(){ - var stage = addStage(); - var layer = new Konva.Layer(); - var group = new Konva.Group({ - x: 50, - y: 50 - }); - var circle = new Konva.Circle({ - x: 74, - y: 74, - radius: 70, - fill: 'green', - stroke: 'black', - strokeWidth: 4, - name: 'myCircle', - draggable: true - }); - - group.add(circle); - layer.add(group); - stage.add(layer); - - assert.equal(circle._cache.canvas, undefined); - - circle.cache({ - x: -74, - y: -74, - width: 148, - height: 148 - }).offset({ - x: 74, - y: 74 - }); - - assert.notEqual(circle._cache.canvas.scene, undefined); - assert.notEqual(circle._cache.canvas.hit, undefined); - - layer.draw(); - - - //document.body.appendChild(circle._cache.canvas.scene._canvas); - // document.body.appendChild(circle._cache.canvas.hit._canvas); - - showHit(layer) - - assert.equal(layer.getContext().getTrace(), 'clearRect(0,0,578,200);save();transform(1,0,0,1,124,124);beginPath();arc(0,0,70,0,6.283,false);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();clearRect(0,0,578,200);save();transform(1,0,0,1,50,50);drawImage([object HTMLCanvasElement],0,0);restore();'); - assert.equal(circle._cache.canvas.scene.getContext().getTrace(), 'save();translate(74,74);translate(-74,-74);save();transform(1,0,0,1,74,74);beginPath();arc(0,0,70,0,6.283,false);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();restore();'); - }); - - test('cache shape thats larger than stage', function(){ - var stage = addStage(); - var layer = new Konva.Layer(); - var group = new Konva.Group(); - var circle = new Konva.Circle({ - x: 74, - y: 74, - radius: 300, - fill: 'green', - stroke: 'black', - strokeWidth: 4, - name: 'myCircle', - draggable: true - }); - - group.add(circle); - layer.add(group); - stage.add(layer); - - assert.equal(circle._cache.canvas, undefined); - - circle.cache({ - x: -304, - y: -304, - width: 608, - height: 608 - }).offset({ - x: 304, - y: 304 - }); - layer.draw(); - - - }); - - test('show cache border', function(){ - var stage = addStage(); - var layer = new Konva.Layer(); - var group = new Konva.Group(); - var circle = new Konva.Circle({ - x: 200, - y: 74, - radius: 70, - fill: 'green', - stroke: 'black', - strokeWidth: 4, - name: 'myCircle', - draggable: true - }); - - group.add(circle); - layer.add(group); - stage.add(layer); - - assert.equal(circle._cache.canvas, undefined); - - circle.cache({ - x: -74, - y: -74, - width: 148, - height: 148, - drawBorder: true - }).offset({ - x: 74, - y: 74 - }); - - assert.notEqual(circle._cache.canvas.scene, undefined); - assert.notEqual(circle._cache.canvas.hit, undefined); - - layer.draw(); - - - showHit(layer); - - - //console.log(circle._cache.canvas.scene.getContext().getTrace()); - - // make sure the border rectangle was drawn onto the cached scene canvas - assert.equal(circle._cache.canvas.scene.getContext().getTrace(),'save();save();beginPath();rect(0,0,148,148);closePath();strokeStyle=red;lineWidth=5;stroke();restore();translate(74,74);translate(-200,-74);save();transform(1,0,0,1,200,74);beginPath();arc(0,0,70,0,6.283,false);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();restore();'); - }); - - test('cache group', function(){ - var stage = addStage(); - var layer = new Konva.Layer(); - var group = new Konva.Group({ - x: 100, - y: 100, - draggable: true - }); - var top = new Konva.Circle({ - x: 0, - y: -70, - radius: 30, - fill: 'green', - stroke: 'black', - strokeWidth: 4 - }); - var right = new Konva.Circle({ - x: 70, - y: 0, - radius: 30, - fill: 'red', - stroke: 'black', - strokeWidth: 4 - }); - var bottom = new Konva.Circle({ - x: 0, - y: 70, - radius: 30, - fill: 'blue', - stroke: 'black', - strokeWidth: 4 - }); - var left = new Konva.Circle({ - x: -70, - y: 0, - radius: 30, - fill: 'yellow', - stroke: 'black', - strokeWidth: 4 - }); - - group.add(top).add(right).add(bottom).add(left); - layer.add(group); - stage.add(layer); - - //console.log('---before cache') - - assert.equal(group._cache.canvas, undefined); - - group.cache({ - width: 80, - height: 80 - }); - - assert.notEqual(group._cache.canvas.scene, undefined); - assert.notEqual(group._cache.canvas.hit, undefined); - - //console.log('---before first draw') - layer.draw(); - - //console.log(layer.getContext().getTrace()) - - //document.body.appendChild(group._cache.canvas.scene._canvas); - - //console.log('---before second draw') - layer.draw(); - - assert.equal(layer.getContext().getTrace(), 'clearRect(0,0,578,200);save();transform(1,0,0,1,100,30);beginPath();arc(0,0,30,0,6.283,false);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();save();transform(1,0,0,1,170,100);beginPath();arc(0,0,30,0,6.283,false);closePath();fillStyle=red;fill();lineWidth=4;strokeStyle=black;stroke();restore();save();transform(1,0,0,1,100,170);beginPath();arc(0,0,30,0,6.283,false);closePath();fillStyle=blue;fill();lineWidth=4;strokeStyle=black;stroke();restore();save();transform(1,0,0,1,30,100);beginPath();arc(0,0,30,0,6.283,false);closePath();fillStyle=yellow;fill();lineWidth=4;strokeStyle=black;stroke();restore();clearRect(0,0,578,200);save();transform(1,0,0,1,100,100);drawImage([object HTMLCanvasElement],0,0);restore();clearRect(0,0,578,200);save();transform(1,0,0,1,100,100);drawImage([object HTMLCanvasElement],0,0);restore();'); - - showHit(layer); - }); - - test('cache transformed group', function(){ - var stage = addStage(); - var layer = new Konva.Layer(); - var group = new Konva.Group({ - x: 100, - y: 100, - draggable: true, - rotation: 20, - scaleX: 2, - scaleY: 2 - }); - var top = new Konva.Circle({ - x: 0, - y: -70, - radius: 50, - fill: 'green', - stroke: 'black', - strokeWidth: 4 - }); - var right = new Konva.Circle({ - x: 70, - y: 0, - radius: 30, - fill: 'red', - stroke: 'black', - strokeWidth: 4 - }); - var bottom = new Konva.Circle({ - x: 0, - y: 70, - radius: 30, - fill: 'blue', - stroke: 'black', - strokeWidth: 4 - }); - var left = new Konva.Circle({ - x: -70, - y: 0, - radius: 30, - fill: 'yellow', - stroke: 'black', - strokeWidth: 4 - }); - - group.add(top).add(right).add(bottom).add(left); - layer.add(group); - stage.add(layer); - - //console.log('---before cache') - - //console.log(group.getAbsoluteTransform().getTranslation()) - - group.cache({ - x: -104, - y: -104, - width: 208, - height: 208 - }); - - group.offsetX(104).offsetY(104); - - //console.log('--after cache'); - //console.log(group.getAbsoluteTransform().getTranslation()) - //console.log(group.getAbsolutePosition()); - //console.log('---before first draw') - layer.draw(); - - //document.body.appendChild(group._cache.canvas.scene._canvas); - //console.log('---before second draw') - layer.draw(); - - //console.log(layer.getContext().getTrace()) - assert.equal(layer.getContext().getTrace(), 'clearRect(0,0,578,200);save();transform(1.879,0.684,-0.684,1.879,147.883,-31.557);beginPath();arc(0,0,50,0,6.283,false);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();save();transform(1.879,0.684,-0.684,1.879,231.557,147.883);beginPath();arc(0,0,30,0,6.283,false);closePath();fillStyle=red;fill();lineWidth=4;strokeStyle=black;stroke();restore();save();transform(1.879,0.684,-0.684,1.879,52.117,231.557);beginPath();arc(0,0,30,0,6.283,false);closePath();fillStyle=blue;fill();lineWidth=4;strokeStyle=black;stroke();restore();save();transform(1.879,0.684,-0.684,1.879,-31.557,52.117);beginPath();arc(0,0,30,0,6.283,false);closePath();fillStyle=yellow;fill();lineWidth=4;strokeStyle=black;stroke();restore();clearRect(0,0,578,200);save();transform(1.879,0.684,-0.684,1.879,-24.316,-166.596);drawImage([object HTMLCanvasElement],0,0);restore();clearRect(0,0,578,200);save();transform(1.879,0.684,-0.684,1.879,-24.316,-166.596);drawImage([object HTMLCanvasElement],0,0);restore();'); - showHit(layer); - }); - - test('cache layer', function(){ - var stage = addStage(); - var layer = new Konva.Layer({ - x: 100, - y: 100, - draggable: true - }); - var group = new Konva.Group(); - var top = new Konva.Circle({ - x: 0, - y: -70, - radius: 30, - fill: 'green', - stroke: 'black', - strokeWidth: 4 - }); - var right = new Konva.Circle({ - x: 70, - y: 0, - radius: 30, - fill: 'red', - stroke: 'black', - strokeWidth: 4 - }); - var bottom = new Konva.Circle({ - x: 0, - y: 70, - radius: 30, - fill: 'blue', - stroke: 'black', - strokeWidth: 4 - }); - var left = new Konva.Circle({ - x: -70, - y: 0, - radius: 30, - fill: 'yellow', - stroke: 'black', - strokeWidth: 4 - }); - - group.add(top).add(right).add(bottom).add(left); - layer.add(group); - stage.add(layer); - - assert.equal(layer._cache.canvas, undefined); - - layer.cache({ - width: 80, - height: 80 - }); - - assert.notEqual(layer._cache.canvas.scene, undefined); - assert.notEqual(layer._cache.canvas.hit, undefined); - - - layer.draw(); - layer.draw(); - - //console.log(layer.getContext().getTrace()); - assert.equal(layer.getContext().getTrace(), 'clearRect(0,0,578,200);save();transform(1,0,0,1,100,30);beginPath();arc(0,0,30,0,6.283,false);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();save();transform(1,0,0,1,170,100);beginPath();arc(0,0,30,0,6.283,false);closePath();fillStyle=red;fill();lineWidth=4;strokeStyle=black;stroke();restore();save();transform(1,0,0,1,100,170);beginPath();arc(0,0,30,0,6.283,false);closePath();fillStyle=blue;fill();lineWidth=4;strokeStyle=black;stroke();restore();save();transform(1,0,0,1,30,100);beginPath();arc(0,0,30,0,6.283,false);closePath();fillStyle=yellow;fill();lineWidth=4;strokeStyle=black;stroke();restore();clearRect(0,0,578,200);save();transform(1,0,0,1,100,100);drawImage([object HTMLCanvasElement],0,0);restore();clearRect(0,0,578,200);save();transform(1,0,0,1,100,100);drawImage([object HTMLCanvasElement],0,0);restore();'); - - - // make sure that the hit graph is also rendered after caching the layer - assert.equal(layer.hitCanvas.getContext().getTrace(true), 'clearRect();save();transform();beginPath();arc();closePath();save();fillStyle;fill();restore();lineWidth;strokeStyle;stroke();restore();save();transform();beginPath();arc();closePath();save();fillStyle;fill();restore();lineWidth;strokeStyle;stroke();restore();save();transform();beginPath();arc();closePath();save();fillStyle;fill();restore();lineWidth;strokeStyle;stroke();restore();save();transform();beginPath();arc();closePath();save();fillStyle;fill();restore();lineWidth;strokeStyle;stroke();restore();clearRect();clearRect();save();transform();drawImage();restore();clearRect();save();transform();drawImage();restore();'); - - showHit(layer); - }); test('stage.toObject() when stage contains an image', function(done){ diff --git a/test/unit/plugins/Label-test.js b/test/unit/plugins/Label-test.js index 3b8e7327..14cfedfc 100644 --- a/test/unit/plugins/Label-test.js +++ b/test/unit/plugins/Label-test.js @@ -99,4 +99,122 @@ suite('Label', function() { assert.equal(stage.find('Label')[0], label); }); + test('cache label', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + + // tooltip + var tooltip = new Konva.Label({ + x: 170, + y: 75, + opacity: 0.75 + }); + tooltip.add(new Konva.Tag({ + fill: 'black', + pointerDirection: 'down', + pointerWidth: 10, + pointerHeight: 10, + lineJoin: 'round', + shadowColor: 'black', + shadowBlur: 10, + shadowOffset: 10, + shadowOpacity: 0.5 + })); + tooltip.add(new Konva.Text({ + text: 'Tooltip pointing down', + fontFamily: 'Calibri', + fontSize: 18, + padding: 5, + fill: 'white' + })); + + var tooltipUp = new Konva.Label({ + x: 170, + y: 75, + opacity: 0.75 + }); + tooltipUp.add(new Konva.Tag({ + fill: 'black', + pointerDirection: 'up', + pointerWidth: 10, + pointerHeight: 10, + lineJoin: 'round', + shadowColor: 'black', + shadowBlur: 10, + shadowOffset: 10, + shadowOpacity: 0.5 + })); + tooltipUp.add(new Konva.Text({ + text: 'Tooltip pointing up', + fontFamily: 'Calibri', + fontSize: 18, + padding: 5, + fill: 'white' + })); + // label with left pointer + var labelLeft = new Konva.Label({ + x: 20, + y: 130, + opacity: 0.75 + }); + labelLeft.add(new Konva.Tag({ + fill: 'green', + pointerDirection: 'left', + pointerWidth: 30, + pointerHeight: 28, + lineJoin: 'round' + })); + labelLeft.add(new Konva.Text({ + text: 'Label pointing left', + fontFamily: 'Calibri', + fontSize: 18, + padding: 5, + fill: 'white' + })); + // label with left pointer + var labelRight = new Konva.Label({ + x: 160, + y: 170, + offsetX : 20, + opacity: 0.75 + }); + labelRight.add(new Konva.Tag({ + fill: 'green', + pointerDirection: 'right', + pointerWidth: 20, + pointerHeight: 28, + lineJoin: 'round' + })); + labelRight.add(new Konva.Text({ + text: 'Label right', + fontFamily: 'Calibri', + fontSize: 18, + padding: 5, + fill: 'white' + })); + // simple label + var simpleLabel = new Konva.Label({ + x: 180, + y: 150, + opacity: 0.75 + }); + simpleLabel.add(new Konva.Tag({ + fill: 'yellow' + })); + simpleLabel.add(new Konva.Text({ + text: 'Simple label', + fontFamily: 'Calibri', + fontSize: 18, + padding: 5, + fill: 'black' + })); + // add the labels to layer + layer.add(tooltip, tooltipUp, labelLeft, labelRight, simpleLabel); + layer.children.cache(); + + stage.add(layer); + + cloneAndCompareLayer(layer, 150); + }); + }); \ No newline at end of file diff --git a/test/unit/plugins/Path-test.js b/test/unit/plugins/Path-test.js index fb1b2b74..f849d654 100644 --- a/test/unit/plugins/Path-test.js +++ b/test/unit/plugins/Path-test.js @@ -102,6 +102,32 @@ suite('Path', function() { stage.add(layer); }); + + //======================================================= + test('complex path made of many different closed and open paths (Sopwith Camel) cached', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + + var path = new Konva.Path({ + data: 'm 15.749277,58.447629 8.495831,-0.05348 m 0.319898,-15.826548 -0.202438,17.295748 0.942206,0.941911 1.345933,-1.816987 0.20211,-11.642611 z m 77.458374,28.680768 c 0,5.308829 -4.303525,9.612686 -9.612485,9.612686 -5.30873,0 -9.612194,-4.303857 -9.612194,-9.612686 0,-5.308829 4.303464,-9.61226 9.612194,-9.61226 5.30896,0 9.612485,4.303431 9.612485,9.61226 z m -3.520874,0 c 0,3.364079 -2.72763,6.091348 -6.091611,6.091348 -3.364243,0 -6.091119,-2.727269 -6.091119,-6.091348 0,-3.363719 2.726876,-6.090791 6.091119,-6.090791 3.363981,0 6.091611,2.727072 6.091611,6.090791 z m -3.997576,0 c 0,1.156718 -0.937743,2.093937 -2.094035,2.093937 -1.156062,0 -2.093871,-0.937219 -2.093871,-2.093937 0,-1.156357 0.937809,-2.093773 2.093871,-2.093773 1.156292,0 2.094035,0.937416 2.094035,2.093773 z m 45.77821,4.283023 c -0.24607,1.90039 5.06492,3.680204 7.61403,5.520093 0.50662,0.514199 0.27889,0.975967 -0.0984,1.427532 l 3.9019,-1.141987 c -0.59258,-0.121397 -1.85951,0.01969 -1.71294,-0.380038 -0.85894,-1.950525 -3.68693,-2.761261 -5.61518,-4.092495 -1.06971,-1.03496 0.0997,-1.60766 0.76126,-2.284203 z M 43.206396,42.60133 55.578964,74.008743 58.71987,73.910313 47.203939,44.40726 c -1.109013,-0.737406 -1.174108,-2.1004 -3.997543,-1.808752 z m -18.654022,-0.570632 12.467721,31.692335 3.140643,0.09843 -12.467656,-31.692927 z m 2.285318,42.353106 -2.636648,-0.06431 0.163066,0.734584 3.709372,9.956142 2.357927,-1.168202 z m 19.411934,0.566268 -6.370726,9.901284 2.090163,1.615665 7.13671,-11.417403 0.303821,-0.4347 -2.942667,-0.02953 z m -12.091915,8.286013 c -5.729323,0 -10.367941,4.560169 -10.367941,10.184405 0,5.62429 4.638618,10.18489 10.367941,10.18489 5.729424,0 10.37654,-4.5606 10.37654,-10.18489 0,-5.624236 -4.647083,-10.184405 -10.37654,-10.184405 z m 0,2.473319 c 4.310029,0 7.811352,3.453552 7.811352,7.711086 0,4.25776 -3.50129,7.71167 -7.811352,7.71167 -4.310157,0 -7.803016,-3.45391 -7.803016,-7.71167 0,-4.257534 3.492859,-7.711086 7.803016,-7.711086 z m 3.528526,-21.795876 c -1.29032,-0.0066 -2.97525,0.03839 -3.402437,1.45155 l -0.01969,7.494437 c 0.586775,0.761915 1.42432,0.688978 2.236565,0.71411 l 26.529545,-0.14502 8.636784,0.761324 0,-7.518487 C 71.56989,75.908478 71.09444,75.467051 70.239377,75.338961 61.126027,73.734287 49.244756,73.929146 37.690371,73.911166 z M 20.959576,41.269176 c -0.0098,0.603377 0.575258,0.881409 0.575258,0.881409 L 58.95771,42.33629 c -4.893946,-0.985482 -16.592629,-2.859625 -32.835015,-2.783473 -1.570354,0.107617 -5.151439,1.109571 -5.163119,1.712718 z m 3.353022,14.276273 c -2.79955,0.01312 -5.595489,0.02953 -8.382964,0.05545 l 0,9.9e-5 0.0033,1.447677 -1.173484,0.01312 0.0066,1.244485 1.184048,0.05807 c -1.34298,0.220812 -2.956414,1.305807 -3.054779,3.476618 0.0098,3.269061 0.01312,6.538943 0.01312,9.808103 l -1.21197,0.0033 -0.01969,-2.361569 -4.6851755,0.0033 0,5.901969 4.6323185,0.0066 -0.02953,-1.7556 1.308596,-0.02297 0.0098,9.180447 c -0.0066,1.315781 2.739048,3.634336 4.542583,3.634336 l 4.811756,-2.995032 c 1.616583,-0.107617 1.758126,0.482078 1.884346,1.076924 l 35.667571,0.318914 6.909664,-0.81031 m 4.994738,-0.585889 85.216614,-9.991675 c 4.93952,-0.487623 14.9162,-22.255511 -3.75098,-25.556727 -5.12814,-0.887479 -15.53194,4.839613 -21.44018,9.104984 -2.31314,1.954593 -1.74166,4.084194 0.0263,5.982879 l -72.209399,-8.111923 -2.12281,-0.0012 c -0.966453,1.390128 -3.158262,3.260465 -4.554559,4.053123 M 49.36027,58.361483 c -1.699757,-1.038536 -2.965602,-2.804438 -4.533856,-2.875275 -3.903936,0.0011 -7.904399,0.0066 -11.882849,0.01312 m -3.081192,0.0066 c -1.043195,0.0033 -2.082715,0.0066 -3.116396,0.0098', + stroke: '#000', + strokeWidth: 1, + lineCap: 'round', + lineJoin: 'round', + draggable : true + }); + + layer.add(path); + + stage.add(layer); + + path.cache(); + layer.draw(); +// layer.draw(); + cloneAndCompareLayer(layer, 230); + showHit(layer) + + }); @@ -404,6 +430,29 @@ suite('Path', function() { showHit(layer); }); + + // ====================================================== + test.skip('Tiger (RAWR!) cached', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var group = new Konva.Group(); + + for(var i = 0; i < tiger.length; i++) { + var path = new Konva.Path(tiger[i]); + group.add(path); + } + + group.setDraggable(true); + layer.add(group); + stage.add(layer); + group.cache(); + layer.draw(); + + showHit(layer); + + cloneAndCompareLayer(layer, 200); + + }); // ====================================================== test('Able to determine point on line some distance from another point on line', function() { diff --git a/test/unit/plugins/RegularPolygon-test.js b/test/unit/plugins/RegularPolygon-test.js index 14d58a0b..a2ec061c 100644 --- a/test/unit/plugins/RegularPolygon-test.js +++ b/test/unit/plugins/RegularPolygon-test.js @@ -86,5 +86,65 @@ suite('RegularPolygon', function() { layer.add(poly); stage.add(layer); }); + + // ====================================================== + test('attr sync', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + + var poly = new Konva.RegularPolygon({ + x: 200, + y: 100, + sides: 5, + radius: 50, + fill: 'green', + stroke: 'blue', + strokeWidth: 5, + name: 'foobar' + }); + + layer.add(poly); + stage.add(layer); + + assert.equal(poly.getWidth(), 100); + assert.equal(poly.getHeight(), 100); + + poly.setWidth(120); + assert.equal(poly.radius(), 60); + assert.equal(poly.getHeight(), 120); + + poly.setHeight(140); + assert.equal(poly.radius(), 70); + assert.equal(poly.getHeight(), 140); + }); + + test('polygon cache', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + + var poly = new Konva.RegularPolygon({ + x: 200, + y: 100, + sides: 5, + radius: 50, + fill: 'green', + stroke: 'blue', + strokeWidth: 5, + name: 'foobar' + }); + poly.cache(); + layer.add(poly); + stage.add(layer); + + assert.deepEqual(poly.getSelfRect(), { + x : -50, + y : -50, + height : 100, + width : 100 + }); + if (!window.mochaPhantomJS) { + cloneAndCompareLayer(layer, 50); + } + }); }); \ No newline at end of file diff --git a/test/unit/plugins/Star-test.js b/test/unit/plugins/Star-test.js index 3009f3db..24f6ca32 100644 --- a/test/unit/plugins/Star-test.js +++ b/test/unit/plugins/Star-test.js @@ -53,7 +53,7 @@ suite('Star', function() { fill: 'green', stroke: 'blue', strokeWidth: 5, - lineJoin: "round", + lineJoin: 'round', shadowColor: 'black', shadowBlur: 10, shadowOffset: [20, 20], @@ -72,4 +72,77 @@ suite('Star', function() { star.setLineJoin('round'); }); + + // ====================================================== + test('attr sync', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + + var star = new Konva.Star({ + x: 200, + y: 100, + numPoints: 5, + innerRadius: 30, + outerRadius: 50, + fill: 'green', + stroke: 'blue', + strokeWidth: 5, + lineJoin: 'round', + shadowColor: 'black', + shadowBlur: 10, + shadowOffset: [20, 20], + shadowOpacity: 0.5, + draggable: true + }); + + layer.add(star); + + stage.add(layer); + + assert.equal(star.getWidth(), 100); + assert.equal(star.getHeight(), 100); + + star.setWidth(120); + assert.equal(star.outerRadius(), 60); + assert.equal(star.getHeight(), 120); + + star.setHeight(140); + assert.equal(star.outerRadius(), 70); + assert.equal(star.getHeight(), 140); + }); + + // ====================================================== + test('star cache', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + + var star = new Konva.Star({ + x: 200, + y: 100, + numPoints: 5, + innerRadius: 30, + outerRadius: 50, + fill: 'green', + stroke: 'blue', + strokeWidth: 5, + lineJoin: 'round', + shadowColor: 'black', + shadowBlur: 10, + shadowOffset: [20, 20], + shadowOpacity: 0.5, + draggable: true + }); + + layer.add(star); + star.cache(); + stage.add(layer); + + assert.deepEqual(star.getSelfRect(), { + x : -50, + y : -50, + height : 100, + width : 100 + }); + cloneAndCompareLayer(layer, 50); + }); }); \ No newline at end of file diff --git a/test/unit/plugins/TextPath-test.js b/test/unit/plugins/TextPath-test.js index 5048643e..6092271d 100644 --- a/test/unit/plugins/TextPath-test.js +++ b/test/unit/plugins/TextPath-test.js @@ -188,4 +188,31 @@ suite('TextPath', function() { layer.add(textpath); stage.add(layer); }); + + // ====================================================== + test('Render Text Along complex path cached', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + + var c = "M10,10 C0,0 10,150 100,100 S300,150 400,50"; + + var textpath = new Konva.TextPath({ + stroke: 'black', + strokeWidth: 1, + fill: 'orange', + fontSize: 10, + fontFamily: 'Arial', + text: 'All the world\'s a stage, and all the men and women merely players. They have their exits and their entrances; And one man in his time plays many parts.', + data: c, + draggable : true + }); + + textpath.cache(); + + layer.add(textpath); + stage.add(layer); + + cloneAndCompareLayer(layer,50); + showHit(layer); + }); }); \ No newline at end of file diff --git a/test/unit/shapes/Arc-test.js b/test/unit/shapes/Arc-test.js index e8fac1a4..40ab09aa 100644 --- a/test/unit/shapes/Arc-test.js +++ b/test/unit/shapes/Arc-test.js @@ -26,4 +26,92 @@ suite('Arc', function() { assert.equal(trace, 'clearRect(0,0,578,200);save();transform(1,0,0,1,100,100);beginPath();arc(0,0,80,0,1.571,false);arc(0,0,50,1.571,0,true);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();'); }); + // ====================================================== + test('attrs sync', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var arc = new Konva.Arc({ + x: 100, + y: 100, + innerRadius: 50, + outerRadius: 80, + angle: 90, + fill: 'green', + stroke: 'black', + strokeWidth: 4, + name: 'myArc', + draggable: true + }); + + layer.add(arc); + stage.add(layer); + assert.equal(arc.getWidth(), 160); + assert.equal(arc.getHeight(), 160); + + arc.setWidth(100); + assert.equal(arc.outerRadius(), 50); + assert.equal(arc.getHeight(), 100); + + arc.setHeight(120); + assert.equal(arc.outerRadius(), 60); + assert.equal(arc.getHeight(), 120); + }); + + test('getSelfRect', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var arc = new Konva.Arc({ + x: 100, + y: 100, + innerRadius: 50, + outerRadius: 80, + angle: 90, + fill: 'green', + stroke: 'black', + strokeWidth: 4, + name: 'myArc', + draggable: true + }); + + layer.add(arc); + stage.add(layer); + + assert.deepEqual(arc.getSelfRect(), { + x : -80, + y : -80, + width : 160, + height : 160 + }); + }); + + test('cache', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var arc = new Konva.Arc({ + x: 100, + y: 100, + innerRadius: 50, + outerRadius: 80, + angle: 90, + fill: 'green', + stroke: 'black', + strokeWidth: 4, + }); + + layer.add(arc); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + context.beginPath(); + context.arc(100, 100, 80, 0, Math.PI / 2, false); + context.arc(100, 100, 50, Math.PI / 2, 0, true); + context.closePath(); + context.fillStyle = 'green'; + context.fill(); + context.lineWidth = 4; + context.stroke(); + compareLayerAndCanvas(layer, canvas, 10); + }); + }); \ No newline at end of file diff --git a/test/unit/shapes/Blob-test.js b/test/unit/shapes/Blob-test.js index 31ddb1e0..9575b28f 100644 --- a/test/unit/shapes/Blob-test.js +++ b/test/unit/shapes/Blob-test.js @@ -91,4 +91,27 @@ suite('Blob', function(){ assert.equal(blob.eventListeners.pointsChange, undefined); assert.equal(blob.eventListeners.tensionChange, undefined); }); + + test('cache', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var blob = new Konva.Line({ + x : 50, + y : 50, + points: [-25,50,250,-30,150,50,250,110], + stroke: 'blue', + strokeWidth: 10, + draggable: true, + fill: '#aaf', + tension: 0.3, + closed: true + }); + blob.cache(); + layer.add(blob); + stage.add(layer); + + if (!window.mochaPhantomJS) { + cloneAndCompareLayer(layer, 50); + } + }); }); \ No newline at end of file diff --git a/test/unit/shapes/Circle-test.js b/test/unit/shapes/Circle-test.js index bf4f8708..2d1f9a1d 100644 --- a/test/unit/shapes/Circle-test.js +++ b/test/unit/shapes/Circle-test.js @@ -188,7 +188,6 @@ suite('Circle', function(){ stage.add(layer); assert.equal(circle.getWidth(), 140); - assert.equal(circle.attrs.height, 140); assert.equal(circle.getHeight(), 140); circle.setWidth(100); @@ -218,4 +217,55 @@ suite('Circle', function(){ stage.add(layer); }); + + test('getSelfRect', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var circle = new Konva.Circle({ + x: 100, + y: 100, + radius: 50, + fill: 'green', + stroke: 'black', + strokeWidth: 4, + draggable: true + }); + + layer.add(circle); + stage.add(layer); + + assert.deepEqual(circle.getSelfRect(), { + x : -50, + y : -50, + width : 100, + height : 100 + }); + }); + + test('cache', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var circle = new Konva.Circle({ + x: 100, + y: 100, + radius: 50, + fill: 'green', + stroke: 'black', + strokeWidth: 4 + }); + + layer.add(circle); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + context.beginPath(); + context.arc(100, 100, 50, 0, Math.PI * 2, false); + context.closePath(); + context.fillStyle = 'green'; + context.fill(); + context.lineWidth = 4; + context.stroke(); + compareLayerAndCanvas(layer, canvas, 50); + }); }); \ No newline at end of file diff --git a/test/unit/shapes/Ellipse-test.js b/test/unit/shapes/Ellipse-test.js index 1381cfde..bf436e9f 100644 --- a/test/unit/shapes/Ellipse-test.js +++ b/test/unit/shapes/Ellipse-test.js @@ -1,7 +1,7 @@ suite('Ellipse', function(){ - // ====================================================== - test('add ellipse', function(){ + // ====================================================== + test('add ellipse', function(){ var stage = addStage(); var layer = new Konva.Layer(); var ellipse = new Konva.Ellipse({ @@ -18,5 +18,84 @@ suite('Ellipse', function(){ var trace = layer.getContext().getTrace(); assert.equal(trace, 'clearRect(0,0,578,200);save();transform(1,0,0,1,289,100);beginPath();save();scale(1,0.5);arc(0,0,70,0,6.283,false);restore();closePath();fillStyle=green;fill();lineWidth=8;strokeStyle=black;stroke();restore();'); - }); + }); + + // ====================================================== + test('attrs sync', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var ellipse = new Konva.Ellipse({ + x: stage.getWidth() / 2, + y: stage.getHeight() / 2, + radius: {x:70, y:35}, + fill: 'green', + stroke: 'black', + strokeWidth: 8 + }); + layer.add(ellipse); + stage.add(layer); + + assert.equal(ellipse.getWidth(), 140); + assert.equal(ellipse.getHeight(), 70); + + ellipse.setWidth(100); + assert.equal(ellipse.radiusX(), 50); + assert.equal(ellipse.radiusY(), 35); + + ellipse.setHeight(120); + assert.equal(ellipse.radiusX(), 50); + assert.equal(ellipse.radiusY(), 60); + }); + + test('getSelfRect', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var ellipse = new Konva.Ellipse({ + x: stage.getWidth() / 2, + y: stage.getHeight() / 2, + radius: {x:70, y:35}, + fill: 'green', + stroke: 'black', + strokeWidth: 8 + }); + layer.add(ellipse); + stage.add(layer); + + assert.deepEqual(ellipse.getSelfRect(), { + x : -70, + y : -35, + width : 140, + height : 70 + }); + }); + + test('cache', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var ellipse = new Konva.Ellipse({ + x: stage.getWidth() / 2, + y: stage.getHeight() / 2, + radius: {x:70, y:35}, + fill: 'green', + stroke: 'black', + strokeWidth: 8 + }); + ellipse.cache(); + layer.add(ellipse); + stage.add(layer); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + context.save(); + context.beginPath(); + context.scale(1, 0.5); + context.arc(stage.getWidth() / 2, stage.getHeight(), 70, 0, Math.PI * 2, false); + context.closePath(); + context.restore(); + context.fillStyle = 'green'; + context.fill(); + context.lineWidth = 8; + context.stroke(); + compareLayerAndCanvas(layer, canvas, 50); + }); }); \ No newline at end of file diff --git a/test/unit/shapes/Image-test.js b/test/unit/shapes/Image-test.js index 6127ac7a..bd62669e 100644 --- a/test/unit/shapes/Image-test.js +++ b/test/unit/shapes/Image-test.js @@ -312,4 +312,38 @@ suite('Image', function(){ }; imageObj.src = 'assets/darth-vader.jpg'; }); + + // ====================================================== + test('image caching', function(done) { + var imageObj = new Image(); + imageObj.onload = function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var darth = new Konva.Image({ + x: 200, + y: 60, + image: imageObj, + width: 100, + height: 100, + draggable: true + }); + + darth.cache(); + layer.add(darth); + stage.add(layer); + + assert.deepEqual(darth.getSelfRect(), { + x : 0, y : 0, width : 100, height : 100 + }); + + var canvas = createCanvas(); + var context = canvas.getContext('2d'); + context.drawImage(imageObj, 200, 60, 100, 100); + compareLayerAndCanvas(layer, canvas, 10); + done(); + }; + imageObj.src = 'assets/darth-vader.jpg'; + }); + + }); \ No newline at end of file diff --git a/test/unit/shapes/Line-test.js b/test/unit/shapes/Line-test.js index 46683c05..fc278375 100644 --- a/test/unit/shapes/Line-test.js +++ b/test/unit/shapes/Line-test.js @@ -205,4 +205,73 @@ suite('Line', function() { }); assert.equal(shape, line1, 'first line detected'); }); + + test('line get size', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + + var line = new Konva.Line({ + points: [73, 160, 340, 23, 500, 109, 500, 180], + stroke: 'blue', + + strokeWidth: 10 + }); + + layer.add(line); + stage.add(layer); + + assert.deepEqual(line.size(), { + width : 500 - 73, + height : 180 - 23 + }); + }); + + test('getSelfRect', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var blob = new Konva.Line({ + x : 50, + y : 50, + points: [-25,50,250,-30,150,50,250,110], + stroke: 'blue', + strokeWidth: 10, + draggable: true, + fill: '#aaf', + closed: true + }); + + layer.add(blob); + stage.add(layer); + + assert.deepEqual(blob.getSelfRect(), { + x : -25, + y : -30, + width : 275, + height : 140 + }); + }); + + test('line caching', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var blob = new Konva.Line({ + x : 50, + y : 50, + points: [-25,50,250,-30,150,50,250,110], + stroke: 'blue', + strokeWidth: 10, + draggable: true, + closed : true + }); + + layer.add(blob); + var layer2 = layer.clone(); + blob.cache({ + offset : 30 + }); + stage.add(layer); + stage.add(layer2); + layer2.hide(); + compareLayers(layer, layer2); + }); }); \ No newline at end of file diff --git a/test/unit/shapes/Ring-test.js b/test/unit/shapes/Ring-test.js index c94d6282..367700a6 100644 --- a/test/unit/shapes/Ring-test.js +++ b/test/unit/shapes/Ring-test.js @@ -23,7 +23,6 @@ suite('Ring', function() { }); // ====================================================== - // test for https://github.com/ericdrowell/KonvaJS/issues/987 test('ring attrs sync', function() { var stage = addStage(); var layer = new Konva.Layer(); @@ -31,8 +30,6 @@ suite('Ring', function() { name: 'ring', x: 30, y: 50, - width: 50, - height: 50, innerRadius: 15, outerRadius: 30, fill: 'green', @@ -43,11 +40,50 @@ suite('Ring', function() { layer.add(ring); stage.add(layer); + assert(ring.width(),60); + assert(ring.height(), 60); - var cring = ring.clone(); - assert.equal(cring.outerRadius(), ring.outerRadius()); + ring.height(100); + assert(ring.width(), 100); + assert(ring.outerRadius(), 50); - assert.equal(ring.attrs.width, ring.outerRadius() * 2); + ring.width(120); + assert(ring.height(), 120); + assert(ring.outerRadius(), 60); }); + test('ring cache', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var ring = new Konva.Ring({ + name: 'ring', + x: 30, + y: 50, + innerRadius: 15, + outerRadius: 30, + fill: 'green', + stroke: 'black', + strokeWidth: 4, + draggable: true + }); + + layer.add(ring); + stage.add(layer); + + assert.deepEqual(ring.getSelfRect(), { + x : -30, + y : -30, + width : 60, + height : 60 + }); + + var layer2 = layer.clone(); + stage.add(layer2); + layer2.hide(); + + compareLayers(layer, layer2); + + + }); + }); \ No newline at end of file diff --git a/test/unit/shapes/Text-test.js b/test/unit/shapes/Text-test.js index e13747d2..5b459b24 100644 --- a/test/unit/shapes/Text-test.js +++ b/test/unit/shapes/Text-test.js @@ -344,5 +344,27 @@ suite('Text', function(){ compareLayerAndCanvas(layer, canvas); }); + test('text getSelfRect', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + + var text = new Konva.Text({ + fontSize: 50, + y : 50, + x : 50, + fill: 'black', + text: 'text' + }); + + layer.add(text); + stage.add(layer); + + var rect = text.getSelfRect(); + + assert.deepEqual(rect, { + x : 0,y : 0, width : text.width(), height : 50 + }); + }); + }); \ No newline at end of file diff --git a/test/unit/shapes/Wedge-test.js b/test/unit/shapes/Wedge-test.js index 111477a7..4c318e35 100644 --- a/test/unit/shapes/Wedge-test.js +++ b/test/unit/shapes/Wedge-test.js @@ -25,4 +25,56 @@ suite('Wedge', function() { assert.equal(trace, 'clearRect(0,0,578,200);save();transform(1,0,0,1,100,100);beginPath();arc(0,0,70,0,1.257,false);lineTo(0,0);closePath();fillStyle=green;fill();lineWidth=4;strokeStyle=black;stroke();restore();'); }); + test('attrs sync', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var wedge = new Konva.Wedge({ + x: stage.getWidth() / 2, + y: stage.getHeight() / 2, + angle: 180 * 0.4, + radius: 70, + fill: 'green', + stroke: 'black', + strokeWidth: 4 + }); + + layer.add(wedge); + stage.add(layer); + + assert.equal(wedge.getWidth(), 140); + assert.equal(wedge.getHeight(), 140); + + wedge.setWidth(100); + assert.equal(wedge.radius(), 50); + assert.equal(wedge.getHeight(), 100); + + wedge.setHeight(120); + assert.equal(wedge.radius(), 60); + assert.equal(wedge.getHeight(), 120); + }); + + test('getSelfRect', function() { + var stage = addStage(); + var layer = new Konva.Layer(); + var wedge = new Konva.Wedge({ + x: stage.getWidth() / 2, + y: stage.getHeight() / 2, + angle: 180 * 0.4, + radius: 70, + fill: 'green', + stroke: 'black', + strokeWidth: 4 + }); + + layer.add(wedge); + stage.add(layer); + + assert.deepEqual(wedge.getSelfRect(), { + x : -70, + y : -70, + width : 140, + height : 140 + }); + }); + }); \ No newline at end of file