konva/src/Global.js

415 lines
14 KiB
JavaScript
Raw Normal View History

2014-02-27 08:49:18 +08:00
/*
2015-01-27 15:07:51 +08:00
* KonvaJS JavaScript Framework v@@version
* http://lavrton.github.io/KonvaJS/
* Licensed under the MIT or GPL Version 2 licenses.
* Date: @@date
*
2015-01-09 22:52:27 +08:00
* Original work Copyright (C) 2011 - 2013 by Eric Rowell
2015-01-22 14:42:16 +08:00
* Modified work Copyright (C) 2014 - 2015 by Anton Lavrenov
*
* 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.
*/
/**
2015-01-27 15:07:51 +08:00
* @namespace Konva
2013-03-26 16:09:21 +08:00
*/
2014-02-27 08:49:18 +08:00
/*jshint -W079, -W020*/
2015-01-27 15:07:51 +08:00
var Konva = {};
2014-02-27 19:55:39 +08:00
(function(root) {
var PI_OVER_180 = Math.PI / 180;
2015-01-27 15:07:51 +08:00
Konva = {
// public
version: '@@version',
// private
stages: [],
idCounter: 0,
ids: {},
names: {},
shapes: {},
listenClickTap: false,
inDblClickWindow: false,
// configurations
enableTrace: false,
traceArrMax: 100,
dblClickWindow: 400,
2014-04-14 09:49:10 +08:00
/**
2015-01-27 15:07:51 +08:00
* Global pixel ratio configuration. KonvaJS automatically detect pixel ratio of current device.
2014-04-14 09:49:10 +08:00
* But you may override such property, if you want to use your value.
2014-10-03 13:03:50 +08:00
* @property pixelRatio
2014-04-14 09:49:10 +08:00
* @default undefined
2015-01-27 15:07:51 +08:00
* @memberof Konva
2014-04-14 09:49:10 +08:00
* @example
2015-01-27 15:07:51 +08:00
* Konva.pixelRatio = 1;
2014-04-14 09:49:10 +08:00
*/
pixelRatio: undefined,
2014-04-14 09:49:10 +08:00
/**
* Drag distance property. If you start to drag a node you may want to wait until pointer is moved to some distance from start point,
* only then start dragging.
2014-10-03 13:03:50 +08:00
* @property dragDistance
2014-04-14 09:49:10 +08:00
* @default 0
2015-01-27 15:07:51 +08:00
* @memberof Konva
2014-04-14 09:49:10 +08:00
* @example
2015-01-27 15:07:51 +08:00
* Konva.dragDistance = 10;
2014-04-14 09:49:10 +08:00
*/
2014-03-11 23:14:03 +08:00
dragDistance : 0,
2014-04-14 09:49:10 +08:00
/**
* Use degree values for angle properties. You may set this property to false if you want to use radiant values.
2014-10-03 13:03:50 +08:00
* @property angleDeg
2014-04-14 09:49:10 +08:00
* @default true
2015-01-27 15:07:51 +08:00
* @memberof Konva
2014-04-14 09:49:10 +08:00
* @example
* node.rotation(45); // 45 degrees
2015-01-27 15:07:51 +08:00
* Konva.angleDeg = false;
2014-04-14 09:49:10 +08:00
* node.rotation(Math.PI / 2); // PI/2 radian
*/
angleDeg: true,
2014-05-20 17:57:39 +08:00
/**
* Show different warnings about errors or wrong API usage
2014-10-03 13:03:50 +08:00
* @property showWarnings
2014-05-20 17:57:39 +08:00
* @default true
2015-01-27 15:07:51 +08:00
* @memberof Konva
2014-05-20 17:57:39 +08:00
* @example
2015-01-27 15:07:51 +08:00
* Konva.showWarnings = false;
2014-05-20 17:57:39 +08:00
*/
showWarnings : true,
/**
* @namespace Filters
2015-01-27 15:07:51 +08:00
* @memberof Konva
*/
Filters: {},
/**
* Node constructor. Nodes are entities that can be transformed, layered,
* and have bound events. The stage, layers, groups, and shapes all extend Node.
* @constructor
2015-01-27 15:07:51 +08:00
* @memberof Konva
* @abstract
* @param {Object} config
* @@nodeParams
*/
Node: function(config) {
this._init(config);
},
/**
* Shape constructor. Shapes are primitive objects such as rectangles,
* circles, text, lines, etc.
* @constructor
2015-01-27 15:07:51 +08:00
* @memberof Konva
* @augments Konva.Node
* @param {Object} config
* @@shapeParams
* @@nodeParams
* @example
2015-01-27 15:07:51 +08:00
* var customShape = new Konva.Shape({
2014-04-04 11:17:09 +08:00
* x: 5,
* y: 10,
* fill: 'red',
2015-01-27 15:07:51 +08:00
* // a Konva.Canvas renderer is passed into the drawFunc function
2014-04-04 11:17:09 +08:00
* drawFunc: function(context) {
* context.beginPath();
* context.moveTo(200, 50);
* context.lineTo(420, 80);
* context.quadraticCurveTo(300, 100, 260, 170);
* context.closePath();
* context.fillStrokeShape(this);
* }
*});
*/
Shape: function(config) {
this.__init(config);
},
/**
* Container constructor.  Containers are used to contain nodes or other containers
* @constructor
2015-01-27 15:07:51 +08:00
* @memberof Konva
* @augments Konva.Node
* @abstract
* @param {Object} config
* @@nodeParams
* @@containerParams
*/
Container: function(config) {
this.__init(config);
},
/**
* Stage constructor. A stage is used to contain multiple layers
* @constructor
2015-01-27 15:07:51 +08:00
* @memberof Konva
* @augments Konva.Container
* @param {Object} config
* @param {String|Element} config.container Container id or DOM element
* @@nodeParams
* @example
2015-01-27 15:07:51 +08:00
* var stage = new Konva.Stage({
2014-04-04 11:17:09 +08:00
* width: 500,
* height: 800,
* container: 'containerId'
* });
*/
Stage: function(config) {
this.___init(config);
},
/**
* BaseLayer constructor.
* @constructor
2015-01-27 15:07:51 +08:00
* @memberof Konva
* @augments Konva.Container
* @param {Object} config
* @param {Boolean} [config.clearBeforeDraw] set this property to false if you don't want
* to clear the canvas before each layer draw. The default value is true.
* @@nodeParams
* @@containerParams
* @example
2015-01-27 15:07:51 +08:00
* var layer = new Konva.Layer();
*/
BaseLayer: function(config) {
this.___init(config);
},
/**
* Layer constructor. Layers are tied to their own canvas element and are used
* to contain groups or shapes.
* @constructor
2015-01-27 15:07:51 +08:00
* @memberof Konva
* @augments Konva.BaseLayer
* @param {Object} config
* @param {Boolean} [config.clearBeforeDraw] set this property to false if you don't want
* to clear the canvas before each layer draw. The default value is true.
* @@nodeParams
* @@containerParams
* @example
2015-01-27 15:07:51 +08:00
* var layer = new Konva.Layer();
*/
Layer: function(config) {
this.____init(config);
},
/**
* FastLayer constructor. Layers are tied to their own canvas element and are used
* to contain shapes only. If you don't need node nesting, mouse and touch interactions,
* or event pub/sub, you should use FastLayer instead of Layer to create your layers.
* It renders about 2x faster than normal layers.
* @constructor
2015-01-27 15:07:51 +08:00
* @memberof Konva
* @augments Konva.BaseLayer
* @param {Object} config
* @param {Boolean} [config.clearBeforeDraw] set this property to false if you don't want
* to clear the canvas before each layer draw. The default value is true.
2014-05-08 18:34:38 +08:00
* @param {Boolean} [config.visible]
* @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
* @@containerParams
* @example
2015-01-27 15:07:51 +08:00
* var layer = new Konva.FastLayer();
*/
FastLayer: function(config) {
this.____init(config);
},
/**
* Group constructor. Groups are used to contain shapes or other groups.
* @constructor
2015-01-27 15:07:51 +08:00
* @memberof Konva
* @augments Konva.Container
* @param {Object} config
* @@nodeParams
* @@containerParams
* @example
2015-01-27 15:07:51 +08:00
* var group = new Konva.Group();
*/
Group: function(config) {
this.___init(config);
},
2013-03-26 16:09:21 +08:00
/**
* returns whether or not drag and drop is currently active
* @method
2015-01-27 15:07:51 +08:00
* @memberof Konva
2013-03-26 16:09:21 +08:00
*/
isDragging: function() {
2015-01-27 15:07:51 +08:00
var dd = Konva.DD;
2013-04-03 13:29:56 +08:00
// if DD is not included with the build, then
// drag and drop is not even possible
if (dd) {
2013-04-03 13:29:56 +08:00
return dd.isDragging;
} else {
return false;
2013-04-03 13:29:56 +08:00
}
},
/**
* returns whether or not a drag and drop operation is ready, but may
2013-04-03 13:29:56 +08:00
* not necessarily have started
* @method
2015-01-27 15:07:51 +08:00
* @memberof Konva
2013-04-03 13:29:56 +08:00
*/
isDragReady: function() {
2015-01-27 15:07:51 +08:00
var dd = Konva.DD;
2013-04-03 13:29:56 +08:00
// if DD is not included with the build, then
// drag and drop is not even possible
if (dd) {
2013-04-03 13:29:56 +08:00
return !!dd.node;
} else {
return false;
2013-04-03 13:29:56 +08:00
}
},
_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) {
2015-01-15 10:41:29 +08:00
var names = name.split(/\s/g);
for(var n = 0; n < names.length; n++) {
2015-01-15 10:41:29 +08:00
var subname = names[n];
if (subname) {
if(this.names[subname] === undefined) {
this.names[subname] = [];
}
2015-01-15 10:41:29 +08:00
this.names[subname].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];
}
}
}
},
getAngle: function(angle) {
return this.angleDeg ? angle * PI_OVER_180 : angle;
},
_parseUA: function(userAgent) {
var ua = userAgent.toLowerCase(),
// jQuery UA regex
match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
/(msie) ([\w.]+)/.exec( ua ) ||
ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
[],
// adding mobile flag as well
mobile = !!(userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)),
ieMobile = !!(userAgent.match(/IEMobile/i));
return {
browser: match[ 1 ] || '',
version: match[ 2 ] || '0',
// adding mobile flab
mobile: mobile,
2015-01-27 15:07:51 +08:00
ieMobile: ieMobile // If this is true (i.e., WP8), then Konva touch events are executed instead of equivalent Konva mouse events
};
},
// user agent
UA: undefined
};
2015-01-27 15:07:51 +08:00
Konva.UA = Konva._parseUA((root.navigator && root.navigator.userAgent) || '');
2014-02-27 19:55:39 +08:00
})(this);
// 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') {
2015-01-27 15:07:51 +08:00
var KonvaJS = factory();
2014-05-09 15:51:35 +08:00
// runtime-check for browserify
if(global.window === global) {
2015-01-27 15:07:51 +08:00
Konva.document = global.document;
Konva.window = global;
2014-05-09 15:51:35 +08:00
} else {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
var Canvas = require('canvas');
var jsdom = require('jsdom').jsdom;
2015-01-27 15:07:51 +08:00
Konva.document = jsdom('<!DOCTYPE html><html><head></head><body></body></html>');
Konva.window = Konva.document.createWindow();
Konva.window.Image = Canvas.Image;
Konva._nodeCanvas = Canvas;
2014-05-09 15:51:35 +08:00
}
2015-01-27 15:07:51 +08:00
Konva.root = root;
module.exports = KonvaJS;
return;
}
else if( typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory);
}
2015-01-27 15:07:51 +08:00
Konva.document = document;
Konva.window = window;
Konva.root = root;
2014-04-26 17:25:21 +08:00
}(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.
2015-01-27 15:07:51 +08:00
return Konva;
}));