2015-05-04 17:02:16 +08:00
|
|
|
(function(Konva) {
|
|
|
|
'use strict';
|
2013-03-24 13:56:22 +08:00
|
|
|
// CONSTANTS
|
2013-08-11 02:55:52 +08:00
|
|
|
var ABSOLUTE_OPACITY = 'absoluteOpacity',
|
|
|
|
ABSOLUTE_TRANSFORM = 'absoluteTransform',
|
2016-04-15 11:52:45 +08:00
|
|
|
ABSOLUTE_SCALE = 'absoluteScale',
|
2013-03-24 13:56:22 +08:00
|
|
|
CHANGE = 'Change',
|
2013-08-10 14:00:35 +08:00
|
|
|
CHILDREN = 'children',
|
|
|
|
DOT = '.',
|
|
|
|
EMPTY_STRING = '',
|
|
|
|
GET = 'get',
|
2013-03-24 13:56:22 +08:00
|
|
|
ID = 'id',
|
2015-01-30 05:25:49 +08:00
|
|
|
KONVA = 'konva',
|
2013-08-11 07:19:33 +08:00
|
|
|
LISTENING = 'listening',
|
2013-03-24 13:56:22 +08:00
|
|
|
MOUSEENTER = 'mouseenter',
|
|
|
|
MOUSELEAVE = 'mouseleave',
|
2013-08-10 14:00:35 +08:00
|
|
|
NAME = 'name',
|
|
|
|
SET = 'set',
|
|
|
|
SHAPE = 'Shape',
|
|
|
|
SPACE = ' ',
|
2013-08-12 11:34:54 +08:00
|
|
|
STAGE = 'stage',
|
2013-08-10 12:09:06 +08:00
|
|
|
TRANSFORM = 'transform',
|
2013-08-12 11:34:54 +08:00
|
|
|
UPPER_STAGE = 'Stage',
|
2013-08-10 14:00:35 +08:00
|
|
|
VISIBLE = 'visible',
|
2014-03-02 21:51:35 +08:00
|
|
|
CLONE_BLACK_LIST = ['id'],
|
2013-08-11 04:04:02 +08:00
|
|
|
|
2013-12-06 14:29:50 +08:00
|
|
|
TRANSFORM_CHANGE_STR = [
|
2015-01-27 15:07:51 +08:00
|
|
|
'xChange.konva',
|
|
|
|
'yChange.konva',
|
|
|
|
'scaleXChange.konva',
|
|
|
|
'scaleYChange.konva',
|
|
|
|
'skewXChange.konva',
|
|
|
|
'skewYChange.konva',
|
|
|
|
'rotationChange.konva',
|
|
|
|
'offsetXChange.konva',
|
|
|
|
'offsetYChange.konva',
|
|
|
|
'transformsEnabledChange.konva'
|
2016-04-15 11:52:45 +08:00
|
|
|
].join(SPACE),
|
|
|
|
|
|
|
|
SCALE_CHANGE_STR = [
|
|
|
|
'scaleXChange.konva',
|
|
|
|
'scaleYChange.konva'
|
2013-08-11 04:04:02 +08:00
|
|
|
].join(SPACE);
|
2013-08-10 15:58:53 +08:00
|
|
|
|
2015-04-08 23:26:43 +08:00
|
|
|
/**
|
|
|
|
* Node constructor. Nodes are entities that can be transformed, layered,
|
|
|
|
* and have bound events. The stage, layers, groups, and shapes all extend Node.
|
|
|
|
* @constructor
|
|
|
|
* @memberof Konva
|
|
|
|
* @abstract
|
|
|
|
* @param {Object} config
|
|
|
|
* @@nodeParams
|
|
|
|
*/
|
|
|
|
Konva.Node = function(config) {
|
|
|
|
this._init(config);
|
|
|
|
};
|
2014-03-02 21:51:35 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Util.addMethods(Konva.Node, {
|
2013-07-23 12:41:41 +08:00
|
|
|
_init: function(config) {
|
2013-08-12 11:34:54 +08:00
|
|
|
var that = this;
|
2015-01-27 15:07:51 +08:00
|
|
|
this._id = Konva.idCounter++;
|
2012-11-14 15:22:56 +08:00
|
|
|
this.eventListeners = {};
|
2013-07-23 13:05:21 +08:00
|
|
|
this.attrs = {};
|
2013-12-20 15:29:23 +08:00
|
|
|
this._cache = {};
|
2014-01-01 05:04:05 +08:00
|
|
|
this._filterUpToDate = false;
|
2016-12-13 20:01:51 +08:00
|
|
|
this._isUnderCache = false;
|
2012-11-14 15:22:56 +08:00
|
|
|
this.setAttrs(config);
|
2013-08-11 04:04:02 +08:00
|
|
|
|
|
|
|
// event bindings for cache handling
|
2013-12-06 14:29:50 +08:00
|
|
|
this.on(TRANSFORM_CHANGE_STR, function() {
|
2013-08-12 11:34:54 +08:00
|
|
|
this._clearCache(TRANSFORM);
|
2013-12-10 02:07:08 +08:00
|
|
|
that._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
|
2013-08-12 11:34:54 +08:00
|
|
|
});
|
2016-04-15 11:52:45 +08:00
|
|
|
|
|
|
|
this.on(SCALE_CHANGE_STR, function() {
|
|
|
|
that._clearSelfAndDescendantCache(ABSOLUTE_SCALE);
|
|
|
|
});
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
this.on('visibleChange.konva', function() {
|
2013-12-10 02:07:08 +08:00
|
|
|
that._clearSelfAndDescendantCache(VISIBLE);
|
2013-08-12 11:34:54 +08:00
|
|
|
});
|
2015-01-27 15:07:51 +08:00
|
|
|
this.on('listeningChange.konva', function() {
|
2013-12-10 02:07:08 +08:00
|
|
|
that._clearSelfAndDescendantCache(LISTENING);
|
2013-08-12 11:34:54 +08:00
|
|
|
});
|
2015-01-27 15:07:51 +08:00
|
|
|
this.on('opacityChange.konva', function() {
|
2013-12-10 02:07:08 +08:00
|
|
|
that._clearSelfAndDescendantCache(ABSOLUTE_OPACITY);
|
2013-08-12 11:34:54 +08:00
|
|
|
});
|
|
|
|
},
|
2013-08-10 12:09:06 +08:00
|
|
|
_clearCache: function(attr){
|
2013-12-30 06:07:58 +08:00
|
|
|
if (attr) {
|
|
|
|
delete this._cache[attr];
|
|
|
|
}
|
|
|
|
else {
|
2014-02-27 08:49:18 +08:00
|
|
|
this._cache = {};
|
2013-12-30 06:07:58 +08:00
|
|
|
}
|
2013-08-10 12:09:06 +08:00
|
|
|
},
|
2013-08-10 13:31:25 +08:00
|
|
|
_getCache: function(attr, privateGetter){
|
2013-12-20 15:29:23 +08:00
|
|
|
var cache = this._cache[attr];
|
2013-08-25 15:34:49 +08:00
|
|
|
|
2013-08-10 13:31:25 +08:00
|
|
|
// if not cached, we need to set it using the private getter method.
|
2013-08-10 14:00:35 +08:00
|
|
|
if (cache === undefined) {
|
2013-12-20 15:29:23 +08:00
|
|
|
this._cache[attr] = privateGetter.call(this);
|
2013-08-10 13:23:27 +08:00
|
|
|
}
|
2013-08-10 13:31:25 +08:00
|
|
|
|
2014-02-27 08:49:18 +08:00
|
|
|
return this._cache[attr];
|
2013-08-10 13:23:27 +08:00
|
|
|
},
|
2013-12-10 02:07:08 +08:00
|
|
|
/*
|
|
|
|
* when the logic for a cached result depends on ancestor propagation, use this
|
|
|
|
* method to clear self and children cache
|
|
|
|
*/
|
|
|
|
_clearSelfAndDescendantCache: function(attr) {
|
2013-08-12 11:34:54 +08:00
|
|
|
this._clearCache(attr);
|
|
|
|
|
|
|
|
if (this.children) {
|
|
|
|
this.getChildren().each(function(node) {
|
2013-12-10 02:38:01 +08:00
|
|
|
node._clearSelfAndDescendantCache(attr);
|
2013-08-12 11:34:54 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2013-12-20 15:29:23 +08:00
|
|
|
/**
|
|
|
|
* clear cached canvas
|
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @returns {Konva.Node}
|
2013-12-20 15:29:23 +08:00
|
|
|
* @example
|
|
|
|
* node.clearCache();
|
|
|
|
*/
|
2014-01-06 05:21:05 +08:00
|
|
|
clearCache: function() {
|
2013-12-30 06:07:58 +08:00
|
|
|
delete this._cache.canvas;
|
2014-01-06 05:21:05 +08:00
|
|
|
this._filterUpToDate = false;
|
|
|
|
return this;
|
2013-12-20 15:29:23 +08:00
|
|
|
},
|
|
|
|
/**
|
2015-02-15 08:18:09 +08:00
|
|
|
* cache node to improve drawing performance, apply filters, or create more accurate
|
|
|
|
* hit regions. For all basic shapes size of cache canvas will be automatically detected.
|
|
|
|
* If you need to cache your custom `Konva.Shape` instance you have to pass shape's bounding box
|
|
|
|
* properties. Look at [link to demo page](link to demo page) for more information.
|
2013-12-20 15:29:23 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2015-02-15 08:18:09 +08:00
|
|
|
* @param {Object} [config]
|
2014-01-06 05:21:05 +08:00
|
|
|
* @param {Number} [config.x]
|
|
|
|
* @param {Number} [config.y]
|
|
|
|
* @param {Number} [config.width]
|
|
|
|
* @param {Number} [config.height]
|
2015-02-15 08:18:09 +08:00
|
|
|
* @param {Number} [config.offset] increase canvas size by `offset` pixel in all directions.
|
2014-02-24 22:33:25 +08:00
|
|
|
* @param {Boolean} [config.drawBorder] when set to true, a red border will be drawn around the cached
|
2014-01-06 05:21:05 +08:00
|
|
|
* region for debugging purposes
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Node}
|
2013-12-20 15:29:23 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // cache a shape with the x,y position of the bounding box at the center and
|
|
|
|
* // the width and height of the bounding box equal to the width and height of
|
|
|
|
* // the shape obtained from shape.width() and shape.height()
|
|
|
|
* image.cache();
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // cache a node and define the bounding box position and size
|
|
|
|
* node.cache({
|
|
|
|
* x: -30,
|
|
|
|
* y: -30,
|
|
|
|
* width: 100,
|
|
|
|
* height: 200
|
|
|
|
* });
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // cache a node and draw a red border around the bounding box
|
|
|
|
* // for debugging purposes
|
|
|
|
* node.cache({
|
|
|
|
* x: -30,
|
|
|
|
* y: -30,
|
|
|
|
* width: 100,
|
|
|
|
* height: 200,
|
2015-02-12 15:10:36 +08:00
|
|
|
* offset : 10,
|
2014-04-04 11:17:09 +08:00
|
|
|
* drawBorder: true
|
2014-01-06 06:55:35 +08:00
|
|
|
* });
|
2013-12-20 15:29:23 +08:00
|
|
|
*/
|
2014-01-06 05:21:05 +08:00
|
|
|
cache: function(config) {
|
|
|
|
var conf = config || {},
|
2015-02-12 15:10:36 +08:00
|
|
|
rect = this.getClientRect(true),
|
|
|
|
width = conf.width || rect.width,
|
|
|
|
height = conf.height || rect.height,
|
2016-12-15 01:11:54 +08:00
|
|
|
pixelRatio = conf.pixelRatio,
|
2015-02-12 15:10:36 +08:00
|
|
|
x = conf.x || rect.x,
|
|
|
|
y = conf.y || rect.y,
|
|
|
|
offset = conf.offset || 0,
|
2014-08-19 19:27:46 +08:00
|
|
|
drawBorder = conf.drawBorder || false;
|
|
|
|
|
2015-02-12 15:10:36 +08:00
|
|
|
if (!width || !height) {
|
|
|
|
throw new Error('Width or height of caching configuration equals 0.');
|
2014-03-12 00:01:58 +08:00
|
|
|
}
|
2015-02-12 15:10:36 +08:00
|
|
|
|
|
|
|
width += offset * 2;
|
|
|
|
height += offset * 2;
|
|
|
|
|
|
|
|
x -= offset;
|
|
|
|
y -= offset;
|
|
|
|
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
var cachedSceneCanvas = new Konva.SceneCanvas({
|
2016-12-15 01:11:54 +08:00
|
|
|
pixelRatio: pixelRatio,
|
2015-02-12 15:10:36 +08:00
|
|
|
width: width,
|
|
|
|
height: height
|
|
|
|
}),
|
|
|
|
cachedFilterCanvas = new Konva.SceneCanvas({
|
2016-12-15 01:11:54 +08:00
|
|
|
pixelRatio: pixelRatio,
|
2015-02-12 15:10:36 +08:00
|
|
|
width: width,
|
|
|
|
height: height
|
|
|
|
}),
|
|
|
|
cachedHitCanvas = new Konva.HitCanvas({
|
2015-05-04 17:02:16 +08:00
|
|
|
pixelRatio: 1,
|
2015-02-12 15:10:36 +08:00
|
|
|
width: width,
|
|
|
|
height: height
|
|
|
|
}),
|
|
|
|
sceneContext = cachedSceneCanvas.getContext(),
|
|
|
|
hitContext = cachedHitCanvas.getContext();
|
2014-01-06 05:21:05 +08:00
|
|
|
|
2014-01-19 14:08:49 +08:00
|
|
|
cachedHitCanvas.isCache = true;
|
|
|
|
|
2014-01-06 05:21:05 +08:00
|
|
|
this.clearCache();
|
2015-05-04 17:02:16 +08:00
|
|
|
|
2014-03-22 15:13:05 +08:00
|
|
|
sceneContext.save();
|
|
|
|
hitContext.save();
|
2013-12-29 05:25:15 +08:00
|
|
|
|
2015-02-12 15:10:36 +08:00
|
|
|
sceneContext.translate(-x, -y);
|
|
|
|
hitContext.translate(-x, -y);
|
|
|
|
|
2016-12-13 20:01:51 +08:00
|
|
|
// extra flag to skip on getAbsolute opacity calc
|
|
|
|
this._isUnderCache = true;
|
|
|
|
this._clearSelfAndDescendantCache(ABSOLUTE_OPACITY);
|
2016-12-15 01:11:54 +08:00
|
|
|
this._clearSelfAndDescendantCache(ABSOLUTE_SCALE);
|
2016-12-13 20:01:51 +08:00
|
|
|
|
2015-02-12 15:10:36 +08:00
|
|
|
this.drawScene(cachedSceneCanvas, this, true);
|
|
|
|
this.drawHit(cachedHitCanvas, this, true);
|
2016-12-13 20:01:51 +08:00
|
|
|
this._isUnderCache = false;
|
2015-02-12 15:10:36 +08:00
|
|
|
|
|
|
|
sceneContext.restore();
|
|
|
|
hitContext.restore();
|
|
|
|
|
2014-01-06 05:21:05 +08:00
|
|
|
// this will draw a red border around the cached box for
|
|
|
|
// debugging purposes
|
2014-08-19 19:27:46 +08:00
|
|
|
if (drawBorder) {
|
2014-01-06 05:21:05 +08:00
|
|
|
sceneContext.save();
|
|
|
|
sceneContext.beginPath();
|
|
|
|
sceneContext.rect(0, 0, width, height);
|
|
|
|
sceneContext.closePath();
|
|
|
|
sceneContext.setAttr('strokeStyle', 'red');
|
|
|
|
sceneContext.setAttr('lineWidth', 5);
|
|
|
|
sceneContext.stroke();
|
|
|
|
sceneContext.restore();
|
|
|
|
}
|
2014-03-22 15:17:56 +08:00
|
|
|
|
2013-12-29 05:25:15 +08:00
|
|
|
this._cache.canvas = {
|
2014-01-05 17:10:56 +08:00
|
|
|
scene: cachedSceneCanvas,
|
|
|
|
filter: cachedFilterCanvas,
|
2015-02-12 15:10:36 +08:00
|
|
|
hit: cachedHitCanvas,
|
2015-05-04 17:02:16 +08:00
|
|
|
x: x,
|
|
|
|
y: y
|
2013-12-29 05:25:15 +08:00
|
|
|
};
|
2013-12-31 06:34:57 +08:00
|
|
|
|
|
|
|
return this;
|
2013-12-20 15:29:23 +08:00
|
|
|
},
|
2015-02-12 15:10:36 +08:00
|
|
|
/**
|
2015-05-25 14:56:19 +08:00
|
|
|
* Return client rectangle {x, y, width, height} of node. This rectangle also include all styling (strokes, shadows, etc).
|
|
|
|
* The rectangle position is relative to parent container.
|
2015-02-12 15:10:36 +08:00
|
|
|
* @method
|
|
|
|
* @memberof Konva.Node.prototype
|
2015-02-15 08:18:09 +08:00
|
|
|
* @param {Boolean} [skipTransform] flag should we skip transformation to rectangle
|
2015-02-12 15:10:36 +08:00
|
|
|
* @returns {Object} rect with {x, y, width, height} properties
|
|
|
|
* @example
|
2015-02-15 08:18:09 +08:00
|
|
|
* var rect = new Konva.Rect({
|
|
|
|
* width : 100,
|
|
|
|
* height : 100,
|
|
|
|
* x : 50,
|
|
|
|
* y : 50,
|
|
|
|
* strokeWidth : 4,
|
|
|
|
* stroke : 'black',
|
|
|
|
* offsetX : 50,
|
|
|
|
* scaleY : 2
|
|
|
|
* });
|
2015-02-12 15:10:36 +08:00
|
|
|
*
|
2015-02-15 08:18:09 +08:00
|
|
|
* // get client rect without think off transformations (position, rotation, scale, offset, etc)
|
|
|
|
* rect.getClientRect(true);
|
|
|
|
* // returns {
|
|
|
|
* // x : -2, // two pixels for stroke / 2
|
|
|
|
* // y : -2,
|
|
|
|
* // width : 104, // increased by 4 for stroke
|
|
|
|
* // height : 104
|
|
|
|
* //}
|
|
|
|
*
|
|
|
|
* // get client rect with transformation applied
|
|
|
|
* rect.getClientRect();
|
|
|
|
* // returns Object {x: -2, y: 46, width: 104, height: 208}
|
2015-02-12 15:10:36 +08:00
|
|
|
*/
|
2015-05-04 17:02:16 +08:00
|
|
|
getClientRect: function() {
|
2015-02-12 15:10:36 +08:00
|
|
|
// abstract method
|
|
|
|
// redefine in Container and Shape
|
2015-10-22 13:32:07 +08:00
|
|
|
throw new Error('abstract "getClientRect" method call');
|
2015-02-12 15:10:36 +08:00
|
|
|
},
|
2015-05-04 17:02:16 +08:00
|
|
|
_transformedRect: function(rect) {
|
2015-02-12 15:10:36 +08:00
|
|
|
var points = [
|
2015-05-04 17:02:16 +08:00
|
|
|
{x: rect.x, y: rect.y},
|
|
|
|
{x: rect.x + rect.width, y: rect.y},
|
|
|
|
{x: rect.x + rect.width, y: rect.y + rect.height},
|
|
|
|
{x: rect.x, y: rect.y + rect.height}
|
2015-02-12 15:10:36 +08:00
|
|
|
];
|
|
|
|
var minX, minY, maxX, maxY;
|
|
|
|
var trans = this.getTransform();
|
|
|
|
points.forEach(function(point) {
|
|
|
|
var transformed = trans.point(point);
|
|
|
|
if (minX === undefined) {
|
|
|
|
minX = maxX = transformed.x;
|
|
|
|
minY = maxY = transformed.y;
|
|
|
|
}
|
|
|
|
minX = Math.min(minX, transformed.x);
|
|
|
|
minY = Math.min(minY, transformed.y);
|
|
|
|
maxX = Math.max(maxX, transformed.x);
|
|
|
|
maxY = Math.max(maxY, transformed.y);
|
|
|
|
});
|
|
|
|
return {
|
2016-02-28 16:57:15 +08:00
|
|
|
x: minX,
|
|
|
|
y: minY,
|
|
|
|
width: maxX - minX,
|
|
|
|
height: maxY - minY
|
2015-02-12 15:10:36 +08:00
|
|
|
};
|
|
|
|
},
|
2014-01-01 05:04:05 +08:00
|
|
|
_drawCachedSceneCanvas: function(context) {
|
2014-01-05 17:10:56 +08:00
|
|
|
context.save();
|
2015-02-14 23:12:54 +08:00
|
|
|
context._applyOpacity(this);
|
2015-02-12 15:10:36 +08:00
|
|
|
context.translate(
|
|
|
|
this._cache.canvas.x,
|
|
|
|
this._cache.canvas.y
|
|
|
|
);
|
|
|
|
|
2015-02-14 23:12:54 +08:00
|
|
|
var cacheCanvas = this._getCachedSceneCanvas();
|
2015-04-16 22:49:08 +08:00
|
|
|
var ratio = cacheCanvas.pixelRatio;
|
2015-02-14 23:12:54 +08:00
|
|
|
|
2015-04-16 22:49:08 +08:00
|
|
|
context.drawImage(cacheCanvas._canvas, 0, 0, cacheCanvas.width / ratio, cacheCanvas.height / ratio);
|
2014-01-05 17:10:56 +08:00
|
|
|
context.restore();
|
|
|
|
},
|
2015-02-12 15:10:36 +08:00
|
|
|
_drawCachedHitCanvas: function(context) {
|
|
|
|
var cachedCanvas = this._cache.canvas,
|
|
|
|
hitCanvas = cachedCanvas.hit;
|
|
|
|
context.save();
|
|
|
|
context.translate(
|
|
|
|
this._cache.canvas.x,
|
|
|
|
this._cache.canvas.y
|
|
|
|
);
|
|
|
|
context.drawImage(hitCanvas._canvas, 0, 0);
|
|
|
|
context.restore();
|
|
|
|
},
|
2014-01-05 17:10:56 +08:00
|
|
|
_getCachedSceneCanvas: function() {
|
2014-01-01 05:04:05 +08:00
|
|
|
var filters = this.filters(),
|
|
|
|
cachedCanvas = this._cache.canvas,
|
|
|
|
sceneCanvas = cachedCanvas.scene,
|
|
|
|
filterCanvas = cachedCanvas.filter,
|
|
|
|
filterContext = filterCanvas.getContext(),
|
|
|
|
len, imageData, n, filter;
|
|
|
|
|
|
|
|
if (filters) {
|
|
|
|
if (!this._filterUpToDate) {
|
2015-04-13 02:57:52 +08:00
|
|
|
var ratio = sceneCanvas.pixelRatio;
|
2015-05-04 17:02:16 +08:00
|
|
|
|
2014-01-01 05:04:05 +08:00
|
|
|
try {
|
|
|
|
len = filters.length;
|
|
|
|
filterContext.clear();
|
2015-04-13 02:57:52 +08:00
|
|
|
|
2014-01-01 05:04:05 +08:00
|
|
|
// copy cached canvas onto filter context
|
2015-04-13 02:57:52 +08:00
|
|
|
filterContext.drawImage(sceneCanvas._canvas, 0, 0, sceneCanvas.getWidth() / ratio, sceneCanvas.getHeight() / ratio);
|
2014-01-01 05:04:05 +08:00
|
|
|
imageData = filterContext.getImageData(0, 0, filterCanvas.getWidth(), filterCanvas.getHeight());
|
|
|
|
|
|
|
|
// apply filters to filter context
|
2015-05-04 17:02:16 +08:00
|
|
|
for (n = 0; n < len; n++) {
|
2014-01-01 05:04:05 +08:00
|
|
|
filter = filters[n];
|
2016-09-11 22:01:38 +08:00
|
|
|
if (typeof filter !== 'function') {
|
|
|
|
Konva.Util.error(
|
|
|
|
'Filter should be type of function, but got ' +
|
|
|
|
(typeof filter) + ' insted. Please check correct filters'
|
|
|
|
);
|
|
|
|
continue;
|
|
|
|
}
|
2014-01-01 05:04:05 +08:00
|
|
|
filter.call(this, imageData);
|
|
|
|
filterContext.putImageData(imageData, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(e) {
|
2016-09-11 22:01:38 +08:00
|
|
|
Konva.Util.error('Unable to apply filter. ' + e.message);
|
2014-01-01 05:04:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
this._filterUpToDate = true;
|
|
|
|
}
|
|
|
|
|
2014-01-05 17:10:56 +08:00
|
|
|
return filterCanvas;
|
2014-01-01 05:04:05 +08:00
|
|
|
}
|
2015-10-22 13:32:07 +08:00
|
|
|
return sceneCanvas;
|
2014-01-05 17:10:56 +08:00
|
|
|
},
|
2012-11-14 15:22:56 +08:00
|
|
|
/**
|
2015-01-27 15:07:51 +08:00
|
|
|
* bind events to the node. KonvaJS supports mouseover, mousemove,
|
2016-02-29 08:03:03 +08:00
|
|
|
* mouseout, mouseenter, mouseleave, mousedown, mouseup, wheel, click, dblclick, touchstart, touchmove,
|
2015-01-27 15:07:51 +08:00
|
|
|
* touchend, tap, dbltap, dragstart, dragmove, and dragend events. The Konva Stage supports
|
2016-10-25 23:03:25 +08:00
|
|
|
* contentMouseover, contentMousemove, contentMouseout, contentMousedown, contentMouseup, contentWheel, contentContextmenu
|
2013-10-09 00:54:39 +08:00
|
|
|
* contentClick, contentDblclick, contentTouchstart, contentTouchmove, contentTouchend, contentTap,
|
|
|
|
* and contentDblTap. Pass in a string of events delimmited by a space to bind multiple events at once
|
2012-11-27 11:12:02 +08:00
|
|
|
* such as 'mousedown mouseup mousemove'. Include a namespace to bind an
|
2012-11-14 15:22:56 +08:00
|
|
|
* event by name such as 'click.foobar'.
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-07-25 13:56:21 +08:00
|
|
|
* @param {String} evtStr e.g. 'click', 'mousedown touchstart', 'mousedown.foo touchstart.foo'
|
2012-11-27 11:12:02 +08:00
|
|
|
* @param {Function} handler The handler function is passed an event object
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Node}
|
2013-05-16 00:27:22 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // add click listener
|
|
|
|
* node.on('click', function() {
|
|
|
|
* console.log('you clicked me!');
|
|
|
|
* });
|
2013-07-22 11:14:09 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get the target node
|
|
|
|
* node.on('click', function(evt) {
|
|
|
|
* console.log(evt.target);
|
|
|
|
* });
|
2013-05-18 01:51:56 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // stop event propagation
|
|
|
|
* node.on('click', function(evt) {
|
|
|
|
* evt.cancelBubble = true;
|
|
|
|
* });
|
2013-05-18 01:51:56 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // bind multiple listeners
|
|
|
|
* node.on('click touchstart', function() {
|
|
|
|
* console.log('you clicked/touched me!');
|
|
|
|
* });
|
2013-05-18 01:51:56 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // namespace listener
|
|
|
|
* node.on('click.foo', function() {
|
|
|
|
* console.log('you clicked/touched me!');
|
|
|
|
* });
|
2014-03-21 12:55:30 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get the event type
|
|
|
|
* node.on('click tap', function(evt) {
|
|
|
|
* var eventType = evt.type;
|
|
|
|
* });
|
2014-03-21 12:55:30 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get native event object
|
|
|
|
* node.on('click tap', function(evt) {
|
|
|
|
* var nativeEvent = evt.evt;
|
|
|
|
* });
|
2014-03-27 23:01:08 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // for change events, get the old and new val
|
|
|
|
* node.on('xChange', function(evt) {
|
|
|
|
* var oldVal = evt.oldVal;
|
|
|
|
* var newVal = evt.newVal;
|
2013-05-16 15:28:49 +08:00
|
|
|
* });
|
2015-11-22 11:44:33 +08:00
|
|
|
*
|
2015-11-22 23:26:04 +08:00
|
|
|
* // get event targets
|
|
|
|
* // with event delegations
|
2015-11-22 11:44:33 +08:00
|
|
|
* layer.on('click', 'Group', function(evt) {
|
|
|
|
* var shape = evt.target;
|
|
|
|
* var group = evtn.currentTarger;
|
|
|
|
* });
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
2013-07-25 13:56:21 +08:00
|
|
|
on: function(evtStr, handler) {
|
2015-11-22 11:44:33 +08:00
|
|
|
if (arguments.length === 3) {
|
|
|
|
return this._delegate.apply(this, arguments);
|
|
|
|
}
|
2013-07-25 13:56:21 +08:00
|
|
|
var events = evtStr.split(SPACE),
|
|
|
|
len = events.length,
|
|
|
|
n, event, parts, baseEvent, name;
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-03-24 13:56:22 +08:00
|
|
|
/*
|
2012-11-14 15:22:56 +08:00
|
|
|
* loop through types and attach event listeners to
|
|
|
|
* each one. eg. 'click mouseover.namespace mouseout'
|
|
|
|
* will create three event bindings
|
|
|
|
*/
|
2013-03-24 13:56:22 +08:00
|
|
|
for(n = 0; n < len; n++) {
|
2013-07-25 13:56:21 +08:00
|
|
|
event = events[n];
|
2013-03-24 13:56:22 +08:00
|
|
|
parts = event.split(DOT);
|
|
|
|
baseEvent = parts[0];
|
2013-07-25 13:56:21 +08:00
|
|
|
name = parts[1] || EMPTY_STRING;
|
2012-11-14 15:22:56 +08:00
|
|
|
|
2013-07-25 13:56:21 +08:00
|
|
|
// create events array if it doesn't exist
|
2012-11-14 15:22:56 +08:00
|
|
|
if(!this.eventListeners[baseEvent]) {
|
|
|
|
this.eventListeners[baseEvent] = [];
|
|
|
|
}
|
2012-08-26 13:26:25 +08:00
|
|
|
|
2012-11-14 15:22:56 +08:00
|
|
|
this.eventListeners[baseEvent].push({
|
|
|
|
name: name,
|
|
|
|
handler: handler
|
|
|
|
});
|
2012-07-14 12:24:38 +08:00
|
|
|
}
|
2013-12-10 02:07:08 +08:00
|
|
|
|
2013-03-15 06:07:35 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
2012-11-27 11:12:02 +08:00
|
|
|
* remove event bindings from the node. Pass in a string of
|
2012-11-14 15:22:56 +08:00
|
|
|
* event types delimmited by a space to remove multiple event
|
|
|
|
* bindings at once such as 'mousedown mouseup mousemove'.
|
|
|
|
* include a namespace to remove an event binding by name
|
|
|
|
* such as 'click.foobar'. If you only give a name like '.foobar',
|
|
|
|
* all events in that namespace will be removed.
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-07-25 13:56:21 +08:00
|
|
|
* @param {String} evtStr e.g. 'click', 'mousedown touchstart', '.foobar'
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Node}
|
2013-05-18 02:46:06 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // remove listener
|
|
|
|
* node.off('click');
|
2013-05-18 02:46:06 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // remove multiple listeners
|
|
|
|
* node.off('click touchstart');
|
2013-05-18 02:46:06 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // remove listener by name
|
2013-05-18 02:46:06 +08:00
|
|
|
* node.off('click.foo');
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
2013-07-25 13:56:21 +08:00
|
|
|
off: function(evtStr) {
|
2014-05-15 23:44:14 +08:00
|
|
|
var events = (evtStr || '').split(SPACE),
|
2013-07-25 13:56:21 +08:00
|
|
|
len = events.length,
|
2013-12-10 02:38:01 +08:00
|
|
|
n, t, event, parts, baseEvent, name;
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2014-05-15 23:44:14 +08:00
|
|
|
if (!evtStr) {
|
|
|
|
// remove all events
|
|
|
|
for(t in this.eventListeners) {
|
|
|
|
this._off(t);
|
|
|
|
}
|
|
|
|
}
|
2013-03-24 13:56:22 +08:00
|
|
|
for(n = 0; n < len; n++) {
|
2013-07-25 13:56:21 +08:00
|
|
|
event = events[n];
|
2013-03-24 13:56:22 +08:00
|
|
|
parts = event.split(DOT);
|
|
|
|
baseEvent = parts[0];
|
2013-07-25 13:56:21 +08:00
|
|
|
name = parts[1];
|
2012-11-14 15:22:56 +08:00
|
|
|
|
2013-07-25 13:56:21 +08:00
|
|
|
if(baseEvent) {
|
|
|
|
if(this.eventListeners[baseEvent]) {
|
|
|
|
this._off(baseEvent, name);
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2013-07-25 13:56:21 +08:00
|
|
|
for(t in this.eventListeners) {
|
|
|
|
this._off(t, name);
|
|
|
|
}
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
2012-07-14 12:24:38 +08:00
|
|
|
}
|
2013-03-15 06:07:35 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
2014-03-21 14:45:38 +08:00
|
|
|
// some event aliases for third party integration like HammerJS
|
2014-02-21 09:03:21 +08:00
|
|
|
dispatchEvent: function(evt) {
|
2014-03-21 14:45:38 +08:00
|
|
|
var e = {
|
|
|
|
target: this,
|
|
|
|
type: evt.type,
|
|
|
|
evt: evt
|
|
|
|
};
|
|
|
|
this.fire(evt.type, e);
|
2015-12-22 18:19:33 +08:00
|
|
|
return this;
|
2014-02-21 09:03:21 +08:00
|
|
|
},
|
2014-03-21 14:45:38 +08:00
|
|
|
addEventListener: function(type, handler) {
|
2014-04-15 08:51:18 +08:00
|
|
|
// we have to pass native event to handler
|
2014-03-21 14:45:38 +08:00
|
|
|
this.on(type, function(evt){
|
|
|
|
handler.call(this, evt.evt);
|
|
|
|
});
|
2015-12-22 18:19:33 +08:00
|
|
|
return this;
|
2014-02-21 09:03:21 +08:00
|
|
|
},
|
2015-05-04 17:02:16 +08:00
|
|
|
removeEventListener: function(type) {
|
2014-04-15 08:51:18 +08:00
|
|
|
this.off(type);
|
2015-12-22 18:19:33 +08:00
|
|
|
return this;
|
2014-04-15 08:51:18 +08:00
|
|
|
},
|
2015-11-22 23:26:04 +08:00
|
|
|
// like node.on
|
2015-11-22 11:44:33 +08:00
|
|
|
_delegate: function(event, selector, handler) {
|
|
|
|
var stopNode = this;
|
|
|
|
this.on(event, function(evt) {
|
2015-12-25 22:35:19 +08:00
|
|
|
var targets = evt.target.findAncestors(selector, true, stopNode);
|
2015-11-22 11:44:33 +08:00
|
|
|
for(var i = 0; i < targets.length; i++) {
|
|
|
|
evt = Konva.Util.cloneObject(evt);
|
|
|
|
evt.currentTarget = targets[i];
|
|
|
|
handler.call(targets[i], evt);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
2012-11-14 15:22:56 +08:00
|
|
|
/**
|
2013-05-18 01:51:56 +08:00
|
|
|
* remove self from parent, but don't destroy
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @returns {Konva.Node}
|
2013-05-18 02:46:06 +08:00
|
|
|
* @example
|
|
|
|
* node.remove();
|
2012-03-07 13:45:48 +08:00
|
|
|
*/
|
2012-11-14 15:22:56 +08:00
|
|
|
remove: function() {
|
|
|
|
var parent = this.getParent();
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-01-13 14:01:12 +08:00
|
|
|
if(parent && parent.children) {
|
2012-11-14 15:22:56 +08:00
|
|
|
parent.children.splice(this.index, 1);
|
|
|
|
parent._setChildrenIndices();
|
2013-06-09 06:57:36 +08:00
|
|
|
delete this.parent;
|
2013-01-13 14:01:12 +08:00
|
|
|
}
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-08-12 11:34:54 +08:00
|
|
|
// every cached attr that is calculated via node tree
|
2013-12-10 02:07:08 +08:00
|
|
|
// traversal must be cleared when removing a node
|
|
|
|
this._clearSelfAndDescendantCache(STAGE);
|
|
|
|
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
|
|
|
|
this._clearSelfAndDescendantCache(VISIBLE);
|
|
|
|
this._clearSelfAndDescendantCache(LISTENING);
|
|
|
|
this._clearSelfAndDescendantCache(ABSOLUTE_OPACITY);
|
2013-08-12 11:34:54 +08:00
|
|
|
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2013-01-13 14:01:12 +08:00
|
|
|
},
|
|
|
|
/**
|
2013-05-18 01:51:56 +08:00
|
|
|
* remove and destroy self
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-05-18 02:46:06 +08:00
|
|
|
* @example
|
|
|
|
* node.destroy();
|
2013-01-13 14:01:12 +08:00
|
|
|
*/
|
|
|
|
destroy: function() {
|
2013-01-14 03:10:49 +08:00
|
|
|
// remove from ids and names hashes
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva._removeId(this.getId());
|
|
|
|
Konva._removeName(this.getName(), this._id);
|
2013-01-13 14:01:12 +08:00
|
|
|
|
2013-01-14 11:59:35 +08:00
|
|
|
this.remove();
|
2015-12-22 18:19:33 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
2013-03-15 23:33:05 +08:00
|
|
|
/**
|
|
|
|
* get attr
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-07-22 11:14:09 +08:00
|
|
|
* @param {String} attr
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Integer|String|Object|Array}
|
2013-05-18 02:46:06 +08:00
|
|
|
* @example
|
2013-05-19 01:40:05 +08:00
|
|
|
* var x = node.getAttr('x');
|
2013-03-15 23:33:05 +08:00
|
|
|
*/
|
|
|
|
getAttr: function(attr) {
|
2015-01-27 15:07:51 +08:00
|
|
|
var method = GET + Konva.Util._capitalize(attr);
|
|
|
|
if(Konva.Util._isFunction(this[method])) {
|
2013-04-28 11:50:42 +08:00
|
|
|
return this[method]();
|
|
|
|
}
|
|
|
|
// otherwise get directly
|
2015-10-22 13:32:07 +08:00
|
|
|
return this.attrs[attr];
|
2013-03-15 23:33:05 +08:00
|
|
|
},
|
2013-08-10 15:58:53 +08:00
|
|
|
/**
|
|
|
|
* get ancestors
|
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @returns {Konva.Collection}
|
2013-08-10 15:58:53 +08:00
|
|
|
* @example
|
|
|
|
* shape.getAncestors().each(function(node) {
|
|
|
|
* console.log(node.getId());
|
|
|
|
* })
|
|
|
|
*/
|
|
|
|
getAncestors: function() {
|
|
|
|
var parent = this.getParent(),
|
2015-01-27 15:07:51 +08:00
|
|
|
ancestors = new Konva.Collection();
|
2013-08-10 15:58:53 +08:00
|
|
|
|
|
|
|
while (parent) {
|
|
|
|
ancestors.push(parent);
|
|
|
|
parent = parent.getParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return ancestors;
|
|
|
|
},
|
2012-11-14 15:22:56 +08:00
|
|
|
/**
|
2013-05-18 02:46:06 +08:00
|
|
|
* get attrs object literal
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Object}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
getAttrs: function() {
|
2013-03-15 23:33:05 +08:00
|
|
|
return this.attrs || {};
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
2013-05-18 02:46:06 +08:00
|
|
|
* set multiple attrs at once using an object literal
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2012-11-27 11:12:02 +08:00
|
|
|
* @param {Object} config object containing key value pairs
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Node}
|
2013-05-18 02:46:06 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* node.setAttrs({
|
|
|
|
* x: 5,
|
|
|
|
* fill: 'red'
|
|
|
|
* });
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
setAttrs: function(config) {
|
2013-03-24 13:56:22 +08:00
|
|
|
var key, method;
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2015-05-04 17:02:16 +08:00
|
|
|
if(!config) {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
for(key in config) {
|
|
|
|
if (key === CHILDREN) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
method = SET + Konva.Util._capitalize(key);
|
|
|
|
// use setter if available
|
|
|
|
if(Konva.Util._isFunction(this[method])) {
|
|
|
|
this[method](config[key]);
|
|
|
|
}
|
|
|
|
// otherwise set directly
|
|
|
|
else {
|
|
|
|
this._setAttr(key, config[key]);
|
2012-03-07 13:45:48 +08:00
|
|
|
}
|
2012-03-14 12:16:25 +08:00
|
|
|
}
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
2013-08-11 07:19:33 +08:00
|
|
|
/**
|
2013-12-10 02:07:08 +08:00
|
|
|
* determine if node is listening for events by taking into account ancestors.
|
|
|
|
*
|
|
|
|
* Parent | Self | isListening
|
2015-05-04 17:02:16 +08:00
|
|
|
* listening | listening |
|
2013-12-10 02:07:08 +08:00
|
|
|
* ----------+-----------+------------
|
2015-05-04 17:02:16 +08:00
|
|
|
* T | T | T
|
2013-12-10 02:07:08 +08:00
|
|
|
* T | F | F
|
2015-05-04 17:02:16 +08:00
|
|
|
* F | T | T
|
2013-12-10 02:07:08 +08:00
|
|
|
* F | F | F
|
|
|
|
* ----------+-----------+------------
|
|
|
|
* T | I | T
|
|
|
|
* F | I | F
|
|
|
|
* I | I | T
|
|
|
|
*
|
2013-08-11 07:19:33 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:07:08 +08:00
|
|
|
* @returns {Boolean}
|
2013-08-11 07:19:33 +08:00
|
|
|
*/
|
|
|
|
isListening: function() {
|
2013-12-10 02:38:01 +08:00
|
|
|
return this._getCache(LISTENING, this._isListening);
|
2013-08-11 07:19:33 +08:00
|
|
|
},
|
|
|
|
_isListening: function() {
|
|
|
|
var listening = this.getListening(),
|
|
|
|
parent = this.getParent();
|
|
|
|
|
2013-12-10 02:07:08 +08:00
|
|
|
// the following conditions are a simplification of the truth table above.
|
|
|
|
// please modify carefully
|
|
|
|
if (listening === 'inherit') {
|
|
|
|
if (parent) {
|
|
|
|
return parent.isListening();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return listening;
|
2013-08-11 07:19:33 +08:00
|
|
|
}
|
2013-12-10 02:07:08 +08:00
|
|
|
},
|
|
|
|
/**
|
2013-12-11 23:46:49 +08:00
|
|
|
* determine if node is visible by taking into account ancestors.
|
|
|
|
*
|
|
|
|
* Parent | Self | isVisible
|
2015-05-04 17:02:16 +08:00
|
|
|
* visible | visible |
|
2013-12-11 23:46:49 +08:00
|
|
|
* ----------+-----------+------------
|
2015-05-04 17:02:16 +08:00
|
|
|
* T | T | T
|
2013-12-11 23:46:49 +08:00
|
|
|
* T | F | F
|
2015-05-04 17:02:16 +08:00
|
|
|
* F | T | T
|
2013-12-11 23:46:49 +08:00
|
|
|
* F | F | F
|
|
|
|
* ----------+-----------+------------
|
|
|
|
* T | I | T
|
|
|
|
* F | I | F
|
|
|
|
* I | I | T
|
|
|
|
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Boolean}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
2013-08-11 07:19:33 +08:00
|
|
|
isVisible: function() {
|
2013-12-10 02:38:01 +08:00
|
|
|
return this._getCache(VISIBLE, this._isVisible);
|
2013-08-10 14:00:35 +08:00
|
|
|
},
|
2013-08-11 07:19:33 +08:00
|
|
|
_isVisible: function() {
|
|
|
|
var visible = this.getVisible(),
|
2013-03-15 23:33:05 +08:00
|
|
|
parent = this.getParent();
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-12-11 23:46:49 +08:00
|
|
|
// the following conditions are a simplification of the truth table above.
|
|
|
|
// please modify carefully
|
|
|
|
if (visible === 'inherit') {
|
|
|
|
if (parent) {
|
|
|
|
return parent.isVisible();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return true;
|
|
|
|
}
|
2012-03-07 13:45:48 +08:00
|
|
|
}
|
2013-12-11 23:46:49 +08:00
|
|
|
else {
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* determine if listening is enabled by taking into account descendants. If self or any children
|
2013-12-30 06:07:58 +08:00
|
|
|
* have _isListeningEnabled set to true, then self also has listening enabled.
|
2013-12-11 23:46:49 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-11 23:46:49 +08:00
|
|
|
* @returns {Boolean}
|
|
|
|
*/
|
2014-01-22 06:24:36 +08:00
|
|
|
shouldDrawHit: function(canvas) {
|
2013-12-11 23:46:49 +08:00
|
|
|
var layer = this.getLayer();
|
2015-05-04 17:02:16 +08:00
|
|
|
return (canvas && canvas.isCache) || (layer && layer.hitGraphEnabled())
|
2015-01-21 11:29:33 +08:00
|
|
|
&& this.isListening() && this.isVisible();
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* show node
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @returns {Konva.Node}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
show: function() {
|
|
|
|
this.setVisible(true);
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* hide node. Hidden nodes are no longer detectable
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @returns {Konva.Node}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
hide: function() {
|
|
|
|
this.setVisible(false);
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
2012-11-27 11:12:02 +08:00
|
|
|
* get zIndex relative to the node's siblings who share the same parent
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Integer}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
getZIndex: function() {
|
2013-03-15 23:33:05 +08:00
|
|
|
return this.index || 0;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get absolute z-index which takes into account sibling
|
2012-11-27 11:12:02 +08:00
|
|
|
* and ancestor indices
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Integer}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
getAbsoluteZIndex: function() {
|
2014-01-03 15:03:27 +08:00
|
|
|
var depth = this.getDepth(),
|
2013-03-24 13:56:22 +08:00
|
|
|
that = this,
|
|
|
|
index = 0,
|
|
|
|
nodes, len, n, child;
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2012-11-14 15:22:56 +08:00
|
|
|
function addChildren(children) {
|
2013-03-24 13:56:22 +08:00
|
|
|
nodes = [];
|
|
|
|
len = children.length;
|
|
|
|
for(n = 0; n < len; n++) {
|
|
|
|
child = children[n];
|
2012-11-14 15:22:56 +08:00
|
|
|
index++;
|
|
|
|
|
2013-03-24 13:56:22 +08:00
|
|
|
if(child.nodeType !== SHAPE) {
|
2013-05-20 12:07:43 +08:00
|
|
|
nodes = nodes.concat(child.getChildren().toArray());
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if(child._id === that._id) {
|
|
|
|
n = len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-03 15:03:27 +08:00
|
|
|
if(nodes.length > 0 && nodes[0].getDepth() <= depth) {
|
2012-11-14 15:22:56 +08:00
|
|
|
addChildren(nodes);
|
|
|
|
}
|
|
|
|
}
|
2013-08-12 11:34:54 +08:00
|
|
|
if(that.nodeType !== UPPER_STAGE) {
|
2012-11-14 15:22:56 +08:00
|
|
|
addChildren(that.getStage().getChildren());
|
|
|
|
}
|
|
|
|
|
|
|
|
return index;
|
|
|
|
},
|
|
|
|
/**
|
2014-04-04 11:17:09 +08:00
|
|
|
* get node depth in node tree. Returns an integer.
|
2014-01-03 15:03:27 +08:00
|
|
|
* e.g. Stage depth will always be 0. Layers will always be 1. Groups and Shapes will always
|
2012-11-27 11:12:02 +08:00
|
|
|
* be >= 2
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Integer}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
2014-01-03 15:03:27 +08:00
|
|
|
getDepth: function() {
|
|
|
|
var depth = 0,
|
2013-03-24 13:56:22 +08:00
|
|
|
parent = this.parent;
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2012-11-14 15:22:56 +08:00
|
|
|
while(parent) {
|
2014-01-03 15:03:27 +08:00
|
|
|
depth++;
|
2012-11-14 15:22:56 +08:00
|
|
|
parent = parent.parent;
|
|
|
|
}
|
2014-01-03 15:03:27 +08:00
|
|
|
return depth;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
2013-12-02 15:47:24 +08:00
|
|
|
setPosition: function(pos) {
|
2013-05-08 15:18:29 +08:00
|
|
|
this.setX(pos.x);
|
|
|
|
this.setY(pos.y);
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
getPosition: function() {
|
|
|
|
return {
|
2013-03-15 23:33:05 +08:00
|
|
|
x: this.getX(),
|
|
|
|
y: this.getY()
|
2012-11-14 15:22:56 +08:00
|
|
|
};
|
|
|
|
},
|
|
|
|
/**
|
2012-11-27 11:12:02 +08:00
|
|
|
* get absolute position relative to the top left corner of the stage container div
|
2015-12-23 10:18:36 +08:00
|
|
|
* or relative to passed node
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-12-23 10:18:36 +08:00
|
|
|
* @param {Object} [top] optional parent node
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Object}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
2015-12-23 10:18:36 +08:00
|
|
|
getAbsolutePosition: function(top) {
|
|
|
|
var absoluteMatrix = this.getAbsoluteTransform(top).getMatrix(),
|
2015-01-27 15:07:51 +08:00
|
|
|
absoluteTransform = new Konva.Transform(),
|
2014-01-11 14:09:22 +08:00
|
|
|
offset = this.offset();
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-08-25 15:34:49 +08:00
|
|
|
// clone the matrix array
|
|
|
|
absoluteTransform.m = absoluteMatrix.slice();
|
2014-01-11 14:09:22 +08:00
|
|
|
absoluteTransform.translate(offset.x, offset.y);
|
2013-08-25 15:34:49 +08:00
|
|
|
|
2013-08-12 18:00:08 +08:00
|
|
|
return absoluteTransform.getTranslation();
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* set absolute position
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-02 15:47:24 +08:00
|
|
|
* @param {Object} pos
|
|
|
|
* @param {Number} pos.x
|
|
|
|
* @param {Number} pos.y
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Node}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
2013-12-02 15:47:24 +08:00
|
|
|
setAbsolutePosition: function(pos) {
|
2013-12-29 05:25:15 +08:00
|
|
|
var origTrans = this._clearTransform(),
|
2013-03-24 13:56:22 +08:00
|
|
|
it;
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2012-11-14 15:22:56 +08:00
|
|
|
// don't clear translation
|
2013-12-29 05:25:15 +08:00
|
|
|
this.attrs.x = origTrans.x;
|
|
|
|
this.attrs.y = origTrans.y;
|
|
|
|
delete origTrans.x;
|
|
|
|
delete origTrans.y;
|
2012-11-14 15:22:56 +08:00
|
|
|
|
|
|
|
// unravel transform
|
2013-03-24 13:56:22 +08:00
|
|
|
it = this.getAbsoluteTransform();
|
2012-11-14 15:22:56 +08:00
|
|
|
|
|
|
|
it.invert();
|
|
|
|
it.translate(pos.x, pos.y);
|
|
|
|
pos = {
|
|
|
|
x: this.attrs.x + it.getTranslation().x,
|
|
|
|
y: this.attrs.y + it.getTranslation().y
|
|
|
|
};
|
|
|
|
|
2015-05-04 17:02:16 +08:00
|
|
|
this.setPosition({x: pos.x, y: pos.y});
|
2013-12-29 05:25:15 +08:00
|
|
|
this._setTransform(origTrans);
|
|
|
|
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
2013-08-12 18:00:08 +08:00
|
|
|
_setTransform: function(trans) {
|
|
|
|
var key;
|
|
|
|
|
|
|
|
for(key in trans) {
|
|
|
|
this.attrs[key] = trans[key];
|
|
|
|
}
|
|
|
|
|
|
|
|
this._clearCache(TRANSFORM);
|
2013-12-10 02:07:08 +08:00
|
|
|
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
|
2013-08-12 18:00:08 +08:00
|
|
|
},
|
|
|
|
_clearTransform: function() {
|
|
|
|
var trans = {
|
|
|
|
x: this.getX(),
|
|
|
|
y: this.getY(),
|
|
|
|
rotation: this.getRotation(),
|
|
|
|
scaleX: this.getScaleX(),
|
|
|
|
scaleY: this.getScaleY(),
|
2014-01-11 14:09:22 +08:00
|
|
|
offsetX: this.getOffsetX(),
|
|
|
|
offsetY: this.getOffsetY(),
|
2013-08-12 18:00:08 +08:00
|
|
|
skewX: this.getSkewX(),
|
|
|
|
skewY: this.getSkewY()
|
|
|
|
};
|
|
|
|
|
|
|
|
this.attrs.x = 0;
|
|
|
|
this.attrs.y = 0;
|
|
|
|
this.attrs.rotation = 0;
|
|
|
|
this.attrs.scaleX = 1;
|
|
|
|
this.attrs.scaleY = 1;
|
2014-01-11 14:09:22 +08:00
|
|
|
this.attrs.offsetX = 0;
|
|
|
|
this.attrs.offsetY = 0;
|
2013-08-12 18:00:08 +08:00
|
|
|
this.attrs.skewX = 0;
|
|
|
|
this.attrs.skewY = 0;
|
|
|
|
|
|
|
|
this._clearCache(TRANSFORM);
|
2013-12-10 02:07:08 +08:00
|
|
|
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
|
2013-08-12 18:00:08 +08:00
|
|
|
|
2013-12-29 05:25:15 +08:00
|
|
|
// return original transform
|
2013-08-12 18:00:08 +08:00
|
|
|
return trans;
|
|
|
|
},
|
2012-11-14 15:22:56 +08:00
|
|
|
/**
|
2012-11-27 11:12:02 +08:00
|
|
|
* move node by an amount relative to its current position
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-02 15:47:24 +08:00
|
|
|
* @param {Object} change
|
|
|
|
* @param {Number} change.x
|
|
|
|
* @param {Number} change.y
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Node}
|
2013-05-18 02:46:06 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // move node in x direction by 1px and y direction by 2px
|
|
|
|
* node.move({
|
|
|
|
* x: 1,
|
|
|
|
* y: 2)
|
2013-05-18 06:09:57 +08:00
|
|
|
* });
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
2013-12-02 15:47:24 +08:00
|
|
|
move: function(change) {
|
|
|
|
var changeX = change.x,
|
|
|
|
changeY = change.y,
|
2013-03-24 13:56:22 +08:00
|
|
|
x = this.getX(),
|
|
|
|
y = this.getY();
|
2012-11-14 15:22:56 +08:00
|
|
|
|
2013-12-02 15:47:24 +08:00
|
|
|
if(changeX !== undefined) {
|
|
|
|
x += changeX;
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
|
|
|
|
2013-12-02 15:47:24 +08:00
|
|
|
if(changeY !== undefined) {
|
|
|
|
y += changeY;
|
2012-09-27 03:50:08 +08:00
|
|
|
}
|
|
|
|
|
2015-05-04 17:02:16 +08:00
|
|
|
this.setPosition({x: x, y: y});
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
2014-03-22 15:13:05 +08:00
|
|
|
_eachAncestorReverse: function(func, top) {
|
2013-07-22 11:14:09 +08:00
|
|
|
var family = [],
|
2013-03-24 13:56:22 +08:00
|
|
|
parent = this.getParent(),
|
|
|
|
len, n;
|
2012-12-31 15:14:23 +08:00
|
|
|
|
2014-03-22 15:13:05 +08:00
|
|
|
// if top node is defined, and this node is top node,
|
|
|
|
// there's no need to build a family tree. just execute
|
|
|
|
// func with this because it will be the only node
|
|
|
|
if (top && top._id === this._id) {
|
|
|
|
func(this);
|
|
|
|
return true;
|
2012-12-31 17:47:49 +08:00
|
|
|
}
|
2014-03-22 15:13:05 +08:00
|
|
|
|
|
|
|
family.unshift(this);
|
|
|
|
|
|
|
|
while(parent && (!top || parent._id !== top._id)) {
|
2012-12-31 15:14:23 +08:00
|
|
|
family.unshift(parent);
|
|
|
|
parent = parent.parent;
|
|
|
|
}
|
|
|
|
|
2013-03-24 13:56:22 +08:00
|
|
|
len = family.length;
|
|
|
|
for(n = 0; n < len; n++) {
|
2012-12-31 15:48:46 +08:00
|
|
|
func(family[n]);
|
2012-12-31 15:14:23 +08:00
|
|
|
}
|
|
|
|
},
|
2012-11-14 15:22:56 +08:00
|
|
|
/**
|
2014-01-07 13:37:46 +08:00
|
|
|
* rotate node by an amount in degrees relative to its current rotation
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2012-11-14 15:22:56 +08:00
|
|
|
* @param {Number} theta
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Node}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
rotate: function(theta) {
|
|
|
|
this.setRotation(this.getRotation() + theta);
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* move node to the top of its siblings
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Boolean}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
moveToTop: function() {
|
2014-03-01 20:23:37 +08:00
|
|
|
if (!this.parent) {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Util.warn('Node has no parent. moveToTop function is ignored.');
|
2015-05-04 17:02:16 +08:00
|
|
|
return false;
|
2014-03-01 20:23:37 +08:00
|
|
|
}
|
2012-11-14 15:22:56 +08:00
|
|
|
var index = this.index;
|
|
|
|
this.parent.children.splice(index, 1);
|
|
|
|
this.parent.children.push(this);
|
|
|
|
this.parent._setChildrenIndices();
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* move node up
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2015-04-07 16:03:08 +08:00
|
|
|
* @returns {Boolean} flag is moved or not
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
moveUp: function() {
|
2014-03-01 20:23:37 +08:00
|
|
|
if (!this.parent) {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Util.warn('Node has no parent. moveUp function is ignored.');
|
2015-05-04 17:02:16 +08:00
|
|
|
return false;
|
2014-03-01 20:23:37 +08:00
|
|
|
}
|
2013-03-24 13:56:22 +08:00
|
|
|
var index = this.index,
|
|
|
|
len = this.parent.getChildren().length;
|
2012-11-14 15:22:56 +08:00
|
|
|
if(index < len - 1) {
|
|
|
|
this.parent.children.splice(index, 1);
|
|
|
|
this.parent.children.splice(index + 1, 0, this);
|
|
|
|
this.parent._setChildrenIndices();
|
|
|
|
return true;
|
|
|
|
}
|
2013-06-07 13:45:31 +08:00
|
|
|
return false;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* move node down
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Boolean}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
moveDown: function() {
|
2014-03-01 20:23:37 +08:00
|
|
|
if (!this.parent) {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Util.warn('Node has no parent. moveDown function is ignored.');
|
2015-05-04 17:02:16 +08:00
|
|
|
return false;
|
2014-03-01 20:23:37 +08:00
|
|
|
}
|
2012-11-14 15:22:56 +08:00
|
|
|
var index = this.index;
|
|
|
|
if(index > 0) {
|
|
|
|
this.parent.children.splice(index, 1);
|
|
|
|
this.parent.children.splice(index - 1, 0, this);
|
|
|
|
this.parent._setChildrenIndices();
|
|
|
|
return true;
|
|
|
|
}
|
2013-06-07 13:45:31 +08:00
|
|
|
return false;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* move node to the bottom of its siblings
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Boolean}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
moveToBottom: function() {
|
2014-03-01 20:23:37 +08:00
|
|
|
if (!this.parent) {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Util.warn('Node has no parent. moveToBottom function is ignored.');
|
2015-05-04 17:02:16 +08:00
|
|
|
return false;
|
2014-03-01 20:23:37 +08:00
|
|
|
}
|
2012-11-14 15:22:56 +08:00
|
|
|
var index = this.index;
|
|
|
|
if(index > 0) {
|
|
|
|
this.parent.children.splice(index, 1);
|
|
|
|
this.parent.children.unshift(this);
|
|
|
|
this.parent._setChildrenIndices();
|
|
|
|
return true;
|
|
|
|
}
|
2013-06-07 13:45:31 +08:00
|
|
|
return false;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
2012-11-27 11:12:02 +08:00
|
|
|
* set zIndex relative to siblings
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2012-11-14 15:22:56 +08:00
|
|
|
* @param {Integer} zIndex
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Node}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
setZIndex: function(zIndex) {
|
2014-03-01 20:23:37 +08:00
|
|
|
if (!this.parent) {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Util.warn('Node has no parent. zIndex parameter is ignored.');
|
2015-05-04 17:02:16 +08:00
|
|
|
return false;
|
2014-03-01 20:23:37 +08:00
|
|
|
}
|
2012-11-14 15:22:56 +08:00
|
|
|
var index = this.index;
|
|
|
|
this.parent.children.splice(index, 1);
|
|
|
|
this.parent.children.splice(zIndex, 0, this);
|
|
|
|
this.parent._setChildrenIndices();
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get absolute opacity
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Number}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
getAbsoluteOpacity: function() {
|
2013-08-11 02:55:52 +08:00
|
|
|
return this._getCache(ABSOLUTE_OPACITY, this._getAbsoluteOpacity);
|
|
|
|
},
|
|
|
|
_getAbsoluteOpacity: function() {
|
2012-11-14 15:22:56 +08:00
|
|
|
var absOpacity = this.getOpacity();
|
2016-12-13 20:01:51 +08:00
|
|
|
var parent = this.getParent();
|
|
|
|
if(parent && !parent._isUnderCache) {
|
2012-11-14 15:22:56 +08:00
|
|
|
absOpacity *= this.getParent().getAbsoluteOpacity();
|
|
|
|
}
|
|
|
|
return absOpacity;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* move node to another container
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2012-11-14 15:22:56 +08:00
|
|
|
* @param {Container} newContainer
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Node}
|
2013-05-18 02:46:06 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // move node from current layer into layer2
|
2013-05-18 02:46:06 +08:00
|
|
|
* node.moveTo(layer2);
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
moveTo: function(newContainer) {
|
2014-08-19 19:48:20 +08:00
|
|
|
// do nothing if new container is already parent
|
2014-07-28 09:37:50 +08:00
|
|
|
if (this.getParent() !== newContainer) {
|
2016-11-11 06:41:31 +08:00
|
|
|
// this.remove my be overrided by drag and drop
|
|
|
|
// buy we need original
|
|
|
|
(this.__originalRemove || this.remove).call(this);
|
2014-07-28 09:37:50 +08:00
|
|
|
newContainer.add(this);
|
|
|
|
}
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
2012-11-27 11:12:02 +08:00
|
|
|
* convert Node into an object for serialization. Returns an object.
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Object}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
toObject: function() {
|
2015-04-13 08:17:32 +08:00
|
|
|
var obj = {},
|
2013-03-24 13:56:22 +08:00
|
|
|
attrs = this.getAttrs(),
|
2013-11-28 00:47:52 +08:00
|
|
|
key, val, getter, defaultValue;
|
2012-04-29 03:55:18 +08:00
|
|
|
|
2012-11-14 15:22:56 +08:00
|
|
|
obj.attrs = {};
|
|
|
|
|
2013-03-24 13:56:22 +08:00
|
|
|
for(key in attrs) {
|
|
|
|
val = attrs[key];
|
2015-04-13 08:17:32 +08:00
|
|
|
getter = this[key];
|
|
|
|
// remove attr value so that we can extract the default value from the getter
|
|
|
|
delete attrs[key];
|
|
|
|
defaultValue = getter ? getter.call(this) : null;
|
|
|
|
// restore attr value
|
|
|
|
attrs[key] = val;
|
|
|
|
if (defaultValue !== val) {
|
|
|
|
obj.attrs[key] = val;
|
2012-05-13 06:15:42 +08:00
|
|
|
}
|
2012-04-29 03:55:18 +08:00
|
|
|
}
|
2012-11-14 15:22:56 +08:00
|
|
|
|
2013-05-21 12:58:57 +08:00
|
|
|
obj.className = this.getClassName();
|
2016-07-09 21:54:28 +08:00
|
|
|
return Konva.Util._prepareToStringify(obj);
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
2012-11-27 11:12:02 +08:00
|
|
|
/**
|
|
|
|
* convert Node into a JSON string. Returns a JSON string.
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {String}}
|
2012-11-27 11:12:02 +08:00
|
|
|
*/
|
2012-11-14 15:22:56 +08:00
|
|
|
toJSON: function() {
|
|
|
|
return JSON.stringify(this.toObject());
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get parent container
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @returns {Konva.Node}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
getParent: function() {
|
|
|
|
return this.parent;
|
|
|
|
},
|
2015-12-25 22:35:19 +08:00
|
|
|
/**
|
|
|
|
* get all ancestros (parent then parent of the parent, etc) of the node
|
|
|
|
* @method
|
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @param {String} [selector] selector for search
|
|
|
|
* @param {Boolean} [includeSelf] show we think that node is ancestro itself?
|
|
|
|
* @param {Konva.Node} [stopNode] optional node where we need to stop searching (one of ancestors)
|
|
|
|
* @returns {Array} [ancestors]
|
|
|
|
* @example
|
|
|
|
* // get one of the parent group
|
|
|
|
* var parentGroups = node.findAncestors('Group');
|
|
|
|
*/
|
|
|
|
findAncestors: function(selector, includeSelf, stopNode) {
|
2015-11-22 11:44:33 +08:00
|
|
|
var res = [];
|
2015-12-25 22:35:19 +08:00
|
|
|
|
|
|
|
if (includeSelf && this._isMatch(selector)) {
|
2015-11-22 11:44:33 +08:00
|
|
|
res.push(this);
|
|
|
|
}
|
2015-12-25 22:35:19 +08:00
|
|
|
var ancestor = this.parent;
|
|
|
|
while(ancestor) {
|
|
|
|
if (ancestor === stopNode) {
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
if (ancestor._isMatch(selector)) {
|
|
|
|
res.push(ancestor);
|
|
|
|
}
|
|
|
|
ancestor = ancestor.parent;
|
2015-11-22 11:44:33 +08:00
|
|
|
}
|
2015-12-25 22:35:19 +08:00
|
|
|
return res;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get ancestor (parent or parent of the parent, etc) of the node that match passed selector
|
|
|
|
* @method
|
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @param {String} [selector] selector for search
|
|
|
|
* @param {Boolean} [includeSelf] show we think that node is ancestro itself?
|
|
|
|
* @param {Konva.Node} [stopNode] optional node where we need to stop searching (one of ancestors)
|
|
|
|
* @returns {Konva.Node} ancestor
|
|
|
|
* @example
|
|
|
|
* // get one of the parent group
|
|
|
|
* var group = node.findAncestors('.mygroup');
|
|
|
|
*/
|
|
|
|
findAncestor: function(selector, includeSelf, stopNode) {
|
|
|
|
return this.findAncestors(selector, includeSelf, stopNode)[0];
|
2015-11-22 11:44:33 +08:00
|
|
|
},
|
2015-11-22 23:26:04 +08:00
|
|
|
// is current node match passed selector?
|
2015-11-22 11:44:33 +08:00
|
|
|
_isMatch: function(selector) {
|
2015-12-25 22:35:19 +08:00
|
|
|
if (!selector) {
|
|
|
|
return false;
|
|
|
|
}
|
2015-11-22 11:44:33 +08:00
|
|
|
var selectorArr = selector.replace(/ /g, '').split(','),
|
|
|
|
len = selectorArr.length,
|
|
|
|
n, sel;
|
|
|
|
|
|
|
|
for (n = 0; n < len; n++) {
|
|
|
|
sel = selectorArr[n];
|
|
|
|
if (!Konva.Util.isValidSelector(sel)) {
|
|
|
|
Konva.Util.warn('Selector "' + sel + '" is invalid. Allowed selectors examples are "#foo", ".bar" or "Group".');
|
|
|
|
Konva.Util.warn('If you have a custom shape with such className, please change it to start with upper letter like "Triangle".');
|
|
|
|
Konva.Util.warn('Konva is awesome, right?');
|
|
|
|
}
|
|
|
|
// id selector
|
|
|
|
if(sel.charAt(0) === '#') {
|
|
|
|
if (this.id() === sel.slice(1)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// name selector
|
|
|
|
else if(sel.charAt(0) === '.') {
|
|
|
|
if (this.hasName(sel.slice(1))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else if (this._get(sel).length !== 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
2012-11-14 15:22:56 +08:00
|
|
|
/**
|
2012-11-27 11:12:02 +08:00
|
|
|
* get layer ancestor
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @returns {Konva.Layer}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
getLayer: function() {
|
2013-11-28 00:24:47 +08:00
|
|
|
var parent = this.getParent();
|
|
|
|
return parent ? parent.getLayer() : null;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
2012-11-27 11:12:02 +08:00
|
|
|
* get stage ancestor
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @returns {Konva.Stage}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
getStage: function() {
|
2013-08-12 11:34:54 +08:00
|
|
|
return this._getCache(STAGE, this._getStage);
|
|
|
|
},
|
|
|
|
_getStage: function() {
|
|
|
|
var parent = this.getParent();
|
|
|
|
if(parent) {
|
|
|
|
return parent.getStage();
|
2012-09-26 04:38:36 +08:00
|
|
|
}
|
2012-11-14 15:22:56 +08:00
|
|
|
else {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
2013-03-22 10:43:17 +08:00
|
|
|
* fire event
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-03-22 10:43:17 +08:00
|
|
|
* @param {String} eventType event type. can be a regular event, like click, mouseover, or mouseout, or it can be a custom event, like myCustomEvent
|
2014-08-19 19:27:46 +08:00
|
|
|
* @param {Event} [evt] event object
|
2014-01-13 00:46:18 +08:00
|
|
|
* @param {Boolean} [bubble] setting the value to false, or leaving it undefined, will result in the event
|
2013-05-13 23:56:09 +08:00
|
|
|
* not bubbling. Setting the value to true will result in the event bubbling.
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Node}
|
2013-05-18 02:46:06 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // manually fire click event
|
|
|
|
* node.fire('click');
|
2013-05-18 02:46:06 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // fire custom event
|
|
|
|
* node.fire('foo');
|
2013-05-18 02:46:06 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // fire custom event with custom event object
|
|
|
|
* node.fire('foo', {
|
|
|
|
* bar: 10
|
|
|
|
* });
|
2013-05-18 02:46:06 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // fire click event that bubbles
|
2013-05-19 01:40:05 +08:00
|
|
|
* node.fire('click', null, true);
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
2013-05-13 23:56:09 +08:00
|
|
|
fire: function(eventType, evt, bubble) {
|
2016-01-04 08:24:27 +08:00
|
|
|
evt = evt || {};
|
|
|
|
evt.target = evt.target || this;
|
2013-03-22 10:43:17 +08:00
|
|
|
// bubble
|
2013-05-13 23:56:09 +08:00
|
|
|
if (bubble) {
|
2015-11-22 11:44:33 +08:00
|
|
|
this._fireAndBubble(eventType, evt);
|
2013-05-13 23:56:09 +08:00
|
|
|
}
|
|
|
|
// no bubble
|
2013-03-22 10:43:17 +08:00
|
|
|
else {
|
2015-11-22 11:44:33 +08:00
|
|
|
this._fire(eventType, evt);
|
2013-03-22 10:43:17 +08:00
|
|
|
}
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get absolute transform of the node which takes into
|
2012-11-27 11:12:02 +08:00
|
|
|
* account its ancestor transforms
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @returns {Konva.Transform}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
2014-03-22 15:13:05 +08:00
|
|
|
getAbsoluteTransform: function(top) {
|
|
|
|
// if using an argument, we can't cache the result.
|
|
|
|
if (top) {
|
2014-08-19 19:27:46 +08:00
|
|
|
return this._getAbsoluteTransform(top);
|
2014-03-22 15:13:05 +08:00
|
|
|
}
|
|
|
|
// if no argument, we can cache the result
|
|
|
|
else {
|
|
|
|
return this._getCache(ABSOLUTE_TRANSFORM, this._getAbsoluteTransform);
|
|
|
|
}
|
2013-08-10 15:58:53 +08:00
|
|
|
},
|
2014-03-22 15:13:05 +08:00
|
|
|
_getAbsoluteTransform: function(top) {
|
2015-01-27 15:07:51 +08:00
|
|
|
var at = new Konva.Transform(),
|
2013-12-30 13:40:37 +08:00
|
|
|
transformsEnabled, trans;
|
2012-11-14 15:22:56 +08:00
|
|
|
|
2013-12-30 13:40:37 +08:00
|
|
|
// start with stage and traverse downwards to self
|
2012-12-31 17:47:49 +08:00
|
|
|
this._eachAncestorReverse(function(node) {
|
2013-12-30 13:40:37 +08:00
|
|
|
transformsEnabled = node.transformsEnabled();
|
|
|
|
trans = node.getTransform();
|
|
|
|
|
2014-02-27 08:49:18 +08:00
|
|
|
if (transformsEnabled === 'all') {
|
2013-12-30 13:40:37 +08:00
|
|
|
at.multiply(trans);
|
|
|
|
}
|
|
|
|
else if (transformsEnabled === 'position') {
|
|
|
|
at.translate(node.x(), node.y());
|
2013-12-12 14:34:02 +08:00
|
|
|
}
|
2014-03-22 15:13:05 +08:00
|
|
|
}, top);
|
2013-12-30 13:40:37 +08:00
|
|
|
return at;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
2016-04-15 11:52:45 +08:00
|
|
|
/**
|
|
|
|
* get absolute scale of the node which takes into
|
|
|
|
* account its ancestor scales
|
|
|
|
* @method
|
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @returns {Konva.Transform}
|
|
|
|
*/
|
|
|
|
getAbsoluteScale: function(top) {
|
|
|
|
// if using an argument, we can't cache the result.
|
|
|
|
if (top) {
|
|
|
|
return this._getAbsoluteTransform(top);
|
|
|
|
}
|
|
|
|
// if no argument, we can cache the result
|
|
|
|
else {
|
|
|
|
return this._getCache(ABSOLUTE_SCALE, this._getAbsoluteScale);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_getAbsoluteScale: function(top) {
|
2016-12-15 01:11:54 +08:00
|
|
|
// this is special logic for caching with some shapes with shadow
|
|
|
|
var parent = this;
|
|
|
|
while(parent) {
|
|
|
|
if (parent._isUnderCache) {
|
|
|
|
top = parent;
|
|
|
|
}
|
|
|
|
parent = parent.getParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-15 11:52:45 +08:00
|
|
|
var scaleX = 1, scaleY = 1;
|
|
|
|
|
|
|
|
// start with stage and traverse downwards to self
|
|
|
|
this._eachAncestorReverse(function(node) {
|
|
|
|
scaleX *= node.scaleX();
|
|
|
|
scaleY *= node.scaleY();
|
|
|
|
}, top);
|
|
|
|
return {
|
|
|
|
x: scaleX,
|
|
|
|
y: scaleY
|
|
|
|
};
|
|
|
|
},
|
2013-12-10 02:33:31 +08:00
|
|
|
/**
|
|
|
|
* get transform of the node
|
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @returns {Konva.Transform}
|
2013-12-10 02:33:31 +08:00
|
|
|
*/
|
|
|
|
getTransform: function() {
|
|
|
|
return this._getCache(TRANSFORM, this._getTransform);
|
|
|
|
},
|
2013-08-10 13:23:27 +08:00
|
|
|
_getTransform: function() {
|
2015-01-27 15:07:51 +08:00
|
|
|
var m = new Konva.Transform(),
|
2013-07-22 11:14:09 +08:00
|
|
|
x = this.getX(),
|
|
|
|
y = this.getY(),
|
2015-01-27 15:07:51 +08:00
|
|
|
rotation = Konva.getAngle(this.getRotation()),
|
2013-07-22 11:14:09 +08:00
|
|
|
scaleX = this.getScaleX(),
|
|
|
|
scaleY = this.getScaleY(),
|
|
|
|
skewX = this.getSkewX(),
|
|
|
|
skewY = this.getSkewY(),
|
2014-01-11 14:09:22 +08:00
|
|
|
offsetX = this.getOffsetX(),
|
|
|
|
offsetY = this.getOffsetY();
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2012-11-14 16:07:59 +08:00
|
|
|
if(x !== 0 || y !== 0) {
|
|
|
|
m.translate(x, y);
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
2012-11-14 16:07:59 +08:00
|
|
|
if(rotation !== 0) {
|
|
|
|
m.rotate(rotation);
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
2013-05-02 01:56:01 +08:00
|
|
|
if(skewX !== 0 || skewY !== 0) {
|
|
|
|
m.skew(skewX, skewY);
|
|
|
|
}
|
2012-11-14 16:07:59 +08:00
|
|
|
if(scaleX !== 1 || scaleY !== 1) {
|
|
|
|
m.scale(scaleX, scaleY);
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
2014-01-11 14:09:22 +08:00
|
|
|
if(offsetX !== 0 || offsetY !== 0) {
|
|
|
|
m.translate(-1 * offsetX, -1 * offsetY);
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2012-11-14 15:22:56 +08:00
|
|
|
return m;
|
|
|
|
},
|
|
|
|
/**
|
2013-05-18 11:56:24 +08:00
|
|
|
* clone node. Returns a new Node instance with identical attributes. You can also override
|
|
|
|
* the node properties with an object literal, enabling you to use an existing node as a template
|
|
|
|
* for another node
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2014-08-19 19:27:46 +08:00
|
|
|
* @param {Object} obj override attrs
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Node}
|
2013-05-18 02:46:06 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // simple clone
|
|
|
|
* var clone = node.clone();
|
2013-05-18 02:46:06 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // clone a node and override the x position
|
|
|
|
* var clone = rect.clone({
|
|
|
|
* x: 5
|
2013-05-18 02:46:06 +08:00
|
|
|
* });
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
clone: function(obj) {
|
|
|
|
// instantiate new node
|
2015-04-27 12:20:55 +08:00
|
|
|
var attrs = Konva.Util.cloneObject(this.attrs),
|
2013-03-24 13:56:22 +08:00
|
|
|
key, allListeners, len, n, listener;
|
2014-03-02 21:51:35 +08:00
|
|
|
// filter black attrs
|
|
|
|
for (var i in CLONE_BLACK_LIST) {
|
|
|
|
var blockAttr = CLONE_BLACK_LIST[i];
|
|
|
|
delete attrs[blockAttr];
|
|
|
|
}
|
2014-03-07 22:51:26 +08:00
|
|
|
// apply attr overrides
|
|
|
|
for (key in obj) {
|
|
|
|
attrs[key] = obj[key];
|
|
|
|
}
|
|
|
|
|
2015-04-26 16:20:11 +08:00
|
|
|
var node = new this.constructor(attrs);
|
2013-03-24 11:15:49 +08:00
|
|
|
// copy over listeners
|
2013-03-24 13:56:22 +08:00
|
|
|
for(key in this.eventListeners) {
|
|
|
|
allListeners = this.eventListeners[key];
|
|
|
|
len = allListeners.length;
|
|
|
|
for(n = 0; n < len; n++) {
|
|
|
|
listener = allListeners[n];
|
2012-11-14 15:22:56 +08:00
|
|
|
/*
|
2015-01-27 15:07:51 +08:00
|
|
|
* don't include konva namespaced listeners because
|
2012-11-14 15:22:56 +08:00
|
|
|
* these are generated by the constructors
|
|
|
|
*/
|
2015-01-30 05:25:49 +08:00
|
|
|
if(listener.name.indexOf(KONVA) < 0) {
|
2012-11-14 15:22:56 +08:00
|
|
|
// if listeners array doesn't exist, then create it
|
|
|
|
if(!node.eventListeners[key]) {
|
|
|
|
node.eventListeners[key] = [];
|
|
|
|
}
|
|
|
|
node.eventListeners[key].push(listener);
|
|
|
|
}
|
2012-04-01 06:17:36 +08:00
|
|
|
}
|
|
|
|
}
|
2012-11-14 15:22:56 +08:00
|
|
|
return node;
|
|
|
|
},
|
2016-11-12 06:02:32 +08:00
|
|
|
_toKonvaCanvas: function(config) {
|
|
|
|
config = config || {};
|
|
|
|
|
|
|
|
var stage = this.getStage(),
|
|
|
|
x = config.x || 0,
|
|
|
|
y = config.y || 0,
|
|
|
|
pixelRatio = config.pixelRatio || 1,
|
|
|
|
canvas = new Konva.SceneCanvas({
|
|
|
|
width: config.width || this.getWidth() || (stage ? stage.getWidth() : 0),
|
|
|
|
height: config.height || this.getHeight() || (stage ? stage.getHeight() : 0),
|
|
|
|
pixelRatio: pixelRatio
|
|
|
|
}),
|
|
|
|
context = canvas.getContext();
|
|
|
|
|
|
|
|
context.save();
|
|
|
|
|
|
|
|
if(x || y) {
|
|
|
|
context.translate(-1 * x, -1 * y);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.drawScene(canvas);
|
|
|
|
context.restore();
|
|
|
|
|
|
|
|
return canvas;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* converts node into an canvas element.
|
|
|
|
* @method
|
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @param {Object} config
|
|
|
|
* @param {Function} config.callback function executed when the composite has completed
|
|
|
|
* @param {Number} [config.x] x position of canvas section
|
|
|
|
* @param {Number} [config.y] y position of canvas section
|
|
|
|
* @param {Number} [config.width] width of canvas section
|
|
|
|
* @param {Number} [config.height] height of canvas section
|
|
|
|
* @paremt {Number} [config.pixelRatio] pixelRatio of ouput image. Default is 1.
|
|
|
|
* @example
|
|
|
|
* var canvas = node.toCanvas();
|
|
|
|
*/
|
|
|
|
toCanvas: function(config) {
|
|
|
|
return this._toKonvaCanvas(config)._canvas;
|
|
|
|
},
|
2012-11-14 15:22:56 +08:00
|
|
|
/**
|
|
|
|
* Creates a composite data URL. If MIME type is not
|
|
|
|
* specified, then "image/png" will result. For "image/jpeg", specify a quality
|
|
|
|
* level as quality (range 0.0 - 1.0)
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2012-11-14 15:22:56 +08:00
|
|
|
* @param {Object} config
|
2012-12-17 12:52:07 +08:00
|
|
|
* @param {String} [config.mimeType] can be "image/png" or "image/jpeg".
|
2012-11-14 15:22:56 +08:00
|
|
|
* "image/png" is the default
|
2012-12-17 12:52:07 +08:00
|
|
|
* @param {Number} [config.x] x position of canvas section
|
|
|
|
* @param {Number} [config.y] y position of canvas section
|
|
|
|
* @param {Number} [config.width] width of canvas section
|
|
|
|
* @param {Number} [config.height] height of canvas section
|
2012-11-14 15:22:56 +08:00
|
|
|
* @param {Number} [config.quality] jpeg quality. If using an "image/jpeg" mimeType,
|
|
|
|
* you can specify the quality from 0 to 1, where 0 is very poor quality and 1
|
|
|
|
* is very high quality
|
2015-04-27 12:20:55 +08:00
|
|
|
* @paremt {Number} [config.pixelRatio] pixelRatio of ouput image url. Default is 1
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {String}
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
toDataURL: function(config) {
|
2013-06-02 13:03:02 +08:00
|
|
|
config = config || {};
|
2013-07-22 11:14:09 +08:00
|
|
|
var mimeType = config.mimeType || null,
|
2016-11-12 06:02:32 +08:00
|
|
|
quality = config.quality || null;
|
|
|
|
return this._toKonvaCanvas(config).toDataURL(mimeType, quality);
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* converts node into an image. Since the toImage
|
2012-11-27 11:12:02 +08:00
|
|
|
* method is asynchronous, a callback is required. toImage is most commonly used
|
|
|
|
* to cache complex drawings as an image so that they don't have to constantly be redrawn
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2012-11-14 15:22:56 +08:00
|
|
|
* @param {Object} config
|
2012-12-17 12:52:07 +08:00
|
|
|
* @param {Function} config.callback function executed when the composite has completed
|
|
|
|
* @param {String} [config.mimeType] can be "image/png" or "image/jpeg".
|
2012-11-14 15:22:56 +08:00
|
|
|
* "image/png" is the default
|
2012-12-17 12:52:07 +08:00
|
|
|
* @param {Number} [config.x] x position of canvas section
|
|
|
|
* @param {Number} [config.y] y position of canvas section
|
|
|
|
* @param {Number} [config.width] width of canvas section
|
|
|
|
* @param {Number} [config.height] height of canvas section
|
2012-11-14 15:22:56 +08:00
|
|
|
* @param {Number} [config.quality] jpeg quality. If using an "image/jpeg" mimeType,
|
|
|
|
* you can specify the quality from 0 to 1, where 0 is very poor quality and 1
|
|
|
|
* is very high quality
|
2015-04-27 12:20:55 +08:00
|
|
|
* @paremt {Number} [config.pixelRatio] pixelRatio of ouput image. Default is 1.
|
2013-05-18 02:46:06 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* var image = node.toImage({
|
|
|
|
* callback: function(img) {
|
|
|
|
* // do stuff with img
|
|
|
|
* }
|
2013-05-18 06:09:57 +08:00
|
|
|
* });
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
|
|
|
toImage: function(config) {
|
2015-04-16 10:23:55 +08:00
|
|
|
if (!config || !config.callback) {
|
2015-04-27 12:20:55 +08:00
|
|
|
throw 'callback required for toImage method config argument';
|
2015-04-16 10:23:55 +08:00
|
|
|
}
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Util._getImage(this.toDataURL(config), function(img) {
|
2012-11-14 15:22:56 +08:00
|
|
|
config.callback(img);
|
|
|
|
});
|
|
|
|
},
|
2013-12-02 15:47:24 +08:00
|
|
|
setSize: function(size) {
|
2012-11-14 15:22:56 +08:00
|
|
|
this.setWidth(size.width);
|
|
|
|
this.setHeight(size.height);
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
getSize: function() {
|
|
|
|
return {
|
|
|
|
width: this.getWidth(),
|
|
|
|
height: this.getHeight()
|
|
|
|
};
|
|
|
|
},
|
|
|
|
getWidth: function() {
|
|
|
|
return this.attrs.width || 0;
|
|
|
|
},
|
|
|
|
getHeight: function() {
|
|
|
|
return this.attrs.height || 0;
|
|
|
|
},
|
2013-05-18 01:51:56 +08:00
|
|
|
/**
|
|
|
|
* get class name, which may return Stage, Layer, Group, or shape class names like Rect, Circle, Text, etc.
|
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {String}
|
2013-05-18 01:51:56 +08:00
|
|
|
*/
|
|
|
|
getClassName: function() {
|
2013-05-20 12:48:48 +08:00
|
|
|
return this.className || this.nodeType;
|
2013-05-18 01:51:56 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get the node type, which may return Stage, Layer, Group, or Node
|
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {String}
|
2013-05-18 01:51:56 +08:00
|
|
|
*/
|
|
|
|
getType: function() {
|
|
|
|
return this.nodeType;
|
|
|
|
},
|
2014-03-11 23:14:03 +08:00
|
|
|
getDragDistance: function() {
|
|
|
|
// compare with undefined because we need to track 0 value
|
|
|
|
if (this.attrs.dragDistance !== undefined) {
|
|
|
|
return this.attrs.dragDistance;
|
|
|
|
} else if (this.parent) {
|
|
|
|
return this.parent.getDragDistance();
|
|
|
|
} else {
|
2015-01-27 15:07:51 +08:00
|
|
|
return Konva.dragDistance;
|
2014-03-11 23:14:03 +08:00
|
|
|
}
|
|
|
|
},
|
2012-11-14 15:22:56 +08:00
|
|
|
_get: function(selector) {
|
2014-04-25 19:17:12 +08:00
|
|
|
return this.className === selector || this.nodeType === selector ? [this] : [];
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
|
|
|
_off: function(type, name) {
|
2013-03-24 13:56:22 +08:00
|
|
|
var evtListeners = this.eventListeners[type],
|
2013-07-25 13:56:21 +08:00
|
|
|
i, evtName;
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-03-24 13:56:22 +08:00
|
|
|
for(i = 0; i < evtListeners.length; i++) {
|
2013-07-25 13:56:21 +08:00
|
|
|
evtName = evtListeners[i].name;
|
|
|
|
// the following two conditions must be true in order to remove a handler:
|
2015-01-27 15:07:51 +08:00
|
|
|
// 1) the current event name cannot be konva unless the event name is konva
|
|
|
|
// this enables developers to force remove a konva specific listener for whatever reason
|
2013-07-25 13:56:21 +08:00
|
|
|
// 2) an event name is not specified, or if one is specified, it matches the current event name
|
2015-01-27 15:07:51 +08:00
|
|
|
if((evtName !== 'konva' || name === 'konva') && (!name || evtName === name)) {
|
2013-03-24 13:56:22 +08:00
|
|
|
evtListeners.splice(i, 1);
|
|
|
|
if(evtListeners.length === 0) {
|
2012-11-14 15:22:56 +08:00
|
|
|
delete this.eventListeners[type];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_fireChangeEvent: function(attr, oldVal, newVal) {
|
2013-05-13 23:56:09 +08:00
|
|
|
this._fire(attr + CHANGE, {
|
2012-11-14 15:22:56 +08:00
|
|
|
oldVal: oldVal,
|
|
|
|
newVal: newVal
|
2013-05-13 23:56:09 +08:00
|
|
|
});
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
2013-01-14 03:10:49 +08:00
|
|
|
setId: function(id) {
|
2013-09-09 13:02:04 +08:00
|
|
|
var oldId = this.getId();
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva._removeId(oldId);
|
|
|
|
Konva._addId(this, id);
|
2013-05-15 13:37:33 +08:00
|
|
|
this._setAttr(ID, id);
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2013-01-14 03:10:49 +08:00
|
|
|
},
|
|
|
|
setName: function(name) {
|
2015-02-08 10:52:19 +08:00
|
|
|
var oldNames = (this.getName() || '').split(/\s/g);
|
|
|
|
var newNames = (name || '').split(/\s/g);
|
|
|
|
var subname, i;
|
|
|
|
// remove all subnames
|
|
|
|
for(i = 0; i < oldNames.length; i++) {
|
|
|
|
subname = oldNames[i];
|
|
|
|
if ((newNames.indexOf(subname)) === -1 && subname) {
|
|
|
|
Konva._removeName(subname, this._id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add new names
|
|
|
|
for(i = 0; i < newNames.length; i++) {
|
|
|
|
subname = newNames[i];
|
|
|
|
if ((oldNames.indexOf(subname) === -1) && subname) {
|
|
|
|
Konva._addName(this, subname);
|
|
|
|
}
|
|
|
|
}
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-05-15 13:37:33 +08:00
|
|
|
this._setAttr(NAME, name);
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2013-01-14 03:10:49 +08:00
|
|
|
},
|
2015-02-08 07:24:11 +08:00
|
|
|
// naming methods
|
|
|
|
/**
|
|
|
|
* add name to node
|
|
|
|
* @method
|
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @param {String} name
|
|
|
|
* @returns {Konva.Node}
|
|
|
|
* @example
|
|
|
|
* node.name('red');
|
|
|
|
* node.addName('selected');
|
|
|
|
* node.name(); // return 'red selected'
|
|
|
|
*/
|
2015-05-04 17:02:16 +08:00
|
|
|
addName: function(name) {
|
2015-02-08 07:24:11 +08:00
|
|
|
if (!this.hasName(name)) {
|
2015-02-08 08:39:43 +08:00
|
|
|
var oldName = this.name();
|
|
|
|
var newName = oldName ? (oldName + ' ' + name) : name;
|
2015-02-08 07:24:11 +08:00
|
|
|
this.setName(newName);
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* check is node has name
|
|
|
|
* @method
|
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @param {String} name
|
|
|
|
* @returns {Boolean}
|
|
|
|
* @example
|
|
|
|
* node.name('red');
|
|
|
|
* node.hasName('red'); // return true
|
|
|
|
* node.hasName('selected'); // return false
|
|
|
|
*/
|
2015-05-04 17:02:16 +08:00
|
|
|
hasName: function(name) {
|
2015-02-08 08:39:43 +08:00
|
|
|
var names = (this.name() || '').split(/\s/g);
|
2015-02-08 07:24:11 +08:00
|
|
|
return names.indexOf(name) !== -1;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* remove name from node
|
|
|
|
* @method
|
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @param {String} name
|
|
|
|
* @returns {Konva.Node}
|
|
|
|
* @example
|
|
|
|
* node.name('red selected');
|
|
|
|
* node.removeName('selected');
|
|
|
|
* node.hasName('selected'); // return false
|
|
|
|
* node.name(); // return 'red'
|
|
|
|
*/
|
2015-05-04 17:02:16 +08:00
|
|
|
removeName: function(name) {
|
2015-02-08 08:39:43 +08:00
|
|
|
var names = (this.name() || '').split(/\s/g);
|
2015-02-08 07:24:11 +08:00
|
|
|
var index = names.indexOf(name);
|
|
|
|
if (index !== -1) {
|
|
|
|
names.splice(index, 1);
|
|
|
|
this.setName(names.join(' '));
|
|
|
|
}
|
2015-12-22 18:19:33 +08:00
|
|
|
return this;
|
2015-02-08 07:24:11 +08:00
|
|
|
},
|
2013-12-05 00:56:21 +08:00
|
|
|
/**
|
|
|
|
* set attr
|
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-05 00:56:21 +08:00
|
|
|
* @param {String} attr
|
2013-12-10 02:33:31 +08:00
|
|
|
* @param {*} val
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Node}
|
2013-12-05 00:56:21 +08:00
|
|
|
* @example
|
|
|
|
* node.setAttr('x', 5);
|
|
|
|
*/
|
2014-08-19 19:27:46 +08:00
|
|
|
setAttr: function(attr, val) {
|
2015-01-27 15:07:51 +08:00
|
|
|
var method = SET + Konva.Util._capitalize(attr),
|
2013-12-05 00:56:21 +08:00
|
|
|
func = this[method];
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
if(Konva.Util._isFunction(func)) {
|
2013-12-05 00:56:21 +08:00
|
|
|
func.call(this, val);
|
|
|
|
}
|
|
|
|
// otherwise set directly
|
|
|
|
else {
|
|
|
|
this._setAttr(attr, val);
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
2013-05-15 13:37:33 +08:00
|
|
|
_setAttr: function(key, val) {
|
2013-03-24 13:56:22 +08:00
|
|
|
var oldVal;
|
2016-07-05 10:59:41 +08:00
|
|
|
oldVal = this.attrs[key];
|
|
|
|
if (oldVal === val) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (val === undefined || val === null) {
|
|
|
|
delete this.attrs[key];
|
|
|
|
} else {
|
|
|
|
this.attrs[key] = val;
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
2016-07-05 10:59:41 +08:00
|
|
|
this._fireChangeEvent(key, oldVal, val);
|
2012-11-14 15:22:56 +08:00
|
|
|
},
|
2013-12-10 02:38:01 +08:00
|
|
|
_setComponentAttr: function(key, component, val) {
|
2013-12-02 15:47:24 +08:00
|
|
|
var oldVal;
|
|
|
|
if(val !== undefined) {
|
|
|
|
oldVal = this.attrs[key];
|
|
|
|
|
|
|
|
if (!oldVal) {
|
2013-12-04 14:54:16 +08:00
|
|
|
// set value to default value using getAttr
|
|
|
|
this.attrs[key] = this.getAttr(key);
|
2013-12-02 15:47:24 +08:00
|
|
|
}
|
2015-05-04 17:02:16 +08:00
|
|
|
|
2013-12-02 15:47:24 +08:00
|
|
|
this.attrs[key][component] = val;
|
|
|
|
this._fireChangeEvent(key, oldVal, val);
|
|
|
|
}
|
|
|
|
},
|
2013-05-13 23:56:09 +08:00
|
|
|
_fireAndBubble: function(eventType, evt, compareShape) {
|
2013-08-12 11:34:54 +08:00
|
|
|
var okayToRun = true;
|
|
|
|
|
2013-03-24 13:56:22 +08:00
|
|
|
if(evt && this.nodeType === SHAPE) {
|
2014-03-21 12:55:30 +08:00
|
|
|
evt.target = this;
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
|
|
|
|
2014-05-02 08:45:52 +08:00
|
|
|
if(eventType === MOUSEENTER && compareShape && (this._id === compareShape._id || (this.isAncestorOf && this.isAncestorOf(compareShape)))) {
|
2012-11-14 15:22:56 +08:00
|
|
|
okayToRun = false;
|
|
|
|
}
|
2014-05-02 08:45:52 +08:00
|
|
|
else if(eventType === MOUSELEAVE && compareShape && (this._id === compareShape._id || (this.isAncestorOf && this.isAncestorOf(compareShape)))) {
|
2012-11-14 15:22:56 +08:00
|
|
|
okayToRun = false;
|
|
|
|
}
|
2013-07-22 11:14:09 +08:00
|
|
|
if(okayToRun) {
|
2013-05-13 23:56:09 +08:00
|
|
|
this._fire(eventType, evt);
|
2012-11-14 15:22:56 +08:00
|
|
|
|
|
|
|
// simulate event bubbling
|
2016-06-07 18:25:32 +08:00
|
|
|
var stopBubble =
|
|
|
|
(eventType === MOUSEENTER || eventType === MOUSELEAVE) &&
|
|
|
|
((compareShape && compareShape.isAncestorOf && compareShape.isAncestorOf(this) && !compareShape.isAncestorOf(this.parent)));
|
2016-01-04 08:24:27 +08:00
|
|
|
if((evt && !evt.cancelBubble || !evt) && this.parent && this.parent.isListening() && (!stopBubble)) {
|
2016-06-07 18:25:32 +08:00
|
|
|
if (compareShape && compareShape.parent) {
|
2013-05-13 23:56:09 +08:00
|
|
|
this._fireAndBubble.call(this.parent, eventType, evt, compareShape.parent);
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
|
|
|
else {
|
2013-05-13 23:56:09 +08:00
|
|
|
this._fireAndBubble.call(this.parent, eventType, evt);
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2013-05-13 23:56:09 +08:00
|
|
|
_fire: function(eventType, evt) {
|
2013-03-22 10:43:17 +08:00
|
|
|
var events = this.eventListeners[eventType],
|
2013-10-05 03:43:08 +08:00
|
|
|
i;
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2016-01-26 23:21:25 +08:00
|
|
|
evt = evt || {};
|
2016-01-04 08:24:27 +08:00
|
|
|
evt.currentTarget = this;
|
2014-03-21 12:55:30 +08:00
|
|
|
evt.type = eventType;
|
|
|
|
|
2013-03-22 10:43:17 +08:00
|
|
|
if (events) {
|
2013-10-05 03:03:50 +08:00
|
|
|
for(i = 0; i < events.length; i++) {
|
2013-05-15 13:37:33 +08:00
|
|
|
events[i].handler.call(this, evt);
|
2013-03-22 10:43:17 +08:00
|
|
|
}
|
2012-11-14 15:22:56 +08:00
|
|
|
}
|
2013-03-22 15:46:41 +08:00
|
|
|
},
|
2013-10-14 03:35:29 +08:00
|
|
|
/**
|
2013-12-10 02:33:31 +08:00
|
|
|
* draw both scene and hit graphs. If the node being drawn is the stage, all of the layers will be cleared and redrawn
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @returns {Konva.Node}
|
2013-03-22 15:46:41 +08:00
|
|
|
*/
|
2014-03-22 15:17:56 +08:00
|
|
|
draw: function() {
|
|
|
|
this.drawScene();
|
|
|
|
this.drawHit();
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-06-10 06:31:25 +08:00
|
|
|
}
|
2013-05-08 14:17:57 +08:00
|
|
|
});
|
2012-06-10 06:31:25 +08:00
|
|
|
|
2012-03-07 13:45:48 +08:00
|
|
|
/**
|
2015-08-28 11:29:52 +08:00
|
|
|
* create node with JSON string or an Object. De-serializtion does not generate custom
|
2012-11-14 15:22:56 +08:00
|
|
|
* shape drawing functions, images, or event handlers (this would make the
|
2013-06-02 13:03:02 +08:00
|
|
|
* serialized object huge). If your app uses custom shapes, images, and
|
2012-11-14 15:22:56 +08:00
|
|
|
* event handlers (it probably does), then you need to select the appropriate
|
|
|
|
* shapes after loading the stage and set these properties via on(), setDrawFunc(),
|
2012-11-27 11:12:02 +08:00
|
|
|
* and setImage() methods
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node
|
2015-08-28 11:29:52 +08:00
|
|
|
* @param {String|Object} json string or object
|
2014-08-19 19:27:46 +08:00
|
|
|
* @param {Element} [container] optional container dom element used only if you're
|
2012-11-27 11:12:02 +08:00
|
|
|
* creating a stage node
|
2012-03-07 13:45:48 +08:00
|
|
|
*/
|
2015-08-28 11:29:52 +08:00
|
|
|
Konva.Node.create = function(data, container) {
|
|
|
|
if (Konva.Util._isString(data)) {
|
|
|
|
data = JSON.parse(data);
|
|
|
|
}
|
|
|
|
return this._createNode(data, container);
|
2012-11-14 15:22:56 +08:00
|
|
|
};
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Node._createNode = function(obj, container) {
|
|
|
|
var className = Konva.Node.prototype.getClassName.call(obj),
|
2013-05-20 12:48:48 +08:00
|
|
|
children = obj.children,
|
|
|
|
no, len, n;
|
2012-10-04 10:38:12 +08:00
|
|
|
|
2012-11-14 15:22:56 +08:00
|
|
|
// if container was passed in, add it to attrs
|
|
|
|
if(container) {
|
|
|
|
obj.attrs.container = container;
|
|
|
|
}
|
2012-10-04 10:38:12 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
no = new Konva[className](obj.attrs);
|
2013-05-20 12:48:48 +08:00
|
|
|
if(children) {
|
|
|
|
len = children.length;
|
2013-03-24 13:56:22 +08:00
|
|
|
for(n = 0; n < len; n++) {
|
2013-05-20 12:48:48 +08:00
|
|
|
no.add(this._createNode(children[n]));
|
2012-10-04 10:38:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-14 15:22:56 +08:00
|
|
|
return no;
|
|
|
|
};
|
2014-01-06 06:55:35 +08:00
|
|
|
|
|
|
|
|
|
|
|
// =========================== add getters setters ===========================
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addOverloadedGetterSetter(Konva.Node, 'position');
|
2012-03-07 13:45:48 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set node position relative to parent
|
2013-12-14 13:33:40 +08:00
|
|
|
* @name position
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-14 13:33:40 +08:00
|
|
|
* @param {Object} pos
|
|
|
|
* @param {Number} pos.x
|
2014-08-19 19:27:46 +08:00
|
|
|
* @param {Number} pos.y
|
2013-12-14 13:33:40 +08:00
|
|
|
* @returns {Object}
|
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get position
|
|
|
|
* var position = node.position();
|
2013-12-14 13:33:40 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set position
|
|
|
|
* node.position({
|
|
|
|
* x: 5
|
|
|
|
* y: 10
|
2013-12-14 13:33:40 +08:00
|
|
|
* });
|
2012-03-07 13:45:48 +08:00
|
|
|
*/
|
2012-11-14 15:22:56 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'x', 0);
|
2013-12-14 13:33:40 +08:00
|
|
|
|
2012-06-02 15:21:49 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set x position
|
2013-12-14 13:33:40 +08:00
|
|
|
* @name x
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-14 13:33:40 +08:00
|
|
|
* @param {Number} x
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Object}
|
2013-12-14 13:33:40 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get x
|
|
|
|
* var x = node.x();
|
2013-12-14 13:33:40 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set x
|
2013-12-14 13:33:40 +08:00
|
|
|
* node.x(5);
|
2012-06-02 15:21:49 +08:00
|
|
|
*/
|
2012-11-14 15:22:56 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'y', 0);
|
2013-05-02 01:56:01 +08:00
|
|
|
|
2012-03-24 14:39:54 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set y position
|
2013-12-14 13:33:40 +08:00
|
|
|
* @name y
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-05-02 01:56:01 +08:00
|
|
|
* @param {Number} y
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Integer}
|
2013-12-14 13:33:40 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get y
|
|
|
|
* var y = node.y();
|
2013-12-14 13:33:40 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set y
|
2013-12-14 13:33:40 +08:00
|
|
|
* node.y(5);
|
2012-11-27 11:12:02 +08:00
|
|
|
*/
|
2012-11-30 12:15:01 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'opacity', 1);
|
2013-05-02 01:56:01 +08:00
|
|
|
|
2012-11-27 11:12:02 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set opacity. Opacity values range from 0 to 1.
|
2013-05-02 01:56:01 +08:00
|
|
|
* A node with an opacity of 0 is fully transparent, and a node
|
|
|
|
* with an opacity of 1 is fully opaque
|
2013-12-14 13:33:40 +08:00
|
|
|
* @name opacity
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-05-02 01:56:01 +08:00
|
|
|
* @param {Object} opacity
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Number}
|
2013-12-14 13:33:40 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get opacity
|
|
|
|
* var opacity = node.opacity();
|
2013-12-14 13:33:40 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set opacity
|
2013-12-14 13:33:40 +08:00
|
|
|
* node.opacity(0.5);
|
toDataURL() is now synchronous, and works with all nodes, including the stage, layers, groups, and shapes. This also sets things up nicely for node caching. You can now cache anything, including the whole stage, layers, groups, or shapes, manifested as Kinetic Images that were instantiated with data urls
2012-07-15 09:10:37 +08:00
|
|
|
*/
|
2012-07-22 06:38:25 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetter(Konva.Node, 'name');
|
|
|
|
Konva.Factory.addOverloadedGetterSetter(Konva.Node, 'name');
|
2013-01-14 03:10:49 +08:00
|
|
|
|
2013-12-14 13:33:40 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set name
|
2013-12-14 13:33:40 +08:00
|
|
|
* @name name
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-14 13:33:40 +08:00
|
|
|
* @param {String} name
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {String}
|
2013-12-14 13:33:40 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get name
|
|
|
|
* var name = node.name();
|
2013-12-14 13:33:40 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set name
|
2013-12-14 13:33:40 +08:00
|
|
|
* node.name('foo');
|
2014-09-24 10:26:42 +08:00
|
|
|
*
|
|
|
|
* // also node may have multiple names (as css classes)
|
|
|
|
* node.name('foo bar');
|
2012-07-15 14:41:16 +08:00
|
|
|
*/
|
2012-11-14 15:22:56 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetter(Konva.Node, 'id');
|
|
|
|
Konva.Factory.addOverloadedGetterSetter(Konva.Node, 'id');
|
2013-05-02 01:56:01 +08:00
|
|
|
|
2012-09-25 11:34:23 +08:00
|
|
|
/**
|
2015-05-14 08:07:55 +08:00
|
|
|
* get/set id. Id is global for whole page.
|
2013-12-14 13:33:40 +08:00
|
|
|
* @name id
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-14 13:33:40 +08:00
|
|
|
* @param {String} id
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {String}
|
2013-12-14 13:33:40 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get id
|
|
|
|
* var name = node.id();
|
2013-12-14 13:33:40 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set id
|
2013-12-14 13:33:40 +08:00
|
|
|
* node.id('foo');
|
2012-09-26 04:38:36 +08:00
|
|
|
*/
|
2012-11-14 15:22:56 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'rotation', 0);
|
2013-01-03 13:35:51 +08:00
|
|
|
|
2012-09-25 11:34:23 +08:00
|
|
|
/**
|
2014-01-07 13:37:46 +08:00
|
|
|
* get/set rotation in degrees
|
2013-12-14 13:33:40 +08:00
|
|
|
* @name rotation
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2014-01-06 06:55:35 +08:00
|
|
|
* @param {Number} rotation
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Number}
|
2013-12-14 13:33:40 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get rotation in degrees
|
|
|
|
* var rotation = node.rotation();
|
2013-12-14 13:33:40 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set rotation in degrees
|
2014-01-07 13:37:46 +08:00
|
|
|
* node.rotation(45);
|
2012-10-11 09:48:08 +08:00
|
|
|
*/
|
2012-11-14 15:22:56 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addComponentsGetterSetter(Konva.Node, 'scale', ['x', 'y']);
|
2013-01-03 13:35:51 +08:00
|
|
|
|
2012-10-11 09:48:08 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set scale
|
2013-12-14 13:33:40 +08:00
|
|
|
* @name scale
|
2013-12-02 15:47:24 +08:00
|
|
|
* @param {Object} scale
|
|
|
|
* @param {Number} scale.x
|
|
|
|
* @param {Number} scale.y
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-14 13:33:40 +08:00
|
|
|
* @returns {Object}
|
2013-05-19 01:40:05 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get scale
|
|
|
|
* var scale = node.scale();
|
2013-12-14 13:33:40 +08:00
|
|
|
*
|
2015-05-04 17:02:16 +08:00
|
|
|
* // set scale
|
2014-04-04 11:17:09 +08:00
|
|
|
* shape.scale({
|
|
|
|
* x: 2
|
|
|
|
* y: 3
|
2013-12-02 15:47:24 +08:00
|
|
|
* });
|
2013-01-03 13:35:51 +08:00
|
|
|
*/
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'scaleX', 1);
|
2014-01-09 15:13:50 +08:00
|
|
|
|
2013-12-02 15:47:24 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set scale x
|
2013-12-14 13:33:40 +08:00
|
|
|
* @name scaleX
|
2013-12-02 15:47:24 +08:00
|
|
|
* @param {Number} x
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-10 02:33:31 +08:00
|
|
|
* @returns {Number}
|
2013-12-14 13:33:40 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get scale x
|
|
|
|
* var scaleX = node.scaleX();
|
2013-12-14 13:33:40 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set scale x
|
2013-12-14 13:33:40 +08:00
|
|
|
* node.scaleX(2);
|
2013-05-02 01:56:01 +08:00
|
|
|
*/
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'scaleY', 1);
|
2014-01-09 15:13:50 +08:00
|
|
|
|
2013-12-02 15:47:24 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set scale y
|
2013-12-14 13:33:40 +08:00
|
|
|
* @name scaleY
|
2013-12-02 15:47:24 +08:00
|
|
|
* @param {Number} y
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-14 13:33:40 +08:00
|
|
|
* @returns {Number}
|
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get scale y
|
|
|
|
* var scaleY = node.scaleY();
|
2013-12-14 13:33:40 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set scale y
|
2013-12-14 13:33:40 +08:00
|
|
|
* node.scaleY(2);
|
2013-05-08 01:19:54 +08:00
|
|
|
*/
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addComponentsGetterSetter(Konva.Node, 'skew', ['x', 'y']);
|
2013-05-02 01:56:01 +08:00
|
|
|
|
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set skew
|
|
|
|
* @name skew
|
2013-12-04 14:54:16 +08:00
|
|
|
* @param {Object} skew
|
|
|
|
* @param {Number} skew.x
|
|
|
|
* @param {Number} skew.y
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2014-01-06 06:55:35 +08:00
|
|
|
* @returns {Object}
|
2013-05-19 01:40:05 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get skew
|
|
|
|
* var skew = node.skew();
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2015-05-04 17:02:16 +08:00
|
|
|
* // set skew
|
2014-04-04 11:17:09 +08:00
|
|
|
* node.skew({
|
|
|
|
* x: 20
|
2013-12-04 14:54:16 +08:00
|
|
|
* y: 10
|
|
|
|
* });
|
2012-10-11 09:48:08 +08:00
|
|
|
*/
|
2012-07-20 14:30:59 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'skewX', 0);
|
2014-01-09 15:13:50 +08:00
|
|
|
|
2013-12-04 14:54:16 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set skew x
|
|
|
|
* @name skewX
|
2013-12-04 14:54:16 +08:00
|
|
|
* @param {Number} x
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-04 14:54:16 +08:00
|
|
|
* @returns {Number}
|
2014-01-06 06:55:35 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get skew x
|
|
|
|
* var skewX = node.skewX();
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set skew x
|
2014-01-06 06:55:35 +08:00
|
|
|
* node.skewX(3);
|
2012-03-07 13:45:48 +08:00
|
|
|
*/
|
2012-10-11 09:48:08 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'skewY', 0);
|
2014-01-09 15:13:50 +08:00
|
|
|
|
2013-12-04 14:54:16 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set skew y
|
|
|
|
* @name skewY
|
2013-12-04 14:54:16 +08:00
|
|
|
* @param {Number} y
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-04 14:54:16 +08:00
|
|
|
* @returns {Number}
|
2014-01-06 06:55:35 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get skew y
|
|
|
|
* var skewY = node.skewY();
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set skew y
|
2014-01-06 06:55:35 +08:00
|
|
|
* node.skewY(3);
|
2013-05-08 01:19:54 +08:00
|
|
|
*/
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addComponentsGetterSetter(Konva.Node, 'offset', ['x', 'y']);
|
2013-05-02 01:56:01 +08:00
|
|
|
|
|
|
|
/**
|
2014-01-11 14:09:22 +08:00
|
|
|
* get/set offset. Offsets the default position and rotation point
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2014-01-11 14:09:22 +08:00
|
|
|
* @param {Object} offset
|
|
|
|
* @param {Number} offset.x
|
|
|
|
* @param {Number} offset.y
|
2013-12-29 05:25:15 +08:00
|
|
|
* @returns {Object}
|
2013-05-19 01:40:05 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get offset
|
|
|
|
* var offset = node.offset();
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set offset
|
|
|
|
* node.offset({
|
|
|
|
* x: 20
|
|
|
|
* y: 10
|
2014-01-06 06:55:35 +08:00
|
|
|
* });
|
2013-05-02 01:56:01 +08:00
|
|
|
*/
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'offsetX', 0);
|
2014-01-09 15:13:50 +08:00
|
|
|
|
2013-12-02 15:47:24 +08:00
|
|
|
/**
|
2014-01-11 14:09:22 +08:00
|
|
|
* get/set offset x
|
|
|
|
* @name offsetX
|
2015-01-20 18:06:21 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-02 15:47:24 +08:00
|
|
|
* @param {Number} x
|
2014-01-06 06:55:35 +08:00
|
|
|
* @returns {Number}
|
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get offset x
|
|
|
|
* var offsetX = node.offsetX();
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set offset x
|
2014-01-11 14:09:22 +08:00
|
|
|
* node.offsetX(3);
|
2012-11-14 15:22:56 +08:00
|
|
|
*/
|
2013-01-02 15:54:02 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'offsetY', 0);
|
2014-01-09 15:13:50 +08:00
|
|
|
|
2014-03-11 23:14:03 +08:00
|
|
|
/**
|
2015-01-20 18:06:21 +08:00
|
|
|
* get/set offset y
|
|
|
|
* @name offsetY
|
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2015-01-20 18:06:21 +08:00
|
|
|
* @param {Number} y
|
2014-03-11 23:14:03 +08:00
|
|
|
* @returns {Number}
|
|
|
|
* @example
|
2015-01-20 18:06:21 +08:00
|
|
|
* // get offset y
|
|
|
|
* var offsetY = node.offsetY();
|
2014-03-11 23:14:03 +08:00
|
|
|
*
|
2015-01-20 18:06:21 +08:00
|
|
|
* // set offset y
|
|
|
|
* node.offsetY(3);
|
2014-03-11 23:14:03 +08:00
|
|
|
*/
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addSetter(Konva.Node, 'dragDistance');
|
|
|
|
Konva.Factory.addOverloadedGetterSetter(Konva.Node, 'dragDistance');
|
2014-03-11 23:14:03 +08:00
|
|
|
|
2013-12-02 15:47:24 +08:00
|
|
|
/**
|
2015-01-20 18:06:21 +08:00
|
|
|
* get/set drag distance
|
|
|
|
* @name dragDistance
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2015-01-20 18:06:21 +08:00
|
|
|
* @param {Number} distance
|
2014-01-06 06:55:35 +08:00
|
|
|
* @returns {Number}
|
|
|
|
* @example
|
2015-01-20 18:06:21 +08:00
|
|
|
* // get drag distance
|
|
|
|
* var dragDistance = node.dragDistance();
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2015-01-20 18:06:21 +08:00
|
|
|
* // set distance
|
|
|
|
* // node starts dragging only if pointer moved more then 3 pixels
|
|
|
|
* node.dragDistance(3);
|
|
|
|
* // or set globally
|
2015-01-27 15:07:51 +08:00
|
|
|
* Konva.dragDistance = 3;
|
2013-05-08 01:19:54 +08:00
|
|
|
*/
|
|
|
|
|
2015-01-20 18:06:21 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addSetter(Konva.Node, 'width', 0);
|
|
|
|
Konva.Factory.addOverloadedGetterSetter(Konva.Node, 'width');
|
2013-01-02 15:54:02 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set width
|
|
|
|
* @name width
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-01-03 13:35:51 +08:00
|
|
|
* @param {Number} width
|
2014-01-06 06:55:35 +08:00
|
|
|
* @returns {Number}
|
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get width
|
|
|
|
* var width = node.width();
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set width
|
2014-01-06 06:55:35 +08:00
|
|
|
* node.width(100);
|
2013-01-02 15:54:02 +08:00
|
|
|
*/
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addSetter(Konva.Node, 'height', 0);
|
|
|
|
Konva.Factory.addOverloadedGetterSetter(Konva.Node, 'height');
|
2013-01-02 15:54:02 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set height
|
|
|
|
* @name height
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-01-03 13:35:51 +08:00
|
|
|
* @param {Number} height
|
2014-01-06 06:55:35 +08:00
|
|
|
* @returns {Number}
|
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get height
|
|
|
|
* var height = node.height();
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set height
|
2014-01-06 06:55:35 +08:00
|
|
|
* node.height(100);
|
2013-01-02 15:54:02 +08:00
|
|
|
*/
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'listening', 'inherit');
|
2013-01-02 15:54:02 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set listenig attr. If you need to determine if a node is listening or not
|
2015-05-04 17:02:16 +08:00
|
|
|
* by taking into account its parents, use the isListening() method
|
2014-01-06 06:55:35 +08:00
|
|
|
* @name listening
|
2013-07-22 11:14:09 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2014-01-06 06:55:35 +08:00
|
|
|
* @param {Boolean|String} listening Can be "inherit", true, or false. The default is "inherit".
|
2013-12-10 02:07:08 +08:00
|
|
|
* @returns {Boolean|String}
|
2014-01-06 06:55:35 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get listening attr
|
|
|
|
* var listening = node.listening();
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // stop listening for events
|
|
|
|
* node.listening(false);
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // listen for events
|
|
|
|
* node.listening(true);
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // listen to events according to the parent
|
2014-01-06 06:55:35 +08:00
|
|
|
* node.listening('inherit');
|
2013-07-22 11:14:09 +08:00
|
|
|
*/
|
|
|
|
|
2016-09-10 19:57:50 +08:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get/set preventDefault
|
|
|
|
* By default all shapes will prevent default behaviour
|
|
|
|
* of a browser on a pointer move or tap.
|
|
|
|
* that will prevent native scrolling when you are trying to drag&drop a node
|
|
|
|
* but sometimes you may need to enable default actions
|
|
|
|
* in that case you can set the property to false
|
|
|
|
* @name preventDefault
|
|
|
|
* @method
|
|
|
|
* @memberof Konva.Node.prototype
|
|
|
|
* @param {Number} preventDefault
|
|
|
|
* @returns {Number}
|
|
|
|
* @example
|
|
|
|
* // get preventDefault
|
|
|
|
* var shouldPrevent = shape.preventDefault();
|
|
|
|
*
|
|
|
|
* // set preventDefault
|
|
|
|
* shape.preventDefault(false);
|
|
|
|
*/
|
|
|
|
|
2016-09-10 20:00:31 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'preventDefault', true);
|
2016-09-10 19:57:50 +08:00
|
|
|
|
2015-05-04 17:02:16 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'filters', undefined, function(val) {this._filterUpToDate = false; return val; });
|
2014-01-01 05:04:05 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set filters. Filters are applied to cached canvases
|
2014-01-01 05:04:05 +08:00
|
|
|
* @name filters
|
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2014-01-01 05:04:05 +08:00
|
|
|
* @param {Array} filters array of filters
|
|
|
|
* @returns {Array}
|
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get filters
|
|
|
|
* var filters = node.filters();
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set a single filter
|
|
|
|
* node.cache();
|
2015-01-27 15:07:51 +08:00
|
|
|
* node.filters([Konva.Filters.Blur]);
|
2014-01-01 05:04:05 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set multiple filters
|
|
|
|
* node.cache();
|
|
|
|
* node.filters([
|
2015-01-27 15:07:51 +08:00
|
|
|
* Konva.Filters.Blur,
|
|
|
|
* Konva.Filters.Sepia,
|
|
|
|
* Konva.Filters.Invert
|
2014-01-06 06:55:35 +08:00
|
|
|
* ]);
|
2014-01-01 05:04:05 +08:00
|
|
|
*/
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'visible', 'inherit');
|
2013-01-02 15:54:02 +08:00
|
|
|
/**
|
2014-01-06 06:55:35 +08:00
|
|
|
* get/set visible attr. Can be "inherit", true, or false. The default is "inherit".
|
|
|
|
* If you need to determine if a node is visible or not
|
2015-05-04 17:02:16 +08:00
|
|
|
* by taking into account its parents, use the isVisible() method
|
2014-01-06 06:55:35 +08:00
|
|
|
* @name visible
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2014-01-06 06:55:35 +08:00
|
|
|
* @param {Boolean|String} visible
|
|
|
|
* @returns {Boolean|String}
|
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get visible attr
|
|
|
|
* var visible = node.visible();
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // make invisible
|
|
|
|
* node.visible(false);
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // make visible
|
|
|
|
* node.visible(true);
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // make visible according to the parent
|
2014-01-06 06:55:35 +08:00
|
|
|
* node.visible('inherit');
|
2013-01-03 13:35:51 +08:00
|
|
|
*/
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetterSetter(Konva.Node, 'transformsEnabled', 'all');
|
2013-12-11 15:28:46 +08:00
|
|
|
|
|
|
|
/**
|
2013-12-20 15:29:23 +08:00
|
|
|
* get/set transforms that are enabled. Can be "all", "none", or "position". The default
|
|
|
|
* is "all"
|
|
|
|
* @name transformsEnabled
|
2013-12-11 15:28:46 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2013-12-20 15:29:23 +08:00
|
|
|
* @param {String} enabled
|
|
|
|
* @returns {String}
|
2014-01-06 06:55:35 +08:00
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // enable position transform only to improve draw performance
|
|
|
|
* node.transformsEnabled('position');
|
2014-01-06 06:55:35 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // enable all transforms
|
2014-01-06 06:55:35 +08:00
|
|
|
* node.transformsEnabled('all');
|
2013-12-11 15:28:46 +08:00
|
|
|
*/
|
|
|
|
|
2014-03-21 11:39:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get/set node size
|
|
|
|
* @name size
|
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Node.prototype
|
2014-03-21 11:39:40 +08:00
|
|
|
* @param {Object} size
|
|
|
|
* @param {Number} size.width
|
|
|
|
* @param {Number} size.height
|
|
|
|
* @returns {Object}
|
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get node size
|
|
|
|
* var size = node.size();
|
|
|
|
* var x = size.x;
|
|
|
|
* var y = size.y;
|
2014-03-21 11:39:40 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set size
|
|
|
|
* node.size({
|
|
|
|
* width: 100,
|
|
|
|
* height: 200
|
2014-03-21 11:39:40 +08:00
|
|
|
* });
|
|
|
|
*/
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addOverloadedGetterSetter(Konva.Node, 'size');
|
2014-03-21 11:39:40 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.backCompat(Konva.Node, {
|
2014-01-11 14:58:55 +08:00
|
|
|
rotateDeg: 'rotate',
|
|
|
|
setRotationDeg: 'setRotation',
|
|
|
|
getRotationDeg: 'getRotation'
|
|
|
|
});
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Collection.mapMethods(Konva.Node);
|
2015-05-04 17:02:16 +08:00
|
|
|
})(Konva);
|