diff --git a/README.md b/README.md index 3b6e3a7a..9c320e71 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ To build a development version of the library, run `thor build:dev VERSION`, whe If you add a file in the src directory, be sure to add the filename to the filename array in the Thorfile. #Tests -To run tests, open `unitTests.html`, `functionalTests.html`, or `manualTests.html` in the `tests/html` directory. Unit tests and functional tests output the results to the console via `console.log()` so be sure to have it open. Use test() for hard tests which will throw an error if something fails, and use warn() for soft tests that will allow the tests to continue. The warn() method is great for tests that will have different results in different browsers, such as canvas data url comparisons, text metric dimensions, etc. All tests should pass in Google Chrome with no warnings, and all tests should pass with some warnings in other browsers. +To run tests, open `unitTests.html`, `functionalTests.html`, `manualTests.html`, or `performanceTests.html` in the `tests/html` directory. Unit, functional, and performance tests output the results to the console via `console.log()` so be sure to have it open. Use test() for hard tests which will throw an error if something fails, and use warn() for soft tests that will allow the tests to continue. The warn() method is great for tests that will have different results in different browsers, such as canvas data url comparisons, text metric dimensions, etc. All tests should pass in Google Chrome with no warnings, and all tests should pass with some warnings in other browsers. #Pull Requests I'd be happy to review any pull requests that may better the KineticJS project, in particular if you have a bug fix, enhancement, or a new shape (see `src/shapes` for examples). Before doing so, please first make sure that all of the unit tests and functional tests pass. diff --git a/dist/kinetic-core.js b/dist/kinetic-core.js index 0f80ccf7..f43e4f4a 100644 --- a/dist/kinetic-core.js +++ b/dist/kinetic-core.js @@ -3,7 +3,7 @@ * http://www.kineticjs.com/ * Copyright 2012, Eric Rowell * Licensed under the MIT or GPL Version 2 licenses. - * Date: Sep 23 2012 + * Date: Sep 24 2012 * * Copyright (C) 2011 - 2012 by Eric Rowell * @@ -206,8 +206,7 @@ Kinetic.Filters.Grayscale = function(imageData) { // Type /////////////////////////////////////////////////////////////////////// /* - * utilities that determine data type and transform - * one type into another + * utilities that handle data type detection, conversion, and manipulation */ Kinetic.Type = { /* @@ -450,7 +449,6 @@ Kinetic.Type = { } imageObj.src = dataUrl; } - else { callback(null); } @@ -471,6 +469,32 @@ Kinetic.Type = { var g = Math.round(Math.random() * 255); var b = Math.round(Math.random() * 255); return this._rgbToHex(r, g, b); + }, + // o1 takes precedence over o2 + _merge: function(o1, o2) { + var retObj = this._clone(o2); + for(var key in o1) { + if(this._isObject(o1[key])) { + retObj[key] = this._merge(o1[key], retObj[key]); + } + else { + retObj[key] = o1[key]; + } + } + return retObj; + }, + // deep clone + _clone: function(obj) { + var retObj = {}; + for(var key in obj) { + if(this._isObject(obj[key])) { + retObj[key] = this._clone(obj[key]); + } + else { + retObj[key] = obj[key]; + } + } + return retObj; } }; @@ -1402,113 +1426,19 @@ Kinetic.Node.prototype = { * @param {Object} config */ setAttrs: function(config) { - var type = Kinetic.Type; - var that = this; - // set properties from config - if(config !== undefined) { - function setAttrs(obj, c, level) { - for(var key in c) { - var val = c[key]; - var oldVal = obj[key]; - - /* - * only fire change event for root - * level attrs - */ - if(level === 0) { - that._fireBeforeChangeEvent(key, oldVal, val); - } - - // if obj doesn't have the val property, then create it - if(obj[key] === undefined && val !== undefined) { - obj[key] = {}; - } - - /* - * if property is a pure object (no methods), then add an empty object - * to the node and then traverse - */ - if(type._isObject(val) && !type._isArray(val) && !type._isElement(val) && !type._hasMethods(val)) { - /* - * since some properties can be strings or objects, e.g. - * fill, we need to first check that obj is an object - * before setting properties. If it's not an object, - * overwrite obj with an object literal - */ - if(!Kinetic.Type._isObject(obj[key])) { - obj[key] = {}; - } - - setAttrs(obj[key], val, level + 1); - } - /* - * add all other object types to attrs object - */ - else { - // handle special keys - switch (key) { - case 'radius': - if(Kinetic.Type._isNumber(val)) { - that._setAttr(obj, key, val); - } - else { - var xy = type._getXY(val); - that._setAttr(obj[key], 'x', xy.x); - that._setAttr(obj[key], 'y', xy.y); - } - break; - case 'rotationDeg': - that._setAttr(obj, 'rotation', c[key] * Math.PI / 180); - // override key for change event - key = 'rotation'; - break; - /* - * includes: - * - node offset - * - fill pattern offset - * - shadow offset - */ - case 'offset': - var pos = type._getXY(val); - that._setAttr(obj[key], 'x', pos.x); - that._setAttr(obj[key], 'y', pos.y); - break; - case 'scale': - var pos = type._getXY(val); - that._setAttr(obj[key], 'x', pos.x); - that._setAttr(obj[key], 'y', pos.y); - break; - case 'points': - that._setAttr(obj, key, type._getPoints(val)); - break; - case 'crop': - var pos = type._getXY(val); - var size = type._getSize(val); - that._setAttr(obj[key], 'x', pos.x); - that._setAttr(obj[key], 'y', pos.y); - that._setAttr(obj[key], 'width', size.width); - that._setAttr(obj[key], 'height', size.height); - break; - case 'text': - var str = Kinetic.Type._isString(val) ? val : val.toString(); - that._setAttr(obj, key, str); - break; - default: - that._setAttr(obj, key, val); - break; - } - } - /* - * only fire change event for root - * level attrs - */ - if(level === 0) { - that._fireChangeEvent(key, oldVal, val); - } - } - } - setAttrs(this.attrs, config, 0); - } + if (config) { + for (var key in config) { + var method = 'set' + key.charAt(0).toUpperCase() + key.slice(1); + // use setter if available + if (Kinetic.Type._isFunction(this[method])) { + this[method](config[key]); + } + // otherwise set directly + else { + this.setAttr(key, config[key]); + } + } + } }, /** * determine if shape is visible or not. Shape is visible only @@ -1529,9 +1459,7 @@ Kinetic.Node.prototype = { * @methodOf Kinetic.Node.prototype */ show: function() { - this.setAttrs({ - visible: true - }); + this.setVisible(true); }, /** * hide node. Hidden nodes are no longer detectable @@ -1539,9 +1467,7 @@ Kinetic.Node.prototype = { * @methodOf Kinetic.Node.prototype */ hide: function() { - this.setAttrs({ - visible: false - }); + this.setVisible(false); }, /** * get zIndex @@ -1609,8 +1535,9 @@ Kinetic.Node.prototype = { * @param {Number} y */ setPosition: function() { - var pos = Kinetic.Type._getXY(Array.prototype.slice.call(arguments)); - this.setAttrs(pos); + var pos = Kinetic.Type._getXY([].slice.call(arguments)); + this.setAttr('x', pos.x); + this.setAttr('y', pos.y); }, /** * get node position relative to container @@ -1642,7 +1569,7 @@ Kinetic.Node.prototype = { * y property */ setAbsolutePosition: function() { - var pos = Kinetic.Type._getXY(Array.prototype.slice.call(arguments)); + var pos = Kinetic.Type._getXY([].slice.call(arguments)); var trans = this._clearTransform(); // don't clear translation this.attrs.x = trans.x; @@ -1671,7 +1598,7 @@ Kinetic.Node.prototype = { * @param {Number} y */ move: function() { - var pos = Kinetic.Type._getXY(Array.prototype.slice.call(arguments)); + var pos = Kinetic.Type._getXY([].slice.call(arguments)); var x = this.getX(); var y = this.getY(); @@ -1684,10 +1611,7 @@ Kinetic.Node.prototype = { y += pos.y; } - this.setAttrs({ - x: x, - y: y - }); + this.setPosition(x, y); }, /** * get rotation in degrees @@ -1695,7 +1619,16 @@ Kinetic.Node.prototype = { * @methodOf Kinetic.Node.prototype */ getRotationDeg: function() { - return this.attrs.rotation * 180 / Math.PI; + return this.getRotation() * 180 / Math.PI; + }, + /** + * set rotation in degrees + * @name setRotationDeg + * @methodOf Kinetic.Node.prototype + * @param {Number} rotDeg + */ + setRotationDeg: function(rotDeg) { + this.setRotation(rotDeg * Math.PI / 180); }, /** * rotate node by an amount in radians @@ -1704,9 +1637,7 @@ Kinetic.Node.prototype = { * @param {Number} theta */ rotate: function(theta) { - this.setAttrs({ - rotation: this.getRotation() + theta - }); + this.setRotation(this.getRotation() + theta); }, /** * rotate node by an amount in degrees @@ -1715,9 +1646,7 @@ Kinetic.Node.prototype = { * @param {Number} deg */ rotateDeg: function(deg) { - this.setAttrs({ - rotation: this.getRotation() + (deg * Math.PI / 180) - }); + this.setRotation(this.getRotation() + (deg * Math.PI / 180)); }, /** * move node to the top of its siblings @@ -2092,6 +2021,42 @@ Kinetic.Node.prototype = { config.callback(img); }); }, + /** + * set offset. A node's offset defines the position and rotation point + * @name setOffset + * @methodOf Kinetic.Node.prototype + * @param {Number} x + * @param {Number} y + */ + setOffset: function() { + var pos = Kinetic.Type._getXY([].slice.call(arguments)); + if (pos.x === undefined) { + pos.x = this.getOffset().x; + } + if (pos.y === undefined) { + pos.y = this.getOffset().y; + } + this.setAttr('offset', pos); + }, + /** + * set scale. + * @name setScale + * @param {Number} x + * @param {Number} y + * @methodOf Kinetic.Node.prototype + */ + setScale: function() { + var pos = Kinetic.Type._getXY([].slice.call(arguments)); + + if (pos.x === undefined) { + pos.x = this.getScale().x; + } + if (pos.y === undefined) { + pos.y = this.getScale().y; + } + this.setAttr('scale', pos); + + }, _clearTransform: function() { var trans = { x: this.attrs.x, @@ -2138,13 +2103,13 @@ Kinetic.Node.prototype = { newVal: newVal }); }, - _setAttr: function(obj, attr, val) { - if(val !== undefined) { - if(obj === undefined) { - obj = {}; - } - obj[attr] = val; - } + setAttr: function(key, val) { + if (val !== undefined) { + var oldVal = this.attrs[key]; + this._fireBeforeChangeEvent(key, oldVal, val); + this.attrs[key] = val; + this._fireChangeEvent(key, oldVal, val); + } }, _listenDrag: function() { this._dragCleanup(); @@ -2286,16 +2251,8 @@ Kinetic.Node.addGettersSetters = function(constructor, arr) { Kinetic.Node._addSetter = function(constructor, attr) { var that = this; var method = 'set' + attr.charAt(0).toUpperCase() + attr.slice(1); - constructor.prototype[method] = function() { - if(arguments.length == 1) { - arg = arguments[0]; - } - else { - arg = Array.prototype.slice.call(arguments); - } - var obj = {}; - obj[attr] = arg; - this.setAttrs(obj); + constructor.prototype[method] = function(val) { + this.setAttr(attr, val); }; }; Kinetic.Node._addGetter = function(constructor, attr) { @@ -2306,8 +2263,8 @@ Kinetic.Node._addGetter = function(constructor, attr) { }; }; // add getters setters -Kinetic.Node.addGettersSetters(Kinetic.Node, ['x', 'y', 'scale', 'rotation', 'opacity', 'name', 'id', 'offset', 'draggable', 'dragConstraint', 'dragBounds', 'listening']); -Kinetic.Node.addSetters(Kinetic.Node, ['rotationDeg']); +Kinetic.Node.addGettersSetters(Kinetic.Node, ['x', 'y', 'rotation', 'opacity', 'name', 'id', 'draggable', 'dragConstraint', 'dragBounds', 'listening', 'visible']); +Kinetic.Node.addGetters(Kinetic.Node, ['scale', 'offset']); // mappings /** @@ -2385,29 +2342,6 @@ Kinetic.Node.prototype.isDraggable = Kinetic.Node.prototype.getDraggable; * @param {Boolean} listening */ -/** - * set node rotation in degrees - * @name setRotationDeg - * @methodOf Kinetic.Node.prototype - * @param {Number} deg - */ - -/** - * set offset. A node's offset defines the positition and rotation point - * @name setOffset - * @methodOf Kinetic.Node.prototype - * @param {Number} x - * @param {Number} y - */ - -/** - * set node scale. - * @name setScale - * @param {Number} x - * @param {Number} y - * @methodOf Kinetic.Node.prototype - */ - /** * get scale * @name getScale @@ -2785,14 +2719,6 @@ Kinetic.Stage.prototype = { height: 200 }); - /* - * if container is a string, assume it's an id for - * a DOM element - */ - if( typeof config.container === 'string') { - config.container = document.getElementById(config.container); - } - // call super constructor Kinetic.Container.call(this, config); @@ -2801,20 +2727,22 @@ Kinetic.Stage.prototype = { this._buildDOM(); this._bindContentEvents(); - //change events - this.on('widthChange.kinetic', function() { - this._resizeDOM(); - }); - - this.on('heightChange.kinetic', function() { - this._resizeDOM(); - }); var go = Kinetic.Global; go.stages.push(this); this._addId(this); this._addName(this); }, + setContainer: function(container) { + /* + * if container is a string, assume it's an id for + * a DOM element + */ + if( typeof container === 'string') { + container = document.getElementById(container); + } + this.setAttr('container', container); + }, /** * draw children * @name draw @@ -2833,7 +2761,29 @@ Kinetic.Stage.prototype = { setSize: function() { // set stage dimensions var size = Kinetic.Type._getSize(Array.prototype.slice.call(arguments)); - this.setAttrs(size); + this.setWidth(size.width); + this.setHeight(size.height); + }, + + /** + * set height + * @name setHeight + * @methodOf Kinetic.Stage.prototype + * @param {Number} height + */ + setHeight: function(height) { + this.setAttr('height', height); + this._resizeDOM(); + }, + /** + * set width + * @name setWidth + * @methodOf Kinetic.Stage.prototype + * @param {Number} width + */ + setWidth: function(width) { + this.setAttr('width', width); + this._resizeDOM(); }, /** * get stage size @@ -2986,14 +2936,6 @@ Kinetic.Stage.prototype = { getUserPosition: function(evt) { return this.getTouchPosition() || this.getMousePosition(); }, - /** - * get container DOM element - * @name getContainer - * @methodOf Kinetic.Stage.prototype - */ - getContainer: function() { - return this.attrs.container; - }, /** * get stage * @name getStage @@ -3126,22 +3068,24 @@ Kinetic.Stage.prototype = { return null; }, _resizeDOM: function() { - var width = this.attrs.width; - var height = this.attrs.height; - - // set content dimensions - this.content.style.width = width + 'px'; - this.content.style.height = height + 'px'; - - this.bufferCanvas.setSize(width, height); - // set user defined layer dimensions - var layers = this.children; - for(var n = 0; n < layers.length; n++) { - var layer = layers[n]; - layer.getCanvas().setSize(width, height); - layer.bufferCanvas.setSize(width, height); - layer.draw(); - } + if (this.content) { + var width = this.attrs.width; + var height = this.attrs.height; + + // set content dimensions + this.content.style.width = width + 'px'; + this.content.style.height = height + 'px'; + + this.bufferCanvas.setSize(width, height); + // set user defined layer dimensions + var layers = this.children; + for(var n = 0; n < layers.length; n++) { + var layer = layers[n]; + layer.getCanvas().setSize(width, height); + layer.bufferCanvas.setSize(width, height); + layer.draw(); + } + } }, /** * add layer to stage @@ -3548,8 +3492,14 @@ Kinetic.Stage.prototype = { Kinetic.Global.extend(Kinetic.Stage, Kinetic.Container); // add getters and setters -Kinetic.Node.addGettersSetters(Kinetic.Stage, ['width', 'height']); +Kinetic.Node.addGetters(Kinetic.Stage, ['width', 'height', 'container']); +/** + * get container DOM element + * @name getContainer + * @methodOf Kinetic.Stage.prototype + */ + /** * get width * @name getWidth @@ -3562,19 +3512,7 @@ Kinetic.Node.addGettersSetters(Kinetic.Stage, ['width', 'height']); * @methodOf Kinetic.Stage.prototype */ -/** - * set width - * @name setWidth - * @methodOf Kinetic.Stage.prototype - * @param {Number} width - */ -/** - * set height - * @name setHeight - * @methodOf Kinetic.Stage.prototype - * @param {Number} height - */ /////////////////////////////////////////////////////////////////////// // Layer /////////////////////////////////////////////////////////////////////// @@ -4143,6 +4081,72 @@ Kinetic.Shape.prototype = { context.lineJoin = this.attrs.lineJoin; } }, + /** + * set shadow object + * @name setShadow + * @methodOf Kinetic.Shape.prototype + * @param {Object} config + * @param {String} config.color + * @param {Number} config.blur + * @param {Array|Object|Number} config.offset + * @param {Number} config.opacity + */ + setShadow: function(config) { + if(config.offset !== undefined) { + config.offset = Kinetic.Type._getXY(config.offset); + } + this.setAttr('shadow', Kinetic.Type._merge(config, this.getShadow())); + }, + /** + * set fill which can be a color, linear gradient object, + * radial gradient object, or pattern object + * @name setFill + * @methodOf Kinetic.Shape.prototype + * @param {String|Object} fill + */ + setFill: function(config) { + var fill; + + if(Kinetic.Type._isString(config)) { + fill = config; + } + // if not a string, config should be an object + else { + if(config.offset !== undefined) { + config.offset = Kinetic.Type._getXY(config.offset); + } + + var oldFill = this.getFill(); + if(Kinetic.Type._isObject(oldFill)) { + fill = Kinetic.Type._merge(config, oldFill); + } + else { + fill = config; + } + } + this.setAttr('fill', fill); + }, + /** + * set width and height + * @name setSize + * @methodOf Kinetic.Shape.prototype + */ + setSize: function() { + var size = Kinetic.Type._getSize(Array.prototype.slice.call(arguments)); + this.setWidth(size.width); + this.setHeight(size.height); + }, + /** + * return shape size + * @name getSize + * @methodOf Kinetic.Shape.prototype + */ + getSize: function() { + return { + width: this.getWidth(), + height: this.getHeight() + }; + }, /** * apply shadow. return true if shadow was applied * and false if it was not @@ -4279,15 +4283,8 @@ Kinetic.Shape.prototype = { Kinetic.Global.extend(Kinetic.Shape, Kinetic.Node); // add getters and setters -Kinetic.Node.addGettersSetters(Kinetic.Shape, ['fill', 'stroke', 'lineJoin', 'strokeWidth', 'shadow', 'drawFunc', 'filter']); - -/** - * set fill which can be a color, linear gradient object, - * radial gradient object, or pattern object - * @name setFill - * @methodOf Kinetic.Shape.prototype - * @param {String|Object} fill - */ +Kinetic.Node.addGettersSetters(Kinetic.Shape, ['stroke', 'lineJoin', 'strokeWidth', 'drawFunc', 'filter']); +Kinetic.Node.addGetters(Kinetic.Shape, ['shadow', 'fill']); /** * set stroke color @@ -4311,13 +4308,6 @@ Kinetic.Node.addGettersSetters(Kinetic.Shape, ['fill', 'stroke', 'lineJoin', 'st * @param {Number} strokeWidth */ -/** - * set shadow object - * @name setShadow - * @methodOf Kinetic.Shape.prototype - * @param {Object} config - */ - /** * set draw function * @name setDrawFunc @@ -4406,26 +4396,6 @@ Kinetic.Rect.prototype = { this.fill(context); this.stroke(context); - }, - /** - * set width and height - * @name setSize - * @methodOf Kinetic.Rect.prototype - */ - setSize: function() { - var size = Kinetic.Type._getSize(Array.prototype.slice.call(arguments)); - this.setAttrs(size); - }, - /** - * return rect size - * @name getSize - * @methodOf Kinetic.Rect.prototype - */ - getSize: function() { - return { - width: this.attrs.width, - height: this.attrs.height - }; } }; Kinetic.Global.extend(Kinetic.Rect, Kinetic.Shape); @@ -4642,26 +4612,6 @@ Kinetic.Image.prototype = { } } }, - /** - * set width and height - * @name setSize - * @methodOf Kinetic.Image.prototype - */ - setSize: function() { - var size = Kinetic.Type._getSize(Array.prototype.slice.call(arguments)); - this.setAttrs(size); - }, - /** - * return image size - * @name getSize - * @methodOf Kinetic.Image.prototype - */ - getSize: function() { - return { - width: this.attrs.width, - height: this.attrs.height - }; - }, /** * apply filter * @name applyFilter @@ -4672,11 +4622,11 @@ Kinetic.Image.prototype = { * filter has been applied */ applyFilter: function(config) { - var canvas = new Kinetic.Canvas(this.attrs.image.width, this.attrs.image.height); + var canvas = new Kinetic.Canvas(this.attrs.image.width, this.attrs.image.height); var context = canvas.getContext(); context.drawImage(this.attrs.image, 0, 0); - try { - var imageData = context.getImageData(0, 0, canvas.getWidth(), canvas.getHeight()); + try { + var imageData = context.getImageData(0, 0, canvas.getWidth(), canvas.getHeight()); config.filter(imageData, config); var that = this; Kinetic.Type._getImage(imageData, function(imageObj) { @@ -4686,11 +4636,27 @@ Kinetic.Image.prototype = { config.callback(); } }); - } - catch(e) { + } catch(e) { Kinetic.Global.warn('Unable to apply filter.'); } }, + /** + * set crop + * @name setCrop + * @methodOf Kinetic.Image.prototype + * @param {Object|Array} config + * @param {Number} config.x + * @param {Number} config.y + * @param {Number} config.width + * @param {Number} config.height + */ + setCrop: function() { + var config = [].slice.call(arguments); + var pos = Kinetic.Type._getXY(config); + var size = Kinetic.Type._getSize(config); + var both = Kinetic.Type._merge(pos, size); + this.setAttr('crop', Kinetic.Type._merge(both, this.getCrop())); + }, /** * create image buffer which enables more accurate hit detection mapping of the image * by avoiding event detections for transparent pixels @@ -4722,8 +4688,7 @@ Kinetic.Image.prototype = { callback(); } }); - } - catch(e) { + } catch(e) { Kinetic.Global.warn('Unable to create image buffer.'); } }, @@ -4738,14 +4703,10 @@ Kinetic.Image.prototype = { _syncSize: function() { if(this.attrs.image) { if(!this.attrs.width) { - this.setAttrs({ - width: this.attrs.image.width - }); + this.setWidth(this.attrs.image.width); } if(!this.attrs.height) { - this.setAttrs({ - height: this.attrs.image.height - }); + this.setHeight(this.attrs.image.height); } } } @@ -4753,7 +4714,8 @@ Kinetic.Image.prototype = { Kinetic.Global.extend(Kinetic.Image, Kinetic.Shape); // add getters setters -Kinetic.Node.addGettersSetters(Kinetic.Image, ['image', 'crop', 'filter', 'width', 'height']); +Kinetic.Node.addGettersSetters(Kinetic.Image, ['image', 'filter', 'width', 'height']); +Kinetic.Node.addGetters(Kinetic.Image, ['crop']); /** * set width @@ -4776,13 +4738,6 @@ Kinetic.Node.addGettersSetters(Kinetic.Image, ['image', 'crop', 'filter', 'width * @param {ImageObject} image */ -/** - * set crop - * @name setCrop - * @methodOf Kinetic.Image.prototype - * @param {Object} config - */ - /** * set filter * @name setFilter @@ -4985,6 +4940,16 @@ Kinetic.Text.prototype = { } context.restore(); }, + /** + * set text + * @name setText + * @methodOf Kinetic.Text.prototype + * @param {String} text + */ + setText: function(text) { + var str = Kinetic.Type._isString(text) ? text : text.toString(); + this.setAttr('text', str); + }, /** * get box width * @name getBoxWidth @@ -5100,8 +5065,8 @@ Kinetic.Text.prototype = { Kinetic.Global.extend(Kinetic.Text, Kinetic.Shape); // add getters setters -Kinetic.Node.addGettersSetters(Kinetic.Text, ['fontFamily', 'fontSize', 'fontStyle', 'textFill', 'textStroke', 'textStrokeWidth', 'padding', 'align', 'lineHeight', 'text', 'width', 'height', 'cornerRadius', 'fill', 'stroke', 'strokeWidth', 'shadow']); - +Kinetic.Node.addGettersSetters(Kinetic.Text, ['fontFamily', 'fontSize', 'fontStyle', 'textFill', 'textStroke', 'textStrokeWidth', 'padding', 'align', 'lineHeight', 'width', 'height', 'cornerRadius', 'fill', 'stroke', 'strokeWidth', 'shadow']); +Kinetic.Node.addGetters(Kinetic.Text, ['text']); /** * set font family * @name setFontFamily @@ -5165,13 +5130,6 @@ Kinetic.Node.addGettersSetters(Kinetic.Text, ['fontFamily', 'fontSize', 'fontSty * @param {Number} lineHeight default is 1.2 */ -/** - * set text - * @name setText - * @methodOf Kinetic.Text.prototype - * @param {String} text - */ - /** * set width of text box * @name setWidth @@ -5324,6 +5282,16 @@ Kinetic.Line.prototype = { this.stroke(context); }, + /** + * set points array + * @name setPoints + * @methodOf Kinetic.Line.prototype + * @param {Array} can be an array of point objects or an array + * of Numbers. e.g. [{x:1,y:2},{x:3,y:4}] or [1,2,3,4] + */ + setPoints: function(val) { + this.setAttr('points', Kinetic.Type._getPoints(val)); + }, /** * draw dashed line. Written by Phrogz */ @@ -5374,7 +5342,8 @@ Kinetic.Line.prototype = { Kinetic.Global.extend(Kinetic.Line, Kinetic.Shape); // add getters setters -Kinetic.Node.addGettersSetters(Kinetic.Line, ['dashArray', 'lineCap', 'points']); +Kinetic.Node.addGettersSetters(Kinetic.Line, ['dashArray', 'lineCap']); +Kinetic.Node.addGetters(Kinetic.Line, ['points']); /** * set dash array. @@ -5396,14 +5365,6 @@ Kinetic.Node.addGettersSetters(Kinetic.Line, ['dashArray', 'lineCap', 'points']) * @param {String} lineCap */ -/** - * set points array - * @name setPoints - * @methodOf Kinetic.Line.prototype - * @param {Array} can be an array of point objects or an array - * of Numbers. e.g. [{x:1,y:2},{x:3,y:4}] or [1,2,3,4] - */ - /** * get dash array * @name getDashArray diff --git a/dist/kinetic-core.min.js b/dist/kinetic-core.min.js index c74cfd77..ca2074c1 100644 --- a/dist/kinetic-core.min.js +++ b/dist/kinetic-core.min.js @@ -3,7 +3,7 @@ * http://www.kineticjs.com/ * Copyright 2012, Eric Rowell * Licensed under the MIT or GPL Version 2 licenses. - * Date: Sep 23 2012 + * Date: Sep 24 2012 * * Copyright (C) 2011 - 2012 by Eric Rowell * @@ -25,6 +25,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -var Kinetic={};Kinetic.Filters={},Kinetic.Plugins={},Kinetic.Global={BUBBLE_WHITELIST:["mousedown","mousemove","mouseup","mouseover","mouseout","click","dblclick","touchstart","touchmove","touchend","tap","dbltap","dragstart","dragmove","dragend"],BUFFER_WHITELIST:["fill","stroke","textFill","textStroke"],BUFFER_BLACKLIST:["shadow"],stages:[],idCounter:0,tempNodes:{},shapes:{},maxDragTimeInterval:20,drag:{moving:!1,offset:{x:0,y:0},lastDrawTime:0},warn:function(e){console&&console.warn&&console.warn("Kinetic warning: "+e)},extend:function(e,t){for(var n in t.prototype)n in e.prototype||(e.prototype[n]=t.prototype[n])},_pullNodes:function(e){var t=this.tempNodes;for(var n in t){var r=t[n];r.getStage()!==undefined&&r.getStage()._id===e._id&&(e._addId(r),e._addName(r),this._removeTempNode(r))}},_addTempNode:function(e){this.tempNodes[e._id]=e},_removeTempNode:function(e){delete this.tempNodes[e._id]}},Kinetic.Transition=function(e,t){function r(e,t,i,s){for(var o in e)o!=="duration"&&o!=="easing"&&o!=="callback"&&(Kinetic.Type._isObject(e[o])?(i[o]={},r(e[o],t[o],i[o],s)):n._add(n._getTween(t,o,e[o],i,s)))}this.node=e,this.config=t,this.tweens=[];var n=this,i={};r(t,e.attrs,i,i);var s=0;for(var o=0;o=n.tweens.length&&n.onFinished()}}},Kinetic.Transition.prototype={start:function(){for(var e=0;e0},_getXY:function(e){if(this._isNumber(e))return{x:e,y:e};if(this._isArray(e)){if(e.length===1){var t=e[0];if(this._isNumber(t))return{x:t,y:t};if(this._isArray(t))return{x:t[0],y:t[1]};if(this._isObject(t))return t}else if(e.length>=2)return{x:e[0],y:e[1]}}else if(this._isObject(e))return e;return{x:0,y:0}},_getSize:function(e){if(this._isNumber(e))return{width:e,height:e};if(this._isArray(e))if(e.length===1){var t=e[0];if(this._isNumber(t))return{width:t,height:t};if(this._isArray(t)){if(t.length>=4)return{width:t[2],height:t[3]};if(t.length>=2)return{width:t[0],height:t[1]}}else if(this._isObject(t))return t}else{if(e.length>=4)return{width:e[2],height:e[3]};if(e.length>=2)return{width:e[0],height:e[1]}}else if(this._isObject(e))return e;return{width:0,height:0}},_getPoints:function(e){if(e===undefined)return[];if(this._isObject(e[0]))return e;var t=[];for(var n=0;n>16&255,g:t>>8&255,b:t&255}},_getRandomColorKey:function(){var e=Math.round(Math.random()*255),t=Math.round(Math.random()*255),n=Math.round(Math.random()*255);return this._rgbToHex(e,t,n)}},Kinetic.Canvas=function(e,t){this.element=document.createElement("canvas"),this.context=this.element.getContext("2d"),this.element.width=e,this.element.height=t},Kinetic.Canvas.prototype={clear:function(){var e=this.getContext(),t=this.getElement();e.clearRect(0,0,t.width,t.height)},getElement:function(){return this.element},getContext:function(){return this.context},setWidth:function(e){this.element.width=e},setHeight:function(e){this.element.height=e},getWidth:function(){return this.element.width},getHeight:function(){return this.element.height},setSize:function(e,t){this.setWidth(e),this.setHeight(t)},toDataURL:function(e,t){try{return this.element.toDataURL(e,t)}catch(n){return this.element.toDataURL()}}},Kinetic.Tween=function(e,t,n,r,i,s){this._listeners=[],this.addListener(this),this.obj=e,this.propFunc=t,this.begin=r,this._pos=r,this.setDuration(s),this.isPlaying=!1,this._change=0,this.prevTime=0,this.prevPos=0,this.looping=!1,this._time=0,this._position=0,this._startTime=0,this._finish=0,this.name="",this.func=n,this.setFinish(i)},Kinetic.Tween.prototype={setTime:function(e){this.prevTime=this._time,e>this.getDuration()?this.looping?(this.rewind(e-this._duration),this.update(),this.broadcastMessage("onLooped",{target:this,type:"onLooped"})):(this._time=this._duration,this.update(),this.stop(),this.broadcastMessage("onFinished",{target:this,type:"onFinished"})):e<0?(this.rewind(),this.update()):(this._time=e,this.update())},getTime:function(){return this._time},setDuration:function(e){this._duration=e===null||e<=0?1e5:e},getDuration:function(){return this._duration},setPosition:function(e){this.prevPos=this._pos,this.propFunc(e),this._pos=e,this.broadcastMessage("onChanged",{target:this,type:"onChanged"})},getPosition:function(e){return e===undefined&&(e=this._time),this.func(e,this.begin,this._change,this._duration)},setFinish:function(e){this._change=e-this.begin},getFinish:function(){return this.begin+this._change},start:function(){this.rewind(),this.startEnterFrame(),this.broadcastMessage("onStarted",{target:this,type:"onStarted"})},rewind:function(e){this.stop(),this._time=e===undefined?0:e,this.fixTime(),this.update()},fforward:function(){this._time=this._duration,this.fixTime(),this.update()},update:function(){this.setPosition(this.getPosition(this._time))},startEnterFrame:function(){this.stopEnterFrame(),this.isPlaying=!0,this.onEnterFrame()},onEnterFrame:function(){this.isPlaying&&this.nextFrame()},nextFrame:function(){this.setTime((this.getTimer()-this._startTime)/1e3)},stop:function(){this.stopEnterFrame(),this.broadcastMessage("onStopped",{target:this,type:"onStopped"})},stopEnterFrame:function(){this.isPlaying=!1},continueTo:function(e,t){this.begin=this._pos,this.setFinish(e),this._duration!==undefined&&this.setDuration(t),this.start()},resume:function(){this.fixTime(),this.startEnterFrame(),this.broadcastMessage("onResumed",{target:this,type:"onResumed"})},yoyo:function(){this.continueTo(this.begin,this._time)},addListener:function(e){return this.removeListener(e),this._listeners.push(e)},removeListener:function(e){var t=this._listeners,n=t.length;while(n--)if(t[n]==e)return t.splice(n,1),!0;return!1},broadcastMessage:function(){var e=[];for(var t=0;t0){this._runFrames();var e=this;requestAnimFrame(function(){e._animationLoop()})}else this.animRunning=!1},Kinetic.Animation._handleAnimation=function(){var e=this;this.animRunning||(this.animRunning=!0,e._animationLoop())},requestAnimFrame=function(e){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)}}(),Kinetic.Node=function(e){this._nodeInit(e)},Kinetic.Node.prototype={_nodeInit:function(e){this.defaultNodeAttrs={visible:!0,listening:!0,name:undefined,opacity:1,x:0,y:0,scale:{x:1,y:1},rotation:0,offset:{x:0,y:0},dragConstraint:"none",dragBounds:{},draggable:!1},this.setDefaultAttrs(this.defaultNodeAttrs),this.eventListeners={},this.transAnim=new Kinetic.Animation,this.setAttrs(e),this.on("draggableChange.kinetic",function(){this._onDraggableChange()});var t=this;this.on("idChange.kinetic",function(e){var n=t.getStage();n&&(n._removeId(e.oldVal),n._addId(t))}),this.on("nameChange.kinetic",function(e){var n=t.getStage();n&&(n._removeName(e.oldVal,t._id),n._addName(t))}),this._onDraggableChange()},on:function(e,t){var n=e.split(" ");for(var r=0;r1?o[1]:"";this.eventListeners[u]||(this.eventListeners[u]=[]),this.eventListeners[u].push({name:a,handler:t})}},off:function(e){var t=e.split(" ");for(var n=0;n1){var u=s[1];for(var a=0;a0&&s[0].getLevel()<=e&&i(s)}var e=this.getLevel(),t=this.getStage(),n=this,r=0;return n.nodeType!=="Stage"&&i(n.getStage().getChildren()),r},getLevel:function(){var e=0,t=this.parent;while(t)e++,t=t.parent;return e},setPosition:function(){var e=Kinetic.Type._getXY(Array.prototype.slice.call(arguments));this.setAttrs(e)},getPosition:function(){return{x:this.attrs.x,y:this.attrs.y}},getAbsolutePosition:function(){var e=this.getAbsoluteTransform(),t=this.getOffset();return e.translate(t.x,t.y),e.getTranslation()},setAbsolutePosition:function(){var e=Kinetic.Type._getXY(Array.prototype.slice.call(arguments)),t=this._clearTransform();this.attrs.x=t.x,this.attrs.y=t.y,delete t.x,delete t.y;var n=this.getAbsoluteTransform();n.invert(),n.translate(e.x,e.y),e={x:this.attrs.x+n.getTranslation().x,y:this.attrs.y+n.getTranslation().y},this.setPosition(e.x,e.y),this._setTransform(t)},move:function(){var e=Kinetic.Type._getXY(Array.prototype.slice.call(arguments)),t=this.getX(),n=this.getY();e.x!==undefined&&(t+=e.x),e.y!==undefined&&(n+=e.y),this.setAttrs({x:t,y:n})},getRotationDeg:function(){return this.attrs.rotation*180/Math.PI},rotate:function(e){this.setAttrs({rotation:this.getRotation()+e})},rotateDeg:function(e){this.setAttrs({rotation:this.getRotation()+e*Math.PI/180})},moveToTop:function(){var e=this.index;this.parent.children.splice(e,1),this.parent.children.push(this),this.parent._setChildrenIndices();if(this.nodeType==="Layer"){var t=this.getStage();t&&(t.content.removeChild(this.canvas.element),t.content.appendChild(this.canvas.element))}},moveUp:function(){var e=this.index;if(e0){this.parent.children.splice(e,1),this.parent.children.splice(e-1,0,this),this.parent._setChildrenIndices();if(this.nodeType==="Layer"){var t=this.getStage();if(t){var n=t.getChildren();t.content.removeChild(this.canvas.element),t.content.insertBefore(this.canvas.element,n[this.index+1].canvas.element)}}}},moveToBottom:function(){var e=this.index;if(e>0){this.parent.children.splice(e,1),this.parent.children.unshift(this),this.parent._setChildrenIndices();if(this.nodeType==="Layer"){var t=this.getStage();if(t){var n=t.getChildren();t.content.removeChild(this.canvas.element),t.content.insertBefore(this.canvas.element,n[1].canvas.element)}}}},setZIndex:function(e){var t=this.index;this.parent.children.splice(t,1),this.parent.children.splice(e,0,this),this.parent._setChildrenIndices()},getAbsoluteOpacity:function(){var e=1,t=this;while(t.nodeType!=="Stage")e*=t.attrs.opacity,t=t.parent;return e},isDragging:function(){var e=Kinetic.Global;return e.drag.node&&e.drag.node._id===this._id&&e.drag.moving},moveTo:function(e){var t=this.parent;t.children.splice(this.index,1),t._setChildrenIndices(),e.children.push(this),this.index=e.children.length-1,this.parent=e,e._setChildrenIndices()},getParent:function(){return this.parent},getLayer:function(){return this.nodeType==="Layer"?this:this.getParent().getLayer()},getStage:function(){return this.nodeType!=="Stage"&&this.getParent()?this.getParent().getStage():this.nodeType==="Stage"?this:undefined},simulate:function(e){this._handleEvent(e,{})},transitionTo:function(e){var t=this.nodeType==="Stage"?this:this.getLayer(),n=this,r=new Kinetic.Transition(this,e);return this.transAnim.func=function(){r._onEnterFrame()},this.transAnim.node=t,r.onFinished=function(){n.transAnim.stop(),n.transAnim.node.draw(),e.callback&&e.callback()},r.start(),this.transAnim.start(),r},getAbsoluteTransform:function(){var e=new Kinetic.Transform,t=[],n=this.parent;t.unshift(this);while(n)t.unshift(n),n=n.parent;for(var r=0;r=0&&!t.cancelBubble&&this.parent&&(n&&n.parent?this._handleEvent.call(this.parent,e,t,n.parent):this._handleEvent.call(this.parent,e,t))}},_draw:function(e){if(this.isVisible()&&(!e||e.name!=="buffer"||this.getListening())){this.__draw&&this.__draw(e);var t=this.children;if(t)for(var n=0;n0)this.remove(this.children[0])},add:function(e){e._id=Kinetic.Global.idCounter++,e.index=this.children.length,e.parent=this,this.children.push(e);var t=e.getStage();if(!t)Kinetic.Global._addTempNode(e);else{t._addId(e),t._addName(e);var n=Kinetic.Global;n._pullNodes(t)}return this._add!==undefined&&this._add(e),this},remove:function(e){if(e&&e.index!==undefined&&this.children[e.index]._id==e._id){var t=this.getStage();t&&(t._removeId(e.getId()),t._removeName(e.getName(),e._id)),Kinetic.Global._removeTempNode(e),this.children.splice(e.index,1),this._setChildrenIndices();while(e.children&&e.children.length>0)e.remove(e.children[0]);e._remove!==undefined&&e._remove()}return this},get:function(e){var t=this.getStage(),n,r=e.slice(1);if(e.charAt(0)==="#")n=t.ids[r]!==undefined?[t.ids[r]]:[];else{if(e.charAt(0)!==".")return e==="Shape"||e==="Group"||e==="Layer"?this._getNodes(e):!1;n=t.names[r]!==undefined?t.names[r]:[]}var i=new Kinetic.Collection;for(var s=0;s=0;r--){var i=n[r],s=i.bufferCanvas.context.getImageData(Math.round(e.x),Math.round(e.y),1,1).data;if(s[3]===255){var o=Kinetic.Type._rgbToHex(s[0],s[1],s[2]);return t=Kinetic.Global.shapes[o],{shape:t,pixel:s}}if(s[0]>0||s[1]>0||s[2]>0||s[3]>0)return{pixel:s}}return null},_resizeDOM:function(){var e=this.attrs.width,t=this.attrs.height;this.content.style.width=e+"px",this.content.style.height=t+"px",this.bufferCanvas.setSize(e,t);var n=this.children;for(var r=0;ro.right&&(a.x=o.right),o.top!==undefined&&a.yo.bottom&&(a.y=o.bottom),r.setAbsolutePosition(a),s==="horizontal"?r.attrs.y=u.y:s==="vertical"&&(r.attrs.x=u.x),n.drag.moving||(n.drag.moving=!0,n.drag.node._handleEvent("dragstart",e)),n.drag.node._handleEvent("dragmove",e)}},_buildDOM:function(){this.content=document.createElement("div"),this.content.style.position="relative",this.content.style.display="inline-block",this.content.className="kineticjs-content",this.attrs.container.appendChild(this.content),this.bufferCanvas=new Kinetic.Canvas({width:this.attrs.width,height:this.attrs.height}),this._resizeDOM()},_addId:function(e){e.attrs.id!==undefined&&(this.ids[e.attrs.id]=e)},_removeId:function(e){e!==undefined&&delete this.ids[e]},_addName:function(e){var t=e.attrs.name;t!==undefined&&(this.names[t]===undefined&&(this.names[t]=[]),this.names[t].push(e))},_removeName:function(e,t){if(e!==undefined){var n=this.names[e];if(n!==undefined){for(var r=0;r0},_remove:function(){delete Kinetic.Global.shapes[this.colorKey]},__draw:function(e){if(this.attrs.drawFunc){var t=this.getStage(),n=e.getContext(),r=[],i=this.parent;r.unshift(this);while(i)r.unshift(i),i=i.parent;n.save();for(var s=0;s0&&r&&(this.attrs.height==="auto"||i*(n+1)this.attrs.width-this.attrs.padding*2){if(s==0)break;var a=u.lastIndexOf(" "),f=u.lastIndexOf("-"),l=Math.max(a,f);if(l>=0){o=e.splice(0,1+l).join("");break}o=e.splice(0,s).join("");break}s++,s===e.length&&(o=e.splice(0,s).join(""))}this.textWidth=Math.max(this.textWidth,this._getTextSize(o).width),o!==undefined&&(t.push(o),r=!0),n++}this.textArr=t}},Kinetic.Global.extend(Kinetic.Text,Kinetic.Shape),Kinetic.Node.addGettersSetters(Kinetic.Text,["fontFamily","fontSize","fontStyle","textFill","textStroke","textStrokeWidth","padding","align","lineHeight","text","width","height","cornerRadius","fill","stroke","strokeWidth","shadow"]),Kinetic.Line=function(e){this._initLine(e)},Kinetic.Line.prototype={_initLine:function(e){this.setDefaultAttrs({points:[],lineCap:"butt",dashArray:[],detectionType:"pixel"}),this.shapeType="Line",e.drawFunc=this.drawFunc,Kinetic.Shape.call(this,e)},drawFunc:function(e){var t={};e.beginPath(),e.moveTo(this.attrs.points[0].x,this.attrs.points[0].y);for(var n=1;n0){var s=this.attrs.points[n-1].x,o=this.attrs.points[n-1].y;this._dashedLine(e,s,o,r,i,this.attrs.dashArray)}else e.lineTo(r,i)}!this.attrs.lineCap||(e.lineCap=this.attrs.lineCap),this.stroke(e)},_dashedLine:function(e,t,n,r,i,s){var o=s.length,u=r-t,a=i-n,f=u>a,l=f?a/u:u/a;l>9999?l=9999:l<-9999&&(l=-9999);var c=Math.sqrt(u*u+a*a),h=0,p=!0;while(c>=.1&&h<1e4){var d=s[h++%o];d===0&&(d=.001),d>c&&(d=c);var v=Math.sqrt(d*d/(1+l*l));f?(t+=u<0&&a<0?v*-1:v,n+=u<0&&a<0?l*v*-1:l*v):(t+=u<0&&a<0?l*v*-1:l*v,n+=u<0&&a<0?v*-1:v),e[p?"lineTo":"moveTo"](t,n),c-=d,p=!p}e.moveTo(r,i)}},Kinetic.Global.extend(Kinetic.Line,Kinetic.Shape),Kinetic.Node.addGettersSetters(Kinetic.Line,["dashArray","lineCap","points"]),Kinetic.Sprite=function(e){this._initSprite(e)},Kinetic.Sprite.prototype={_initSprite:function(e){this.setDefaultAttrs({index:0,frameRate:17}),e.drawFunc=this.drawFunc,Kinetic.Shape.call(this,e),this.anim=new Kinetic.Animation;var t=this;this.on("animationChange.kinetic",function(){t.setIndex(0)})},drawFunc:function(e){var t=this.attrs.animation,n=this.attrs.index,r=this.attrs.animations[t][n];e.beginPath(),e.rect(0,0,r.width,r.height),e.closePath(),this.fill(e),this.stroke(e),this.attrs.image&&(e.beginPath(),e.rect(0,0,r.width,r.height),e.closePath(),this.drawImage(e,this.attrs.image,r.x,r.y,r.width,r.height,0,0,r.width,r.height))},start:function(){var e=this,t=this.getLayer();this.anim.node=t,this.interval=setInterval(function(){var t=e.attrs.index;e._updateIndex(),e.afterFrameFunc&&t===e.afterFrameIndex&&(e.afterFrameFunc(),delete e.afterFrameFunc,delete e.afterFrameIndex)},1e3/this.attrs.frameRate),this.anim.start()},stop:function(){this.anim.stop(),clearInterval(this.interval)},afterFrame:function(e,t){this.afterFrameIndex=e,this.afterFrameFunc=t},_updateIndex:function(){var e=this.attrs.index,t=this.attrs.animation;ea?u:a,d=u>a?1:u/a,v=u>a?a/u:1;e.translate(s,o),e.rotate(c),e.scale(d,v),e.arc(0,0,p,f,f+l,1-h),e.scale(1/d,1/v),e.rotate(-c),e.translate(-s,-o);break;case"z":e.closePath()}}this.fill(e),this.stroke(e)}},Kinetic.Global.extend(Kinetic.Path,Kinetic.Shape),Kinetic.Path.getLineLength=function(e,t,n,r){return Math.sqrt((n-e)*(n-e)+(r-t)*(r-t))},Kinetic.Path.getPointOnLine=function(e,t,n,r,i,s,o){s===undefined&&(s=t),o===undefined&&(o=n);var u=(i-n)/(r-t+1e-8),a=Math.sqrt(e*e/(1+u*u)),f=u*a,l;if((o-n)/(s-t+1e-8)===u)l={x:s+a,y:o+f};else{var c,h,p=this.getLineLength(t,n,r,i);if(p<1e-8)return undefined;var d=(s-t)*(r-t)+(o-n)*(i-n);d/=p*p,c=t+d*(r-t),h=n+d*(i-n);var v=this.getLineLength(s,o,c,h),m=Math.sqrt(e*e-v*v);a=Math.sqrt(m*m/(1+u*u)),f=u*a,l={x:c+a,y:h+f}}return l},Kinetic.Path.getPointOnCubicBezier=function(e,t,n,r,i,s,o,u,a){function f(e){return e*e*e}function l(e){return 3*e*e*(1-e)}function c(e){return 3*e*(1-e)*(1-e)}function h(e){return(1-e)*(1-e)*(1-e)}var p=u*f(e)+s*l(e)+r*c(e)+t*h(e),d=a*f(e)+o*l(e)+i*c(e)+n*h(e);return{x:p,y:d}},Kinetic.Path.getPointOnQuadraticBezier=function(e,t,n,r,i,s,o){function u(e){return e*e}function a(e){return 2*e*(1-e)}function f(e){return(1-e)*(1-e)}var l=s*u(e)+r*a(e)+t*f(e),c=o*u(e)+i*a(e)+n*f(e);return{x:l,y:c}},Kinetic.Path.getPointOnEllipticalArc=function(e,t,n,r,i,s){var o=Math.cos(s),u=Math.sin(s),a={x:n*Math.cos(i),y:r*Math.sin(i)};return{x:e+(a.x*o-a.y*u),y:t+(a.x*u+a.y*o)}},Kinetic.Path.parsePathData=function(e){if(!e)return[];var t=e,n=["m","M","l","L","v","V","h","H","z","Z","c","C","q","Q","t","T","s","S","a","A"];t=t.replace(new RegExp(" ","g"),",");for(var r=0;r0&&l[0]===""&&l.shift();for(var c=0;c0){if(isNaN(l[0]))break;var h=null,p=[],d=o,v=u;switch(f){case"l":o+=l.shift(),u+=l.shift(),h="L",p.push(o,u);break;case"L":o=l.shift(),u=l.shift(),p.push(o,u);break;case"m":o+=l.shift(),u+=l.shift(),h="M",p.push(o,u),f="l";break;case"M":o=l.shift(),u=l.shift(),h="M",p.push(o,u),f="L";break;case"h":o+=l.shift(),h="L",p.push(o,u);break;case"H":o=l.shift(),h="L",p.push(o,u);break;case"v":u+=l.shift(),h="L",p.push(o,u);break;case"V":u=l.shift(),h="L",p.push(o,u);break;case"C":p.push(l.shift(),l.shift(),l.shift(),l.shift()),o=l.shift(),u=l.shift(),p.push(o,u);break;case"c":p.push(o+l.shift(),u+l.shift(),o+l.shift(),u+l.shift()),o+=l.shift(),u+=l.shift(),h="C",p.push(o,u);break;case"S":var m=o,g=u,y=s[s.length-1];y.command==="C"&&(m=o+(o-y.points[2]),g=u+(u-y.points[3])),p.push(m,g,l.shift(),l.shift()),o=l.shift(),u=l.shift(),h="C",p.push(o,u);break;case"s":var m=o,g=u,y=s[s.length-1];y.command==="C"&&(m=o+(o-y.points[2]),g=u+(u-y.points[3])),p.push(m,g,o+l.shift(),u+l.shift()),o+=l.shift(),u+=l.shift(),h="C",p.push(o,u);break;case"Q":p.push(l.shift(),l.shift()),o=l.shift(),u=l.shift(),p.push(o,u);break;case"q":p.push(o+l.shift(),u+l.shift()),o+=l.shift(),u+=l.shift(),h="Q",p.push(o,u);break;case"T":var m=o,g=u,y=s[s.length-1];y.command==="Q"&&(m=o+(o-y.points[0]),g=u+(u-y.points[1])),o=l.shift(),u=l.shift(),h="Q",p.push(m,g,o,u);break;case"t":var m=o,g=u,y=s[s.length-1];y.command==="Q"&&(m=o+(o-y.points[0]),g=u+(u-y.points[1])),o+=l.shift(),u+=l.shift(),h="Q",p.push(m,g,o,u);break;case"A":var b=l.shift(),w=l.shift(),E=l.shift(),S=l.shift(),x=l.shift(),T=o,N=u;o=l.shift(),u=l.shift(),h="A",p=this.convertEndpointToCenterParameterization(T,N,o,u,S,x,b,w,E);break;case"a":var b=l.shift(),w=l.shift(),E=l.shift(),S=l.shift(),x=l.shift(),T=o,N=u;o+=l.shift(),u+=l.shift(),h="A",p=this.convertEndpointToCenterParameterization(T,N,o,u,S,x,b,w,E)}s.push({command:h||f,points:p,start:{x:d,y:v},pathLength:this.calcLength(d,v,h||f,p)})}(f==="z"||f==="Z")&&s.push({command:"z",points:[],start:undefined,pathLength:0})}return s},Kinetic.Path.calcLength=function(e,n,r,i){var s,o,u,a=Kinetic.Path;switch(r){case"L":return a.getLineLength(e,n,i[0],i[1]);case"C":s=0,o=a.getPointOnCubicBezier(0,e,n,i[0],i[1],i[2],i[3],i[4],i[5]);for(t=.01;t<=1;t+=.01)u=a.getPointOnCubicBezier(t,e,n,i[0],i[1],i[2],i[3],i[4],i[5]),s+=a.getLineLength(o.x,o.y,u.x,u.y),o=u;return s;case"Q":s=0,o=a.getPointOnQuadraticBezier(0,e,n,i[0],i[1],i[2],i[3]);for(t=.01;t<=1;t+=.01)u=a.getPointOnQuadraticBezier(t,e,n,i[0],i[1],i[2],i[3]),s+=a.getLineLength(o.x,o.y,u.x,u.y),o=u;return s;case"A":s=0;var f=i[4],l=i[5],c=i[4]+l,h=Math.PI/180;Math.abs(f-c)c;t-=h)u=a.getPointOnEllipticalArc(i[0],i[1],i[2],i[3],t,0),s+=a.getLineLength(o.x,o.y,u.x,u.y),o=u;else for(t=f+h;t1&&(o*=Math.sqrt(h),u*=Math.sqrt(h));var p=Math.sqrt((o*o*u*u-o*o*c*c-u*u*l*l)/(o*o*c*c+u*u*l*l));i==s&&(p*=-1),isNaN(p)&&(p=0);var d=p*o*c/u,v=p*-u*l/o,m=(e+n)/2+Math.cos(f)*d-Math.sin(f)*v,g=(t+r)/2+Math.sin(f)*d+Math.cos(f)*v,y=function(e){return Math.sqrt(e[0]*e[0]+e[1]*e[1])},b=function(e,t){return(e[0]*t[0]+e[1]*t[1])/(y(e)*y(t))},w=function(e,t){return(e[0]*t[1]=1&&(T=0),s===0&&T>0&&(T-=2*Math.PI),s==1&&T<0&&(T+=2*Math.PI),[m,g,o,u,E,T,f,s]},Kinetic.Node.addGettersSetters(Kinetic.Path,["data"]),Kinetic.TextPath=function(e){this._initTextPath(e)},Kinetic.TextPath.prototype={_initTextPath:function(e){this.setDefaultAttrs({fontFamily:"Calibri",fontSize:12,fontStyle:"normal",detectionType:"path",text:""}),this.dummyCanvas=document.createElement("canvas"),this.shapeType="TextPath",this.dataArray=[];var t=this;e.drawFunc=this.drawFunc,Kinetic.Shape.call(this,e),this.dataArray=Kinetic.Path.parsePathData(this.attrs.data),this.on("dataChange",function(){t.dataArray=Kinetic.Path.parsePathData(this.attrs.data)});var n=["text","textStroke","textStrokeWidth"];for(var r=0;r0)return o=n,t[n];t[n].command=="M"&&(r={x:t[n].points[0],y:t[n].points[1]})}return{}},f=function(t,n){var o=e._getTextSize(t).width,f=0,l=0,c=!1;i=undefined;while(Math.abs(o-f)/o>.01&&l<25){l++;var h=f;while(s===undefined)s=a(),s&&h+s.pathLengtho?i=Kinetic.Path.getPointOnLine(o,r.x,r.y,s.points[0],s.points[1],r.x,r.y):s=undefined;break;case"A":var d=s.points[4],v=s.points[5],m=s.points[4]+v;u===0?u=d+1e-8:o>f?u+=Math.PI/180*v/Math.abs(v):u-=Math.PI/360*v/Math.abs(v),Math.abs(u)>Math.abs(m)&&(u=m,p=!0),i=Kinetic.Path.getPointOnEllipticalArc(s.points[0],s.points[1],s.points[2],s.points[3],u,s.points[6]);break;case"C":u===0?o>s.pathLength?u=1e-8:u=o/s.pathLength:o>f?u+=(o-f)/s.pathLength:u-=(f-o)/s.pathLength,u>1&&(u=1,p=!0),i=Kinetic.Path.getPointOnCubicBezier(u,s.start.x,s.start.y,s.points[0],s.points[1],s.points[2],s.points[3],s.points[4],s.points[5]);break;case"Q":u===0?u=o/s.pathLength:o>f?u+=(o-f)/s.pathLength:u-=(f-o)/s.pathLength,u>1&&(u=1,p=!0),i=Kinetic.Path.getPointOnQuadraticBezier(u,s.start.x,s.start.y,s.points[0],s.points[1],s.points[2],s.points[3])}i!==undefined&&(f=Kinetic.Path.getLineLength(r.x,r.y,i.x,i.y)),p&&(p=!1,s=undefined)}};for(var l=0;l=n.tweens.length&&n.onFinished()}}},Kinetic.Transition.prototype={start:function(){for(var e=0;e0},_getXY:function(e){if(this._isNumber(e))return{x:e,y:e};if(this._isArray(e)){if(e.length===1){var t=e[0];if(this._isNumber(t))return{x:t,y:t};if(this._isArray(t))return{x:t[0],y:t[1]};if(this._isObject(t))return t}else if(e.length>=2)return{x:e[0],y:e[1]}}else if(this._isObject(e))return e;return{x:0,y:0}},_getSize:function(e){if(this._isNumber(e))return{width:e,height:e};if(this._isArray(e))if(e.length===1){var t=e[0];if(this._isNumber(t))return{width:t,height:t};if(this._isArray(t)){if(t.length>=4)return{width:t[2],height:t[3]};if(t.length>=2)return{width:t[0],height:t[1]}}else if(this._isObject(t))return t}else{if(e.length>=4)return{width:e[2],height:e[3]};if(e.length>=2)return{width:e[0],height:e[1]}}else if(this._isObject(e))return e;return{width:0,height:0}},_getPoints:function(e){if(e===undefined)return[];if(this._isObject(e[0]))return e;var t=[];for(var n=0;n>16&255,g:t>>8&255,b:t&255}},_getRandomColorKey:function(){var e=Math.round(Math.random()*255),t=Math.round(Math.random()*255),n=Math.round(Math.random()*255);return this._rgbToHex(e,t,n)},_merge:function(e,t){var n=this._clone(t);for(var r in e)this._isObject(e[r])?n[r]=this._merge(e[r],n[r]):n[r]=e[r];return n},_clone:function(e){var t={};for(var n in e)this._isObject(e[n])?t[n]=this._clone(e[n]):t[n]=e[n];return t}},Kinetic.Canvas=function(e,t){this.element=document.createElement("canvas"),this.context=this.element.getContext("2d"),this.element.width=e,this.element.height=t},Kinetic.Canvas.prototype={clear:function(){var e=this.getContext(),t=this.getElement();e.clearRect(0,0,t.width,t.height)},getElement:function(){return this.element},getContext:function(){return this.context},setWidth:function(e){this.element.width=e},setHeight:function(e){this.element.height=e},getWidth:function(){return this.element.width},getHeight:function(){return this.element.height},setSize:function(e,t){this.setWidth(e),this.setHeight(t)},toDataURL:function(e,t){try{return this.element.toDataURL(e,t)}catch(n){return this.element.toDataURL()}}},Kinetic.Tween=function(e,t,n,r,i,s){this._listeners=[],this.addListener(this),this.obj=e,this.propFunc=t,this.begin=r,this._pos=r,this.setDuration(s),this.isPlaying=!1,this._change=0,this.prevTime=0,this.prevPos=0,this.looping=!1,this._time=0,this._position=0,this._startTime=0,this._finish=0,this.name="",this.func=n,this.setFinish(i)},Kinetic.Tween.prototype={setTime:function(e){this.prevTime=this._time,e>this.getDuration()?this.looping?(this.rewind(e-this._duration),this.update(),this.broadcastMessage("onLooped",{target:this,type:"onLooped"})):(this._time=this._duration,this.update(),this.stop(),this.broadcastMessage("onFinished",{target:this,type:"onFinished"})):e<0?(this.rewind(),this.update()):(this._time=e,this.update())},getTime:function(){return this._time},setDuration:function(e){this._duration=e===null||e<=0?1e5:e},getDuration:function(){return this._duration},setPosition:function(e){this.prevPos=this._pos,this.propFunc(e),this._pos=e,this.broadcastMessage("onChanged",{target:this,type:"onChanged"})},getPosition:function(e){return e===undefined&&(e=this._time),this.func(e,this.begin,this._change,this._duration)},setFinish:function(e){this._change=e-this.begin},getFinish:function(){return this.begin+this._change},start:function(){this.rewind(),this.startEnterFrame(),this.broadcastMessage("onStarted",{target:this,type:"onStarted"})},rewind:function(e){this.stop(),this._time=e===undefined?0:e,this.fixTime(),this.update()},fforward:function(){this._time=this._duration,this.fixTime(),this.update()},update:function(){this.setPosition(this.getPosition(this._time))},startEnterFrame:function(){this.stopEnterFrame(),this.isPlaying=!0,this.onEnterFrame()},onEnterFrame:function(){this.isPlaying&&this.nextFrame()},nextFrame:function(){this.setTime((this.getTimer()-this._startTime)/1e3)},stop:function(){this.stopEnterFrame(),this.broadcastMessage("onStopped",{target:this,type:"onStopped"})},stopEnterFrame:function(){this.isPlaying=!1},continueTo:function(e,t){this.begin=this._pos,this.setFinish(e),this._duration!==undefined&&this.setDuration(t),this.start()},resume:function(){this.fixTime(),this.startEnterFrame(),this.broadcastMessage("onResumed",{target:this,type:"onResumed"})},yoyo:function(){this.continueTo(this.begin,this._time)},addListener:function(e){return this.removeListener(e),this._listeners.push(e)},removeListener:function(e){var t=this._listeners,n=t.length;while(n--)if(t[n]==e)return t.splice(n,1),!0;return!1},broadcastMessage:function(){var e=[];for(var t=0;t0){this._runFrames();var e=this;requestAnimFrame(function(){e._animationLoop()})}else this.animRunning=!1},Kinetic.Animation._handleAnimation=function(){var e=this;this.animRunning||(this.animRunning=!0,e._animationLoop())},requestAnimFrame=function(e){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)}}(),Kinetic.Node=function(e){this._nodeInit(e)},Kinetic.Node.prototype={_nodeInit:function(e){this.defaultNodeAttrs={visible:!0,listening:!0,name:undefined,opacity:1,x:0,y:0,scale:{x:1,y:1},rotation:0,offset:{x:0,y:0},dragConstraint:"none",dragBounds:{},draggable:!1},this.setDefaultAttrs(this.defaultNodeAttrs),this.eventListeners={},this.transAnim=new Kinetic.Animation,this.setAttrs(e),this.on("draggableChange.kinetic",function(){this._onDraggableChange()});var t=this;this.on("idChange.kinetic",function(e){var n=t.getStage();n&&(n._removeId(e.oldVal),n._addId(t))}),this.on("nameChange.kinetic",function(e){var n=t.getStage();n&&(n._removeName(e.oldVal,t._id),n._addName(t))}),this._onDraggableChange()},on:function(e,t){var n=e.split(" ");for(var r=0;r1?o[1]:"";this.eventListeners[u]||(this.eventListeners[u]=[]),this.eventListeners[u].push({name:a,handler:t})}},off:function(e){var t=e.split(" ");for(var n=0;n1){var u=s[1];for(var a=0;a0&&s[0].getLevel()<=e&&i(s)}var e=this.getLevel(),t=this.getStage(),n=this,r=0;return n.nodeType!=="Stage"&&i(n.getStage().getChildren()),r},getLevel:function(){var e=0,t=this.parent;while(t)e++,t=t.parent;return e},setPosition:function(){var e=Kinetic.Type._getXY([].slice.call(arguments));this.setAttr("x",e.x),this.setAttr("y",e.y)},getPosition:function(){return{x:this.attrs.x,y:this.attrs.y}},getAbsolutePosition:function(){var e=this.getAbsoluteTransform(),t=this.getOffset();return e.translate(t.x,t.y),e.getTranslation()},setAbsolutePosition:function(){var e=Kinetic.Type._getXY([].slice.call(arguments)),t=this._clearTransform();this.attrs.x=t.x,this.attrs.y=t.y,delete t.x,delete t.y;var n=this.getAbsoluteTransform();n.invert(),n.translate(e.x,e.y),e={x:this.attrs.x+n.getTranslation().x,y:this.attrs.y+n.getTranslation().y},this.setPosition(e.x,e.y),this._setTransform(t)},move:function(){var e=Kinetic.Type._getXY([].slice.call(arguments)),t=this.getX(),n=this.getY();e.x!==undefined&&(t+=e.x),e.y!==undefined&&(n+=e.y),this.setPosition(t,n)},getRotationDeg:function(){return this.getRotation()*180/Math.PI},setRotationDeg:function(e){this.setRotation(e*Math.PI/180)},rotate:function(e){this.setRotation(this.getRotation()+e)},rotateDeg:function(e){this.setRotation(this.getRotation()+e*Math.PI/180)},moveToTop:function(){var e=this.index;this.parent.children.splice(e,1),this.parent.children.push(this),this.parent._setChildrenIndices();if(this.nodeType==="Layer"){var t=this.getStage();t&&(t.content.removeChild(this.canvas.element),t.content.appendChild(this.canvas.element))}},moveUp:function(){var e=this.index;if(e0){this.parent.children.splice(e,1),this.parent.children.splice(e-1,0,this),this.parent._setChildrenIndices();if(this.nodeType==="Layer"){var t=this.getStage();if(t){var n=t.getChildren();t.content.removeChild(this.canvas.element),t.content.insertBefore(this.canvas.element,n[this.index+1].canvas.element)}}}},moveToBottom:function(){var e=this.index;if(e>0){this.parent.children.splice(e,1),this.parent.children.unshift(this),this.parent._setChildrenIndices();if(this.nodeType==="Layer"){var t=this.getStage();if(t){var n=t.getChildren();t.content.removeChild(this.canvas.element),t.content.insertBefore(this.canvas.element,n[1].canvas.element)}}}},setZIndex:function(e){var t=this.index;this.parent.children.splice(t,1),this.parent.children.splice(e,0,this),this.parent._setChildrenIndices()},getAbsoluteOpacity:function(){var e=1,t=this;while(t.nodeType!=="Stage")e*=t.attrs.opacity,t=t.parent;return e},isDragging:function(){var e=Kinetic.Global;return e.drag.node&&e.drag.node._id===this._id&&e.drag.moving},moveTo:function(e){var t=this.parent;t.children.splice(this.index,1),t._setChildrenIndices(),e.children.push(this),this.index=e.children.length-1,this.parent=e,e._setChildrenIndices()},getParent:function(){return this.parent},getLayer:function(){return this.nodeType==="Layer"?this:this.getParent().getLayer()},getStage:function(){return this.nodeType!=="Stage"&&this.getParent()?this.getParent().getStage():this.nodeType==="Stage"?this:undefined},simulate:function(e){this._handleEvent(e,{})},transitionTo:function(e){var t=this.nodeType==="Stage"?this:this.getLayer(),n=this,r=new Kinetic.Transition(this,e);return this.transAnim.func=function(){r._onEnterFrame()},this.transAnim.node=t,r.onFinished=function(){n.transAnim.stop(),n.transAnim.node.draw(),e.callback&&e.callback()},r.start(),this.transAnim.start(),r},getAbsoluteTransform:function(){var e=new Kinetic.Transform,t=[],n=this.parent;t.unshift(this);while(n)t.unshift(n),n=n.parent;for(var r=0;r=0&&!t.cancelBubble&&this.parent&&(n&&n.parent?this._handleEvent.call(this.parent,e,t,n.parent):this._handleEvent.call(this.parent,e,t))}},_draw:function(e){if(this.isVisible()&&(!e||e.name!=="buffer"||this.getListening())){this.__draw&&this.__draw(e);var t=this.children;if(t)for(var n=0;n0)this.remove(this.children[0])},add:function(e){e._id=Kinetic.Global.idCounter++,e.index=this.children.length,e.parent=this,this.children.push(e);var t=e.getStage();if(!t)Kinetic.Global._addTempNode(e);else{t._addId(e),t._addName(e);var n=Kinetic.Global;n._pullNodes(t)}return this._add!==undefined&&this._add(e),this},remove:function(e){if(e&&e.index!==undefined&&this.children[e.index]._id==e._id){var t=this.getStage();t&&(t._removeId(e.getId()),t._removeName(e.getName(),e._id)),Kinetic.Global._removeTempNode(e),this.children.splice(e.index,1),this._setChildrenIndices();while(e.children&&e.children.length>0)e.remove(e.children[0]);e._remove!==undefined&&e._remove()}return this},get:function(e){var t=this.getStage(),n,r=e.slice(1);if(e.charAt(0)==="#")n=t.ids[r]!==undefined?[t.ids[r]]:[];else{if(e.charAt(0)!==".")return e==="Shape"||e==="Group"||e==="Layer"?this._getNodes(e):!1;n=t.names[r]!==undefined?t.names[r]:[]}var i=new Kinetic.Collection;for(var s=0;s=0;r--){var i=n[r],s=i.bufferCanvas.context.getImageData(Math.round(e.x),Math.round(e.y),1,1).data;if(s[3]===255){var o=Kinetic.Type._rgbToHex(s[0],s[1],s[2]);return t=Kinetic.Global.shapes[o],{shape:t,pixel:s}}if(s[0]>0||s[1]>0||s[2]>0||s[3]>0)return{pixel:s}}return null},_resizeDOM:function(){if(this.content){var e=this.attrs.width,t=this.attrs.height;this.content.style.width=e+"px",this.content.style.height=t+"px",this.bufferCanvas.setSize(e,t);var n=this.children;for(var r=0;ro.right&&(a.x=o.right),o.top!==undefined&&a.yo.bottom&&(a.y=o.bottom),r.setAbsolutePosition(a),s==="horizontal"?r.attrs.y=u.y:s==="vertical"&&(r.attrs.x=u.x),n.drag.moving||(n.drag.moving=!0,n.drag.node._handleEvent("dragstart",e)),n.drag.node._handleEvent("dragmove",e)}},_buildDOM:function(){this.content=document.createElement("div"),this.content.style.position="relative",this.content.style.display="inline-block",this.content.className="kineticjs-content",this.attrs.container.appendChild(this.content),this.bufferCanvas=new Kinetic.Canvas({width:this.attrs.width,height:this.attrs.height}),this._resizeDOM()},_addId:function(e){e.attrs.id!==undefined&&(this.ids[e.attrs.id]=e)},_removeId:function(e){e!==undefined&&delete this.ids[e]},_addName:function(e){var t=e.attrs.name;t!==undefined&&(this.names[t]===undefined&&(this.names[t]=[]),this.names[t].push(e))},_removeName:function(e,t){if(e!==undefined){var n=this.names[e];if(n!==undefined){for(var r=0;r0},_remove:function(){delete Kinetic.Global.shapes[this.colorKey]},__draw:function(e){if(this.attrs.drawFunc){var t=this.getStage(),n=e.getContext(),r=[],i=this.parent;r.unshift(this);while(i)r.unshift(i),i=i.parent;n.save();for(var s=0;s0&&r&&(this.attrs.height==="auto"||i*(n+1)this.attrs.width-this.attrs.padding*2){if(s==0)break;var a=u.lastIndexOf(" "),f=u.lastIndexOf("-"),l=Math.max(a,f);if(l>=0){o=e.splice(0,1+l).join("");break}o=e.splice(0,s).join("");break}s++,s===e.length&&(o=e.splice(0,s).join(""))}this.textWidth=Math.max(this.textWidth,this._getTextSize(o).width),o!==undefined&&(t.push(o),r=!0),n++}this.textArr=t}},Kinetic.Global.extend(Kinetic.Text,Kinetic.Shape),Kinetic.Node.addGettersSetters(Kinetic.Text,["fontFamily","fontSize","fontStyle","textFill","textStroke","textStrokeWidth","padding","align","lineHeight","width","height","cornerRadius","fill","stroke","strokeWidth","shadow"]),Kinetic.Node.addGetters(Kinetic.Text,["text"]),Kinetic.Line=function(e){this._initLine(e)},Kinetic.Line.prototype={_initLine:function(e){this.setDefaultAttrs({points:[],lineCap:"butt",dashArray:[],detectionType:"pixel"}),this.shapeType="Line",e.drawFunc=this.drawFunc,Kinetic.Shape.call(this,e)},drawFunc:function(e){var t={};e.beginPath(),e.moveTo(this.attrs.points[0].x,this.attrs.points[0].y);for(var n=1;n0){var s=this.attrs.points[n-1].x,o=this.attrs.points[n-1].y;this._dashedLine(e,s,o,r,i,this.attrs.dashArray)}else e.lineTo(r,i)}!this.attrs.lineCap||(e.lineCap=this.attrs.lineCap),this.stroke(e)},setPoints:function(e){this.setAttr("points",Kinetic.Type._getPoints(e))},_dashedLine:function(e,t,n,r,i,s){var o=s.length,u=r-t,a=i-n,f=u>a,l=f?a/u:u/a;l>9999?l=9999:l<-9999&&(l=-9999);var c=Math.sqrt(u*u+a*a),h=0,p=!0;while(c>=.1&&h<1e4){var d=s[h++%o];d===0&&(d=.001),d>c&&(d=c);var v=Math.sqrt(d*d/(1+l*l));f?(t+=u<0&&a<0?v*-1:v,n+=u<0&&a<0?l*v*-1:l*v):(t+=u<0&&a<0?l*v*-1:l*v,n+=u<0&&a<0?v*-1:v),e[p?"lineTo":"moveTo"](t,n),c-=d,p=!p}e.moveTo(r,i)}},Kinetic.Global.extend(Kinetic.Line,Kinetic.Shape),Kinetic.Node.addGettersSetters(Kinetic.Line,["dashArray","lineCap"]),Kinetic.Node.addGetters(Kinetic.Line,["points"]),Kinetic.Sprite=function(e){this._initSprite(e)},Kinetic.Sprite.prototype={_initSprite:function(e){this.setDefaultAttrs({index:0,frameRate:17}),e.drawFunc=this.drawFunc,Kinetic.Shape.call(this,e),this.anim=new Kinetic.Animation;var t=this;this.on("animationChange.kinetic",function(){t.setIndex(0)})},drawFunc:function(e){var t=this.attrs.animation,n=this.attrs.index,r=this.attrs.animations[t][n];e.beginPath(),e.rect(0,0,r.width,r.height),e.closePath(),this.fill(e),this.stroke(e),this.attrs.image&&(e.beginPath(),e.rect(0,0,r.width,r.height),e.closePath(),this.drawImage(e,this.attrs.image,r.x,r.y,r.width,r.height,0,0,r.width,r.height))},start:function(){var e=this,t=this.getLayer();this.anim.node=t,this.interval=setInterval(function(){var t=e.attrs.index;e._updateIndex(),e.afterFrameFunc&&t===e.afterFrameIndex&&(e.afterFrameFunc(),delete e.afterFrameFunc,delete e.afterFrameIndex)},1e3/this.attrs.frameRate),this.anim.start()},stop:function(){this.anim.stop(),clearInterval(this.interval)},afterFrame:function(e,t){this.afterFrameIndex=e,this.afterFrameFunc=t},_updateIndex:function(){var e=this.attrs.index,t=this.attrs.animation;ea?u:a,d=u>a?1:u/a,v=u>a?a/u:1;e.translate(s,o),e.rotate(c),e.scale(d,v),e.arc(0,0,p,f,f+l,1-h),e.scale(1/d,1/v),e.rotate(-c),e.translate(-s,-o);break;case"z":e.closePath()}}this.fill(e),this.stroke(e)}},Kinetic.Global.extend(Kinetic.Path,Kinetic.Shape),Kinetic.Path.getLineLength=function(e,t,n,r){return Math.sqrt((n-e)*(n-e)+(r-t)*(r-t))},Kinetic.Path.getPointOnLine=function(e,t,n,r,i,s,o){s===undefined&&(s=t),o===undefined&&(o=n);var u=(i-n)/(r-t+1e-8),a=Math.sqrt(e*e/(1+u*u)),f=u*a,l;if((o-n)/(s-t+1e-8)===u)l={x:s+a,y:o+f};else{var c,h,p=this.getLineLength(t,n,r,i);if(p<1e-8)return undefined;var d=(s-t)*(r-t)+(o-n)*(i-n);d/=p*p,c=t+d*(r-t),h=n+d*(i-n);var v=this.getLineLength(s,o,c,h),m=Math.sqrt(e*e-v*v);a=Math.sqrt(m*m/(1+u*u)),f=u*a,l={x:c+a,y:h+f}}return l},Kinetic.Path.getPointOnCubicBezier=function(e,t,n,r,i,s,o,u,a){function f(e){return e*e*e}function l(e){return 3*e*e*(1-e)}function c(e){return 3*e*(1-e)*(1-e)}function h(e){return(1-e)*(1-e)*(1-e)}var p=u*f(e)+s*l(e)+r*c(e)+t*h(e),d=a*f(e)+o*l(e)+i*c(e)+n*h(e);return{x:p,y:d}},Kinetic.Path.getPointOnQuadraticBezier=function(e,t,n,r,i,s,o){function u(e){return e*e}function a(e){return 2*e*(1-e)}function f(e){return(1-e)*(1-e)}var l=s*u(e)+r*a(e)+t*f(e),c=o*u(e)+i*a(e)+n*f(e);return{x:l,y:c}},Kinetic.Path.getPointOnEllipticalArc=function(e,t,n,r,i,s){var o=Math.cos(s),u=Math.sin(s),a={x:n*Math.cos(i),y:r*Math.sin(i)};return{x:e+(a.x*o-a.y*u),y:t+(a.x*u+a.y*o)}},Kinetic.Path.parsePathData=function(e){if(!e)return[];var t=e,n=["m","M","l","L","v","V","h","H","z","Z","c","C","q","Q","t","T","s","S","a","A"];t=t.replace(new RegExp(" ","g"),",");for(var r=0;r0&&l[0]===""&&l.shift();for(var c=0;c0){if(isNaN(l[0]))break;var h=null,p=[],d=o,v=u;switch(f){case"l":o+=l.shift(),u+=l.shift(),h="L",p.push(o,u);break;case"L":o=l.shift(),u=l.shift(),p.push(o,u);break;case"m":o+=l.shift(),u+=l.shift(),h="M",p.push(o,u),f="l";break;case"M":o=l.shift(),u=l.shift(),h="M",p.push(o,u),f="L";break;case"h":o+=l.shift(),h="L",p.push(o,u);break;case"H":o=l.shift(),h="L",p.push(o,u);break;case"v":u+=l.shift(),h="L",p.push(o,u);break;case"V":u=l.shift(),h="L",p.push(o,u);break;case"C":p.push(l.shift(),l.shift(),l.shift(),l.shift()),o=l.shift(),u=l.shift(),p.push(o,u);break;case"c":p.push(o+l.shift(),u+l.shift(),o+l.shift(),u+l.shift()),o+=l.shift(),u+=l.shift(),h="C",p.push(o,u);break;case"S":var m=o,g=u,y=s[s.length-1];y.command==="C"&&(m=o+(o-y.points[2]),g=u+(u-y.points[3])),p.push(m,g,l.shift(),l.shift()),o=l.shift(),u=l.shift(),h="C",p.push(o,u);break;case"s":var m=o,g=u,y=s[s.length-1];y.command==="C"&&(m=o+(o-y.points[2]),g=u+(u-y.points[3])),p.push(m,g,o+l.shift(),u+l.shift()),o+=l.shift(),u+=l.shift(),h="C",p.push(o,u);break;case"Q":p.push(l.shift(),l.shift()),o=l.shift(),u=l.shift(),p.push(o,u);break;case"q":p.push(o+l.shift(),u+l.shift()),o+=l.shift(),u+=l.shift(),h="Q",p.push(o,u);break;case"T":var m=o,g=u,y=s[s.length-1];y.command==="Q"&&(m=o+(o-y.points[0]),g=u+(u-y.points[1])),o=l.shift(),u=l.shift(),h="Q",p.push(m,g,o,u);break;case"t":var m=o,g=u,y=s[s.length-1];y.command==="Q"&&(m=o+(o-y.points[0]),g=u+(u-y.points[1])),o+=l.shift(),u+=l.shift(),h="Q",p.push(m,g,o,u);break;case"A":var b=l.shift(),w=l.shift(),E=l.shift(),S=l.shift(),x=l.shift(),T=o,N=u;o=l.shift(),u=l.shift(),h="A",p=this.convertEndpointToCenterParameterization(T,N,o,u,S,x,b,w,E);break;case"a":var b=l.shift(),w=l.shift(),E=l.shift(),S=l.shift(),x=l.shift(),T=o,N=u;o+=l.shift(),u+=l.shift(),h="A",p=this.convertEndpointToCenterParameterization(T,N,o,u,S,x,b,w,E)}s.push({command:h||f,points:p,start:{x:d,y:v},pathLength:this.calcLength(d,v,h||f,p)})}(f==="z"||f==="Z")&&s.push({command:"z",points:[],start:undefined,pathLength:0})}return s},Kinetic.Path.calcLength=function(e,n,r,i){var s,o,u,a=Kinetic.Path;switch(r){case"L":return a.getLineLength(e,n,i[0],i[1]);case"C":s=0,o=a.getPointOnCubicBezier(0,e,n,i[0],i[1],i[2],i[3],i[4],i[5]);for(t=.01;t<=1;t+=.01)u=a.getPointOnCubicBezier(t,e,n,i[0],i[1],i[2],i[3],i[4],i[5]),s+=a.getLineLength(o.x,o.y,u.x,u.y),o=u;return s;case"Q":s=0,o=a.getPointOnQuadraticBezier(0,e,n,i[0],i[1],i[2],i[3]);for(t=.01;t<=1;t+=.01)u=a.getPointOnQuadraticBezier(t,e,n,i[0],i[1],i[2],i[3]),s+=a.getLineLength(o.x,o.y,u.x,u.y),o=u;return s;case"A":s=0;var f=i[4],l=i[5],c=i[4]+l,h=Math.PI/180;Math.abs(f-c)c;t-=h)u=a.getPointOnEllipticalArc(i[0],i[1],i[2],i[3],t,0),s+=a.getLineLength(o.x,o.y,u.x,u.y),o=u;else for(t=f+h;t1&&(o*=Math.sqrt(h),u*=Math.sqrt(h));var p=Math.sqrt((o*o*u*u-o*o*c*c-u*u*l*l)/(o*o*c*c+u*u*l*l));i==s&&(p*=-1),isNaN(p)&&(p=0);var d=p*o*c/u,v=p*-u*l/o,m=(e+n)/2+Math.cos(f)*d-Math.sin(f)*v,g=(t+r)/2+Math.sin(f)*d+Math.cos(f)*v,y=function(e){return Math.sqrt(e[0]*e[0]+e[1]*e[1])},b=function(e,t){return(e[0]*t[0]+e[1]*t[1])/(y(e)*y(t))},w=function(e,t){return(e[0]*t[1]=1&&(T=0),s===0&&T>0&&(T-=2*Math.PI),s==1&&T<0&&(T+=2*Math.PI),[m,g,o,u,E,T,f,s]},Kinetic.Node.addGettersSetters(Kinetic.Path,["data"]),Kinetic.TextPath=function(e){this._initTextPath(e)},Kinetic.TextPath.prototype={_initTextPath:function(e){this.setDefaultAttrs({fontFamily:"Calibri",fontSize:12,fontStyle:"normal",detectionType:"path",text:""}),this.dummyCanvas=document.createElement("canvas"),this.shapeType="TextPath",this.dataArray=[];var t=this;e.drawFunc=this.drawFunc,Kinetic.Shape.call(this,e),this.dataArray=Kinetic.Path.parsePathData(this.attrs.data),this.on("dataChange",function(){t.dataArray=Kinetic.Path.parsePathData(this.attrs.data)});var n=["text","textStroke","textStrokeWidth"];for(var r=0;r0)return o=n,t[n];t[n].command=="M"&&(r={x:t[n].points[0],y:t[n].points[1]})}return{}},f=function(t,n){var o=e._getTextSize(t).width,f=0,l=0,c=!1;i=undefined;while(Math.abs(o-f)/o>.01&&l<25){l++;var h=f;while(s===undefined)s=a(),s&&h+s.pathLengtho?i=Kinetic.Path.getPointOnLine(o,r.x,r.y,s.points[0],s.points[1],r.x,r.y):s=undefined;break;case"A":var d=s.points[4],v=s.points[5],m=s.points[4]+v;u===0?u=d+1e-8:o>f?u+=Math.PI/180*v/Math.abs(v):u-=Math.PI/360*v/Math.abs(v),Math.abs(u)>Math.abs(m)&&(u=m,p=!0),i=Kinetic.Path.getPointOnEllipticalArc(s.points[0],s.points[1],s.points[2],s.points[3],u,s.points[6]);break;case"C":u===0?o>s.pathLength?u=1e-8:u=o/s.pathLength:o>f?u+=(o-f)/s.pathLength:u-=(f-o)/s.pathLength,u>1&&(u=1,p=!0),i=Kinetic.Path.getPointOnCubicBezier(u,s.start.x,s.start.y,s.points[0],s.points[1],s.points[2],s.points[3],s.points[4],s.points[5]);break;case"Q":u===0?u=o/s.pathLength:o>f?u+=(o-f)/s.pathLength:u-=(f-o)/s.pathLength,u>1&&(u=1,p=!0),i=Kinetic.Path.getPointOnQuadraticBezier(u,s.start.x,s.start.y,s.points[0],s.points[1],s.points[2],s.points[3])}i!==undefined&&(f=Kinetic.Path.getLineLength(r.x,r.y,i.x,i.y)),p&&(p=!1,s=undefined)}};for(var l=0;l