/files/kineticjs/4.3.3/kinetic.js
JavaScript | 1439 lines | 1021 code | 49 blank | 369 comment | 214 complexity | 9384dde401490066ec53371c0317fbea MD5 | raw file
- /**
- * KineticJS JavaScript Framework v4.3.3
- * http://www.kineticjs.com/
- * Copyright 2013, Eric Rowell
- * Licensed under the MIT or GPL Version 2 licenses.
- * Date: Feb 12 2013
- *
- * Copyright (C) 2011 - 2013 by Eric Rowell
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- /**
- * @namespace
- */
- var Kinetic = {}; (function() {
- Kinetic.version = '4.3.3';
- /**
- * @namespace
- */
- Kinetic.Filters = {};
- Kinetic.Plugins = {};
- Kinetic.Global = {
- stages: [],
- idCounter: 0,
- ids: {},
- names: {},
- //shapes hash. rgb keys and shape values
- shapes: {},
- warn: function(str) {
- /*
- * IE9 on Windows7 64bit will throw a JS error
- * if we don't use window.console in the conditional
- */
- if(window.console && console.warn) {
- console.warn('Kinetic warning: ' + str);
- }
- },
- extend: function(c1, c2) {
- for(var key in c2.prototype) {
- if(!( key in c1.prototype)) {
- c1.prototype[key] = c2.prototype[key];
- }
- }
- },
- _addId: function(node, id) {
- if(id !== undefined) {
- this.ids[id] = node;
- }
- },
- _removeId: function(id) {
- if(id !== undefined) {
- delete this.ids[id];
- }
- },
- _addName: function(node, name) {
- if(name !== undefined) {
- if(this.names[name] === undefined) {
- this.names[name] = [];
- }
- this.names[name].push(node);
- }
- },
- _removeName: function(name, _id) {
- if(name !== undefined) {
- var nodes = this.names[name];
- if(nodes !== undefined) {
- for(var n = 0; n < nodes.length; n++) {
- var no = nodes[n];
- if(no._id === _id) {
- nodes.splice(n, 1);
- }
- }
- if(nodes.length === 0) {
- delete this.names[name];
- }
- }
- }
- }
- };
- })();
-
- // Uses Node, AMD or browser globals to create a module.
-
- // If you want something that will work in other stricter CommonJS environments,
- // or if you need to create a circular dependency, see commonJsStrict.js
-
- // Defines a module "returnExports" that depends another module called "b".
- // Note that the name of the module is implied by the file name. It is best
- // if the file name and the exported global have matching names.
-
- // If the 'b' module also uses this type of boilerplate, then
- // in the browser, it will create a global .b that is used below.
-
- // If you do not want to support the browser global path, then you
- // can remove the `root` use and the passing `this` as the first arg to
- // the top function.
-
- // if the module has no dependencies, the above pattern can be simplified to
- ( function(root, factory) {
- if( typeof exports === 'object') {
- // Node. Does not work with strict CommonJS, but
- // only CommonJS-like enviroments that support module.exports,
- // like Node.
- module.exports = factory();
- }
- else if( typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define(factory);
- }
- else {
- // Browser globals (root is window)
- root.returnExports = factory();
- }
- }(this, function() {
-
- // Just return a value to define the module export.
- // This example returns an object, but the module
- // can return a function as the exported value.
- return Kinetic;
- }));
-
- (function() {
- /*
- * utilities that handle data type detection, conversion, and manipulation
- */
- Kinetic.Type = {
- /*
- * cherry-picked utilities from underscore.js
- */
- _isElement: function(obj) {
- return !!(obj && obj.nodeType == 1);
- },
- _isFunction: function(obj) {
- return !!(obj && obj.constructor && obj.call && obj.apply);
- },
- _isObject: function(obj) {
- return (!!obj && obj.constructor == Object);
- },
- _isArray: function(obj) {
- return Object.prototype.toString.call(obj) == '[object Array]';
- },
- _isNumber: function(obj) {
- return Object.prototype.toString.call(obj) == '[object Number]';
- },
- _isString: function(obj) {
- return Object.prototype.toString.call(obj) == '[object String]';
- },
- /*
- * other utils
- */
- _hasMethods: function(obj) {
- var names = [];
- for(var key in obj) {
- if(this._isFunction(obj[key]))
- names.push(key);
- }
- return names.length > 0;
- },
- _isInDocument: function(el) {
- while( el = el.parentNode) {
- if(el == document) {
- return true;
- }
- }
- return false;
- },
- /*
- * The argument can be:
- * - an integer (will be applied to both x and y)
- * - an array of one integer (will be applied to both x and y)
- * - an array of two integers (contains x and y)
- * - an array of four integers (contains x, y, width, and height)
- * - an object with x and y properties
- * - an array of one element which is an array of integers
- * - an array of one element of an object
- */
- _getXY: function(arg) {
- if(this._isNumber(arg)) {
- return {
- x: arg,
- y: arg
- };
- }
- else if(this._isArray(arg)) {
- // if arg is an array of one element
- if(arg.length === 1) {
- var val = arg[0];
- // if arg is an array of one element which is a number
- if(this._isNumber(val)) {
- return {
- x: val,
- y: val
- };
- }
- // if arg is an array of one element which is an array
- else if(this._isArray(val)) {
- return {
- x: val[0],
- y: val[1]
- };
- }
- // if arg is an array of one element which is an object
- else if(this._isObject(val)) {
- return val;
- }
- }
- // if arg is an array of two or more elements
- else if(arg.length >= 2) {
- return {
- x: arg[0],
- y: arg[1]
- };
- }
- }
- // if arg is an object return the object
- else if(this._isObject(arg)) {
- return arg;
- }
-
- // default
- return null;
- },
- /*
- * The argument can be:
- * - an integer (will be applied to both width and height)
- * - an array of one integer (will be applied to both width and height)
- * - an array of two integers (contains width and height)
- * - an array of four integers (contains x, y, width, and height)
- * - an object with width and height properties
- * - an array of one element which is an array of integers
- * - an array of one element of an object
- */
- _getSize: function(arg) {
- if(this._isNumber(arg)) {
- return {
- width: arg,
- height: arg
- };
- }
- else if(this._isArray(arg)) {
- // if arg is an array of one element
- if(arg.length === 1) {
- var val = arg[0];
- // if arg is an array of one element which is a number
- if(this._isNumber(val)) {
- return {
- width: val,
- height: val
- };
- }
- // if arg is an array of one element which is an array
- else if(this._isArray(val)) {
- /*
- * if arg is an array of one element which is an
- * array of four elements
- */
- if(val.length >= 4) {
- return {
- width: val[2],
- height: val[3]
- };
- }
- /*
- * if arg is an array of one element which is an
- * array of two elements
- */
- else if(val.length >= 2) {
- return {
- width: val[0],
- height: val[1]
- };
- }
- }
- // if arg is an array of one element which is an object
- else if(this._isObject(val)) {
- return val;
- }
- }
- // if arg is an array of four elements
- else if(arg.length >= 4) {
- return {
- width: arg[2],
- height: arg[3]
- };
- }
- // if arg is an array of two elements
- else if(arg.length >= 2) {
- return {
- width: arg[0],
- height: arg[1]
- };
- }
- }
- // if arg is an object return the object
- else if(this._isObject(arg)) {
- return arg;
- }
-
- // default
- return null;
- },
- /*
- * arg will be an array of numbers or
- * an array of point arrays or
- * an array of point objects
- */
- _getPoints: function(arg) {
- if(arg === undefined) {
- return [];
- }
-
- // an array of arrays
- if(this._isArray(arg[0])) {
- /*
- * convert array of arrays into an array
- * of objects containing x, y
- */
- var arr = [];
- for(var n = 0; n < arg.length; n++) {
- arr.push({
- x: arg[n][0],
- y: arg[n][1]
- });
- }
-
- return arr;
- }
- // an array of objects
- if(this._isObject(arg[0])) {
- return arg;
- }
- // an array of integers
- else {
- /*
- * convert array of numbers into an array
- * of objects containing x, y
- */
- var arr = [];
- for(var n = 0; n < arg.length; n += 2) {
- arr.push({
- x: arg[n],
- y: arg[n + 1]
- });
- }
-
- return arr;
- }
- },
- /*
- * arg can be an image object or image data
- */
- _getImage: function(arg, callback) {
- // if arg is null or undefined
- if(!arg) {
- callback(null);
- }
-
- // if arg is already an image object
- else if(this._isElement(arg)) {
- callback(arg);
- }
-
- // if arg is a string, then it's a data url
- else if(this._isString(arg)) {
- var imageObj = new Image();
- /** @ignore */
- imageObj.onload = function() {
- callback(imageObj);
- }
- imageObj.src = arg;
- }
-
- //if arg is an object that contains the data property, it's an image object
- else if(arg.data) {
- var canvas = document.createElement('canvas');
- canvas.width = arg.width;
- canvas.height = arg.height;
- var context = canvas.getContext('2d');
- context.putImageData(arg, 0, 0);
- var dataUrl = canvas.toDataURL();
- var imageObj = new Image();
- /** @ignore */
- imageObj.onload = function() {
- callback(imageObj);
- }
- imageObj.src = dataUrl;
- }
- else {
- callback(null);
- }
- },
- _rgbToHex: function(r, g, b) {
- return ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
- },
- _hexToRgb: function(hex) {
- var bigint = parseInt(hex, 16);
- return {
- r: (bigint >> 16) & 255,
- g: (bigint >> 8) & 255,
- b: bigint & 255
- };
- },
- _getRandomColorKey: function() {
- var r = Math.round(Math.random() * 255);
- 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;
- },
- _degToRad: function(deg) {
- return deg * Math.PI / 180;
- },
- _radToDeg: function(rad) {
- return rad * 180 / Math.PI;
- }
- };
- })();
-
- (function() {
- // calculate pixel ratio
- var canvas = document.createElement('canvas'),
- context = canvas.getContext('2d'),
- devicePixelRatio = window.devicePixelRatio || 1, backingStoreRatio = context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1,
- _pixelRatio = devicePixelRatio / backingStoreRatio;
-
- /**
- * Canvas Renderer constructor
- * @constructor
- * @param {Number} width
- * @param {Number} height
- */
- Kinetic.Canvas = function(width, height, pixelRatio) {
- this.pixelRatio = pixelRatio || _pixelRatio;
- this.width = width;
- this.height = height;
- this.element = document.createElement('canvas');
- this.context = this.element.getContext('2d');
- this.setSize(width || 0, height || 0);
- };
-
- Kinetic.Canvas.prototype = {
- /**
- * clear canvas
- * @name clear
- * @methodOf Kinetic.Canvas.prototype
- */
- clear: function() {
- var context = this.getContext();
- var el = this.getElement();
- context.clearRect(0, 0, el.width, el.height);
- },
- /**
- * get canvas element
- * @name getElement
- * @methodOf Kinetic.Canvas.prototype
- */
- getElement: function() {
- return this.element;
- },
- /**
- * get canvas context
- * @name getContext
- * @methodOf Kinetic.Canvas.prototype
- */
- getContext: function() {
- return this.context;
- },
- /**
- * set width
- * @name setWidth
- * @methodOf Kinetic.Canvas.prototype
- * @param {Number} width
- */
- setWidth: function(width) {
- this.width = width;
- // take into account pixel ratio
- this.element.width = width * this.pixelRatio;
- this.element.style.width = width + 'px';
- },
- /**
- * set height
- * @name setHeight
- * @methodOf Kinetic.Canvas.prototype
- * @param {Number} height
- */
- setHeight: function(height) {
- this.height = height;
- // take into account pixel ratio
- this.element.height = height * this.pixelRatio;
- this.element.style.height = height + 'px';
- },
- /**
- * get width
- * @name getWidth
- * @methodOf Kinetic.Canvas.prototype
- */
- getWidth: function() {
- return this.width;
- },
- /**
- * get height
- * @name getHeight
- * @methodOf Kinetic.Canvas.prototype
- */
- getHeight: function() {
- return this.height;
- },
- /**
- * set size
- * @name setSize
- * @methodOf Kinetic.Canvas.prototype
- * @param {Number} width
- * @param {Number} height
- */
- setSize: function(width, height) {
- this.setWidth(width);
- this.setHeight(height);
- },
- /**
- * to data url
- * @name toDataURL
- * @methodOf Kinetic.Canvas.prototype
- * @param {String} mimeType
- * @param {Number} quality between 0 and 1 for jpg mime types
- */
- toDataURL: function(mimeType, quality) {
- try {
- // If this call fails (due to browser bug, like in Firefox 3.6),
- // then revert to previous no-parameter image/png behavior
- return this.element.toDataURL(mimeType, quality);
- }
- catch(e) {
- try {
- return this.element.toDataURL();
- }
- catch(e) {
- Kinetic.Global.warn('Unable to get data URL. ' + e.message)
- return '';
- }
- }
- },
- /**
- * fill shape
- * @name fill
- * @methodOf Kinetic.Canvas.prototype
- * @param {Kinetic.Shape} shape
- */
- fill: function(shape) {
- if(shape.getFillEnabled()) {
- this._fill(shape);
- }
- },
- /**
- * stroke shape
- * @name stroke
- * @methodOf Kinetic.Canvas.prototype
- * @param {Kinetic.Shape} shape
- */
- stroke: function(shape) {
- if(shape.getStrokeEnabled()) {
- this._stroke(shape);
- }
- },
- /**
- * fill, stroke, and apply shadows
- * will only be applied to either the fill or stroke. Fill
- * is given priority over stroke.
- * @name fillStroke
- * @methodOf Kinetic.Canvas.prototype
- * @param {Kinetic.Shape} shape
- */
- fillStroke: function(shape) {
- var fillEnabled = shape.getFillEnabled();
- if(fillEnabled) {
- this._fill(shape);
- }
-
- if(shape.getStrokeEnabled()) {
- this._stroke(shape, shape.hasShadow() && shape.hasFill() && fillEnabled);
- }
- },
- /**
- * apply shadow
- * @name applyShadow
- * @methodOf Kinetic.Canvas.prototype
- * @param {Kinetic.Shape} shape
- * @param {Function} drawFunc
- */
- applyShadow: function(shape, drawFunc) {
- var context = this.context;
- context.save();
- this._applyShadow(shape);
- drawFunc();
- context.restore();
- drawFunc();
- },
- _applyLineCap: function(shape) {
- var lineCap = shape.getLineCap();
- if(lineCap) {
- this.context.lineCap = lineCap;
- }
- },
- _applyOpacity: function(shape) {
- var absOpacity = shape.getAbsoluteOpacity();
- if(absOpacity !== 1) {
- this.context.globalAlpha = absOpacity;
- }
- },
- _applyLineJoin: function(shape) {
- var lineJoin = shape.getLineJoin();
- if(lineJoin) {
- this.context.lineJoin = lineJoin;
- }
- },
- _applyAncestorTransforms: function(node) {
- var context = this.context;
- node._eachAncestorReverse(function(no) {
- var t = no.getTransform(), m = t.getMatrix();
- context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
- }, true);
- }
- };
-
- Kinetic.SceneCanvas = function(width, height, pixelRatio) {
- Kinetic.Canvas.call(this, width, height, pixelRatio);
- };
-
- Kinetic.SceneCanvas.prototype = {
- setWidth: function(width) {
- var pixelRatio = this.pixelRatio;
- Kinetic.Canvas.prototype.setWidth.call(this, width);
- this.context.scale(pixelRatio, pixelRatio);
- },
- setHeight: function(height) {
- var pixelRatio = this.pixelRatio;
- Kinetic.Canvas.prototype.setHeight.call(this, height);
- this.context.scale(pixelRatio, pixelRatio);
- },
- _fillColor: function(shape) {
- var context = this.context, fill = shape.getFill();
- context.fillStyle = fill;
- shape._fillFunc(context);
- },
- _fillPattern: function(shape) {
- var context = this.context, fillPatternImage = shape.getFillPatternImage(), fillPatternX = shape.getFillPatternX(), fillPatternY = shape.getFillPatternY(), fillPatternScale = shape.getFillPatternScale(), fillPatternRotation = shape.getFillPatternRotation(), fillPatternOffset = shape.getFillPatternOffset(), fillPatternRepeat = shape.getFillPatternRepeat();
-
- if(fillPatternX || fillPatternY) {
- context.translate(fillPatternX || 0, fillPatternY || 0);
- }
- if(fillPatternRotation) {
- context.rotate(fillPatternRotation);
- }
- if(fillPatternScale) {
- context.scale(fillPatternScale.x, fillPatternScale.y);
- }
- if(fillPatternOffset) {
- context.translate(-1 * fillPatternOffset.x, -1 * fillPatternOffset.y);
- }
-
- context.fillStyle = context.createPattern(fillPatternImage, fillPatternRepeat || 'repeat');
- context.fill();
- },
- _fillLinearGradient: function(shape) {
- var context = this.context, start = shape.getFillLinearGradientStartPoint(), end = shape.getFillLinearGradientEndPoint(), colorStops = shape.getFillLinearGradientColorStops(), grd = context.createLinearGradient(start.x, start.y, end.x, end.y);
-
- // build color stops
- for(var n = 0; n < colorStops.length; n += 2) {
- grd.addColorStop(colorStops[n], colorStops[n + 1]);
- }
- context.fillStyle = grd;
- context.fill();
- },
- _fillRadialGradient: function(shape) {
- var context = this.context, start = shape.getFillRadialGradientStartPoint(), end = shape.getFillRadialGradientEndPoint(), startRadius = shape.getFillRadialGradientStartRadius(), endRadius = shape.getFillRadialGradientEndRadius(), colorStops = shape.getFillRadialGradientColorStops(), grd = context.createRadialGradient(start.x, start.y, startRadius, end.x, end.y, endRadius);
-
- // build color stops
- for(var n = 0; n < colorStops.length; n += 2) {
- grd.addColorStop(colorStops[n], colorStops[n + 1]);
- }
- context.fillStyle = grd;
- context.fill();
- },
- _fill: function(shape, skipShadow) {
- var context = this.context, fill = shape.getFill(), fillPatternImage = shape.getFillPatternImage(), fillLinearGradientStartPoint = shape.getFillLinearGradientStartPoint(), fillRadialGradientStartPoint = shape.getFillRadialGradientStartPoint(), fillPriority = shape.getFillPriority();
-
- context.save();
-
- if(!skipShadow && shape.hasShadow()) {
- this._applyShadow(shape);
- }
-
- // priority fills
- if(fill && fillPriority === 'color') {
- this._fillColor(shape);
- }
- else if(fillPatternImage && fillPriority === 'pattern') {
- this._fillPattern(shape);
- }
- else if(fillLinearGradientStartPoint && fillPriority === 'linear-gradient') {
- this._fillLinearGradient(shape);
- }
- else if(fillRadialGradientStartPoint && fillPriority === 'radial-gradient') {
- this._fillRadialGradient(shape);
- }
- // now just try and fill with whatever is available
- else if(fill) {
- this._fillColor(shape);
- }
- else if(fillPatternImage) {
- this._fillPattern(shape);
- }
- else if(fillLinearGradientStartPoint) {
- this._fillLinearGradient(shape);
- }
- else if(fillRadialGradientStartPoint) {
- this._fillRadialGradient(shape);
- }
- context.restore();
-
- if(!skipShadow && shape.hasShadow()) {
- this._fill(shape, true);
- }
- },
- _stroke: function(shape, skipShadow) {
- var context = this.context, stroke = shape.getStroke(), strokeWidth = shape.getStrokeWidth(), dashArray = shape.getDashArray();
- if(stroke || strokeWidth) {
- context.save();
- this._applyLineCap(shape);
- if(dashArray && shape.getDashArrayEnabled()) {
- if(context.setLineDash) {
- context.setLineDash(dashArray);
- }
- else if('mozDash' in context) {
- context.mozDash = dashArray;
- }
- else if('webkitLineDash' in context) {
- context.webkitLineDash = dashArray;
- }
- }
- if(!skipShadow && shape.hasShadow()) {
- this._applyShadow(shape);
- }
- context.lineWidth = strokeWidth || 2;
- context.strokeStyle = stroke || 'black';
- shape._strokeFunc(context);
- context.restore();
-
- if(!skipShadow && shape.hasShadow()) {
- this._stroke(shape, true);
- }
- }
- },
- _applyShadow: function(shape) {
- var context = this.context;
- if(shape.hasShadow() && shape.getShadowEnabled()) {
- var aa = shape.getAbsoluteOpacity();
- // defaults
- var color = shape.getShadowColor() || 'black';
- var blur = shape.getShadowBlur() || 5;
- var offset = shape.getShadowOffset() || {
- x: 0,
- y: 0
- };
-
- if(shape.getShadowOpacity()) {
- context.globalAlpha = shape.getShadowOpacity() * aa;
- }
- context.shadowColor = color;
- context.shadowBlur = blur;
- context.shadowOffsetX = offset.x;
- context.shadowOffsetY = offset.y;
- }
- }
- };
- Kinetic.Global.extend(Kinetic.SceneCanvas, Kinetic.Canvas);
-
- Kinetic.HitCanvas = function(width, height, pixelRatio) {
- Kinetic.Canvas.call(this, width, height, pixelRatio);
- };
-
- Kinetic.HitCanvas.prototype = {
- _fill: function(shape) {
- var context = this.context;
- context.save();
- context.fillStyle = '#' + shape.colorKey;
- shape._fillFuncHit(context);
- context.restore();
- },
- _stroke: function(shape) {
- var context = this.context, stroke = shape.getStroke(), strokeWidth = shape.getStrokeWidth();
- if(stroke || strokeWidth) {
- this._applyLineCap(shape);
- context.save();
- context.lineWidth = strokeWidth || 2;
- context.strokeStyle = '#' + shape.colorKey;
- shape._strokeFuncHit(context);
- context.restore();
- }
- }
- };
- Kinetic.Global.extend(Kinetic.HitCanvas, Kinetic.Canvas);
- })();
-
- (function() {
- /*
- * The Tween class was ported from an Adobe Flash Tween library
- * to JavaScript by Xaric. In the context of KineticJS, a Tween is
- * an animation of a single Node property. A Transition is a set of
- * multiple tweens
- */
- Kinetic.Tween = function(obj, propFunc, func, begin, finish, duration) {
- this._listeners = [];
- this.addListener(this);
- this.obj = obj;
- this.propFunc = propFunc;
- this.begin = begin;
- this._pos = begin;
- this.setDuration(duration);
- this.isPlaying = false;
- this._change = 0;
- this.prevTime = 0;
- this.prevPos = 0;
- this.looping = false;
- this._time = 0;
- this._position = 0;
- this._startTime = 0;
- this._finish = 0;
- this.name = '';
- this.func = func;
- this.setFinish(finish);
- };
- /*
- * Tween methods
- */
- Kinetic.Tween.prototype = {
- setTime: function(t) {
- this.prevTime = this._time;
- if(t > this.getDuration()) {
- if(this.looping) {
- this.rewind(t - this._duration);
- this.update();
- this.broadcastMessage('onLooped', {
- target: this,
- type: 'onLooped'
- });
- }
- else {
- this._time = this._duration;
- this.update();
- this.stop();
- this.broadcastMessage('onFinished', {
- target: this,
- type: 'onFinished'
- });
- }
- }
- else if(t < 0) {
- this.rewind();
- this.update();
- }
- else {
- this._time = t;
- this.update();
- }
- },
- getTime: function() {
- return this._time;
- },
- setDuration: function(d) {
- this._duration = (d === null || d <= 0) ? 100000 : d;
- },
- getDuration: function() {
- return this._duration;
- },
- setPosition: function(p) {
- this.prevPos = this._pos;
- this.propFunc(p);
- this._pos = p;
- this.broadcastMessage('onChanged', {
- target: this,
- type: 'onChanged'
- });
- },
- getPosition: function(t) {
- if(t === undefined) {
- t = this._time;
- }
- return this.func(t, this.begin, this._change, this._duration);
- },
- setFinish: function(f) {
- this._change = f - this.begin;
- },
- getFinish: function() {
- return this.begin + this._change;
- },
- start: function() {
- this.rewind();
- this.startEnterFrame();
- this.broadcastMessage('onStarted', {
- target: this,
- type: 'onStarted'
- });
- },
- rewind: function(t) {
- this.stop();
- this._time = (t === undefined) ? 0 : t;
- 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 = true;
- this.onEnterFrame();
- },
- onEnterFrame: function() {
- if(this.isPlaying) {
- this.nextFrame();
- }
- },
- nextFrame: function() {
- this.setTime((this.getTimer() - this._startTime) / 1000);
- },
- stop: function() {
- this.stopEnterFrame();
- this.broadcastMessage('onStopped', {
- target: this,
- type: 'onStopped'
- });
- },
- stopEnterFrame: function() {
- this.isPlaying = false;
- },
- continueTo: function(finish, duration) {
- this.begin = this._pos;
- this.setFinish(finish);
- if(this._duration !== undefined) {
- this.setDuration(duration);
- }
- 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(o) {
- this.removeListener(o);
- return this._listeners.push(o);
- },
- removeListener: function(o) {
- var a = this._listeners;
- var i = a.length;
- while(i--) {
- if(a[i] == o) {
- a.splice(i, 1);
- return true;
- }
- }
- return false;
- },
- broadcastMessage: function() {
- var arr = [];
- for(var i = 0; i < arguments.length; i++) {
- arr.push(arguments[i]);
- }
- var e = arr.shift();
- var a = this._listeners;
- var l = a.length;
- for(var i = 0; i < l; i++) {
- if(a[i][e]) {
- a[i][e].apply(a[i], arr);
- }
- }
- },
- fixTime: function() {
- this._startTime = this.getTimer() - this._time * 1000;
- },
- getTimer: function() {
- return new Date().getTime() - this._time;
- }
- };
-
- Kinetic.Tweens = {
- 'back-ease-in': function(t, b, c, d, a, p) {
- var s = 1.70158;
- return c * (t /= d) * t * ((s + 1) * t - s) + b;
- },
- 'back-ease-out': function(t, b, c, d, a, p) {
- var s = 1.70158;
- return c * (( t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
- },
- 'back-ease-in-out': function(t, b, c, d, a, p) {
- var s = 1.70158;
- if((t /= d / 2) < 1) {
- return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
- }
- return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
- },
- 'elastic-ease-in': function(t, b, c, d, a, p) {
- // added s = 0
- var s = 0;
- if(t === 0) {
- return b;
- }
- if((t /= d) == 1) {
- return b + c;
- }
- if(!p) {
- p = d * 0.3;
- }
- if(!a || a < Math.abs(c)) {
- a = c;
- s = p / 4;
- }
- else {
- s = p / (2 * Math.PI) * Math.asin(c / a);
- }
- return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
- },
- 'elastic-ease-out': function(t, b, c, d, a, p) {
- // added s = 0
- var s = 0;
- if(t === 0) {
- return b;
- }
- if((t /= d) == 1) {
- return b + c;
- }
- if(!p) {
- p = d * 0.3;
- }
- if(!a || a < Math.abs(c)) {
- a = c;
- s = p / 4;
- }
- else {
- s = p / (2 * Math.PI) * Math.asin(c / a);
- }
- return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
- },
- 'elastic-ease-in-out': function(t, b, c, d, a, p) {
- // added s = 0
- var s = 0;
- if(t === 0) {
- return b;
- }
- if((t /= d / 2) == 2) {
- return b + c;
- }
- if(!p) {
- p = d * (0.3 * 1.5);
- }
- if(!a || a < Math.abs(c)) {
- a = c;
- s = p / 4;
- }
- else {
- s = p / (2 * Math.PI) * Math.asin(c / a);
- }
- if(t < 1) {
- return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
- }
- return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b;
- },
- 'bounce-ease-out': function(t, b, c, d) {
- if((t /= d) < (1 / 2.75)) {
- return c * (7.5625 * t * t) + b;
- }
- else if(t < (2 / 2.75)) {
- return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;
- }
- else if(t < (2.5 / 2.75)) {
- return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;
- }
- else {
- return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;
- }
- },
- 'bounce-ease-in': function(t, b, c, d) {
- return c - Kinetic.Tweens['bounce-ease-out'](d - t, 0, c, d) + b;
- },
- 'bounce-ease-in-out': function(t, b, c, d) {
- if(t < d / 2) {
- return Kinetic.Tweens['bounce-ease-in'](t * 2, 0, c, d) * 0.5 + b;
- }
- else {
- return Kinetic.Tweens['bounce-ease-out'](t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
- }
- },
- // duplicate
- /*
- strongEaseInOut: function(t, b, c, d) {
- return c * (t /= d) * t * t * t * t + b;
- },
- */
- 'ease-in': function(t, b, c, d) {
- return c * (t /= d) * t + b;
- },
- 'ease-out': function(t, b, c, d) {
- return -c * (t /= d) * (t - 2) + b;
- },
- 'ease-in-out': function(t, b, c, d) {
- if((t /= d / 2) < 1) {
- return c / 2 * t * t + b;
- }
- return -c / 2 * ((--t) * (t - 2) - 1) + b;
- },
- 'strong-ease-in': function(t, b, c, d) {
- return c * (t /= d) * t * t * t * t + b;
- },
- 'strong-ease-out': function(t, b, c, d) {
- return c * (( t = t / d - 1) * t * t * t * t + 1) + b;
- },
- 'strong-ease-in-out': function(t, b, c, d) {
- if((t /= d / 2) < 1) {
- return c / 2 * t * t * t * t * t + b;
- }
- return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
- },
- 'linear': function(t, b, c, d) {
- return c * t / d + b;
- }
- };
- })();
-
- (function() {
- /*
- * Last updated November 2011
- * By Simon Sarris
- * www.simonsarris.com
- * sarris@acm.org
- *
- * Free to use and distribute at will
- * So long as you are nice to people, etc
- */
-
- /*
- * The usage of this class was inspired by some of the work done by a forked
- * project, KineticJS-Ext by Wappworks, which is based on Simon's Transform
- * class.
- */
-
- /**
- * Transform constructor
- * @constructor
- */
- Kinetic.Transform = function() {
- this.m = [1, 0, 0, 1, 0, 0];
- }
-
- Kinetic.Transform.prototype = {
- /**
- * Apply translation
- * @param {Number} x
- * @param {Number} y
- */
- translate: function(x, y) {
- this.m[4] += this.m[0] * x + this.m[2] * y;
- this.m[5] += this.m[1] * x + this.m[3] * y;
- },
- /**
- * Apply scale
- * @param {Number} sx
- * @param {Number} sy
- */
- scale: function(sx, sy) {
- this.m[0] *= sx;
- this.m[1] *= sx;
- this.m[2] *= sy;
- this.m[3] *= sy;
- },
- /**
- * Apply rotation
- * @param {Number} rad Angle in radians
- */
- rotate: function(rad) {
- var c = Math.cos(rad);
- var s = Math.sin(rad);
- var m11 = this.m[0] * c + this.m[2] * s;
- var m12 = this.m[1] * c + this.m[3] * s;
- var m21 = this.m[0] * -s + this.m[2] * c;
- var m22 = this.m[1] * -s + this.m[3] * c;
- this.m[0] = m11;
- this.m[1] = m12;
- this.m[2] = m21;
- this.m[3] = m22;
- },
- /**
- * Returns the translation
- * @returns {Object} 2D point(x, y)
- */
- getTranslation: function() {
- return {
- x: this.m[4],
- y: this.m[5]
- };
- },
- /**
- * Transform multiplication
- * @param {Kinetic.Transform} matrix
- */
- multiply: function(matrix) {
- var m11 = this.m[0] * matrix.m[0] + this.m[2] * matrix.m[1];
- var m12 = this.m[1] * matrix.m[0] + this.m[3] * matrix.m[1];
-
- var m21 = this.m[0] * matrix.m[2] + this.m[2] * matrix.m[3];
- var m22 = this.m[1] * matrix.m[2] + this.m[3] * matrix.m[3];
-
- var dx = this.m[0] * matrix.m[4] + this.m[2] * matrix.m[5] + this.m[4];
- var dy = this.m[1] * matrix.m[4] + this.m[3] * matrix.m[5] + this.m[5];
-
- this.m[0] = m11;
- this.m[1] = m12;
- this.m[2] = m21;
- this.m[3] = m22;
- this.m[4] = dx;
- this.m[5] = dy;
- },
- /**
- * Invert the matrix
- */
- invert: function() {
- var d = 1 / (this.m[0] * this.m[3] - this.m[1] * this.m[2]);
- var m0 = this.m[3] * d;
- var m1 = -this.m[1] * d;
- var m2 = -this.m[2] * d;
- var m3 = this.m[0] * d;
- var m4 = d * (this.m[2] * this.m[5] - this.m[3] * this.m[4]);
- var m5 = d * (this.m[1] * this.m[4] - this.m[0] * this.m[5]);
- this.m[0] = m0;
- this.m[1] = m1;
- this.m[2] = m2;
- this.m[3] = m3;
- this.m[4] = m4;
- this.m[5] = m5;
- },
- /**
- * return matrix
- */
- getMatrix: function() {
- return this.m;
- }
- };
- })();
-
- (function() {
- /**
- * Collection constructor. Collection extends
- * Array. This class is used in conjunction with get()
- * @constructor
- */
- Kinetic.Collection = function() {
- var args = [].slice.call(arguments), length = args.length, i = 0;
-
- this.length = length;
- for(; i < length; i++) {
- this[i] = args[i];
- }
- return this;
- }
- Kinetic.Collection.prototype = new Array();
- /**
- * apply a method to all nodes in the array
- * @name apply
- * @methodOf Kinetic.Collection.prototype
- * @param {String} method
- * @param val
- */
- Kinetic.Collection.prototype.apply = function(method) {
- args = [].slice.call(arguments);
- args.shift();
- for(var n = 0; n < this.length; n++) {
- if(Kinetic.Type._isFunction(this[n][method])) {
- this[n][method].apply(this[n], args);
- }
- }
- };
- /**
- * iterate through node array
- * @name each
- * @methodOf Kinetic.Collection.prototype
- * @param {Function} func
- */
- Kinetic.Collection.prototype.each = function(func) {
- for(var n = 0; n < this.length; n++) {
- func.call(this[n], n, this[n]);
- }
- };
- })();
-
- (function() {
- /**
- * Grayscale Filter
- * @function
- * @memberOf Kinetic.Filters
- * @param {Object} imageData
- * @param {Object} config
- */
- Kinetic.Filters.Grayscale = function(imageData, config) {
- var data = imageData.data;
- for(var i = 0; i < data.length; i += 4) {
- var brightness = 0.34 * data[i] + 0.5 * data[i + 1] + 0.16 * data[i + 2];
- // red
- data[i] = brightness;
- // green
- data[i + 1] = brightness;
- // blue
- data[i + 2] = brightness;
- }
- };
- })();
-
- (function() {
- /**
- * Brighten Filter
- * @function
- * @memberOf Kinetic.Filters
- * @param {Object} imageData
- * @param {Object} config
- * @param {Integer} config.val brightness number from -255 to 255. Positive values increase the brightness and negative values decrease the brightness, making the image darker
- */
- Kinetic.Filters.Brighten = function(imageData, config) {
- var brightness = config.val || 0;
- var data = imageData.data;
- for(var i = 0; i < data.length; i += 4) {
- // red
- data[i] += brightness;
- // green
- data[i + 1] += brightness;
- // blue
- data[i + 2] += brightness;
- }
- };
- })();
-
- (function() {
- /**
- * Invert Filter
- * @function
- * @memberOf Kinetic.Filters
- * @param {Object} imageData
- * @param {Object} config
- */
- Kinetic.Filters.Invert = function(imageData, config) {
- var data = imageData.data;
- for(var i = 0; i < data.length; i += 4) {
- // red
- data[i] = 255 - data[i];
- // green
- data[i + 1] = 255 - data[i + 1];
- // blue
- data[i + 2] = 255 - data[i + 2];
- }
- };
- })();
-
- (function() {
- /**
- * Node constructor. Nodes are entities that can be transformed, layered,
- * and have bound events. The stage, layers, groups, and shapes all extend Node.
- * @constructor
- * @param {Object} config
- * @param {Number} [config.x]
- * @param {Number} [config.y]
- * @param {Number} [config.width]
- * @param {Number} [config.height]
- * @param {Boolean} [config.visible]
- * @param {Boolean} [config.listening] whether or not the node is listening for events
- * @param {String} [config.id] unique id
- * @param {String} [config.name] non-unique name
- * @param {Number} [config.opacity] determines node opacity. Can be any number between 0 and 1
- * @param {Object} [config.scale]
- * @param {Number} [config.scale.x]
- * @param {Number} [config.scale.y]
- * @param {Number} [config.rotation] rotation in radians
- * @param {Number} [config.rotationDeg] rotation in degrees
- * @param {Object} [config.offset] offset from center point and rotation point
- * @param {Number} [config.offset.x]
- * @param {Number} [config.offset.y]
- * @param {Boolean} [config.draggable]
- * @param {Function} [config.dragBoundFunc]
- */
- Kinetic.Node = function(config) {
- this._nodeInit(conf