UNPKG

konva

Version:

<p align="center"> <img src="https://raw.githubusercontent.com/konvajs/konvajs.github.io/master/apple-touch-icon-180x180.png" alt="Konva logo" height="180" /> </p>

1,306 lines (1,305 loc) 47.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Util_1 = require("./Util"); var Factory_1 = require("./Factory"); var Canvas_1 = require("./Canvas"); var Global_1 = require("./Global"); var DragAndDrop_1 = require("./DragAndDrop"); var Validators_1 = require("./Validators"); exports.ids = {}; exports.names = {}; var _addId = function (node, id) { if (!id) { return; } exports.ids[id] = node; }; exports._removeId = function (id, node) { if (!id) { return; } if (exports.ids[id] !== node) { return; } delete exports.ids[id]; }; exports._addName = function (node, name) { if (name) { if (!exports.names[name]) { exports.names[name] = []; } exports.names[name].push(node); } }; exports._removeName = function (name, _id) { if (!name) { return; } var nodes = exports.names[name]; if (!nodes) { return; } for (var n = 0; n < nodes.length; n++) { var no = nodes[n]; if (no._id === _id) { nodes.splice(n, 1); } } if (nodes.length === 0) { delete exports.names[name]; } }; var ABSOLUTE_OPACITY = 'absoluteOpacity', ABSOLUTE_TRANSFORM = 'absoluteTransform', ABSOLUTE_SCALE = 'absoluteScale', CANVAS = 'canvas', CHANGE = 'Change', CHILDREN = 'children', KONVA = 'konva', LISTENING = 'listening', MOUSEENTER = 'mouseenter', MOUSELEAVE = 'mouseleave', NAME = 'name', SET = 'set', SHAPE = 'Shape', SPACE = ' ', STAGE = 'stage', TRANSFORM = 'transform', UPPER_STAGE = 'Stage', VISIBLE = 'visible', CLONE_BLACK_LIST = ['id'], TRANSFORM_CHANGE_STR = [ 'xChange.konva', 'yChange.konva', 'scaleXChange.konva', 'scaleYChange.konva', 'skewXChange.konva', 'skewYChange.konva', 'rotationChange.konva', 'offsetXChange.konva', 'offsetYChange.konva', 'transformsEnabledChange.konva' ].join(SPACE), SCALE_CHANGE_STR = ['scaleXChange.konva', 'scaleYChange.konva'].join(SPACE); var emptyChildren = new Util_1.Collection(); var idCounter = 1; var Node = (function () { function Node(config) { var _this = this; this._id = idCounter++; this.eventListeners = {}; this.attrs = {}; this.index = 0; this.parent = null; this._cache = new Map(); this._lastPos = null; this._filterUpToDate = false; this._isUnderCache = false; this.children = emptyChildren; this._dragEventId = null; this.setAttrs(config); this.on(TRANSFORM_CHANGE_STR, function () { _this._clearCache(TRANSFORM); _this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM); }); this.on(SCALE_CHANGE_STR, function () { _this._clearSelfAndDescendantCache(ABSOLUTE_SCALE); }); this.on('visibleChange.konva', function () { _this._clearSelfAndDescendantCache(VISIBLE); }); this.on('listeningChange.konva', function () { _this._clearSelfAndDescendantCache(LISTENING); }); this.on('opacityChange.konva', function () { _this._clearSelfAndDescendantCache(ABSOLUTE_OPACITY); }); } Node.prototype.hasChildren = function () { return false; }; Node.prototype.getChildren = function () { return emptyChildren; }; Node.prototype._clearCache = function (attr) { if (attr) { this._cache.delete(attr); } else { this._cache.clear(); } }; Node.prototype._getCache = function (attr, privateGetter) { var cache = this._cache.get(attr); if (cache === undefined) { cache = privateGetter.call(this); this._cache.set(attr, cache); } return cache; }; Node.prototype._getCanvasCache = function () { return this._cache.get(CANVAS); }; Node.prototype._clearSelfAndDescendantCache = function (attr) { this._clearCache(attr); if (this._getCanvasCache()) { return; } if (this.children) { this.children.each(function (node) { node._clearSelfAndDescendantCache(attr); }); } }; Node.prototype.clearCache = function () { this._cache.delete(CANVAS); this._clearSelfAndDescendantCache(); return this; }; Node.prototype.cache = function (config) { var conf = config || {}; var rect = {}; if (conf.x === undefined || conf.y === undefined || conf.width === undefined || conf.height === undefined) { rect = this.getClientRect({ skipTransform: true, relativeTo: this.getParent() }); } var width = conf.width || rect.width, height = conf.height || rect.height, pixelRatio = conf.pixelRatio, x = conf.x === undefined ? rect.x : conf.x, y = conf.y === undefined ? rect.y : conf.y, offset = conf.offset || 0, drawBorder = conf.drawBorder || false; if (!width || !height) { Util_1.Util.error('Can not cache the node. Width or height of the node equals 0. Caching is skipped.'); return; } width += offset * 2; height += offset * 2; x -= offset; y -= offset; var cachedSceneCanvas = new Canvas_1.SceneCanvas({ pixelRatio: pixelRatio, width: width, height: height }), cachedFilterCanvas = new Canvas_1.SceneCanvas({ pixelRatio: pixelRatio, width: width, height: height }), cachedHitCanvas = new Canvas_1.HitCanvas({ pixelRatio: 1, width: width, height: height }), sceneContext = cachedSceneCanvas.getContext(), hitContext = cachedHitCanvas.getContext(); cachedHitCanvas.isCache = true; this._cache.delete('canvas'); this._filterUpToDate = false; if (conf.imageSmoothingEnabled === false) { cachedSceneCanvas.getContext()._context.imageSmoothingEnabled = false; cachedFilterCanvas.getContext()._context.imageSmoothingEnabled = false; cachedHitCanvas.getContext()._context.imageSmoothingEnabled = false; } sceneContext.save(); hitContext.save(); sceneContext.translate(-x, -y); hitContext.translate(-x, -y); this._isUnderCache = true; this._clearSelfAndDescendantCache(ABSOLUTE_OPACITY); this._clearSelfAndDescendantCache(ABSOLUTE_SCALE); this.drawScene(cachedSceneCanvas, this, true); this.drawHit(cachedHitCanvas, this, true); this._isUnderCache = false; sceneContext.restore(); hitContext.restore(); if (drawBorder) { sceneContext.save(); sceneContext.beginPath(); sceneContext.rect(0, 0, width, height); sceneContext.closePath(); sceneContext.setAttr('strokeStyle', 'red'); sceneContext.setAttr('lineWidth', 5); sceneContext.stroke(); sceneContext.restore(); } this._cache.set(CANVAS, { scene: cachedSceneCanvas, filter: cachedFilterCanvas, hit: cachedHitCanvas, x: x, y: y }); return this; }; Node.prototype.getClientRect = function (config) { throw new Error('abstract "getClientRect" method call'); }; Node.prototype._transformedRect = function (rect, top) { var points = [ { x: rect.x, y: rect.y }, { x: rect.x + rect.width, y: rect.y }, { x: rect.x + rect.width, y: rect.y + rect.height }, { x: rect.x, y: rect.y + rect.height } ]; var minX, minY, maxX, maxY; var trans = this.getAbsoluteTransform(top); points.forEach(function (point) { var transformed = trans.point(point); if (minX === undefined) { minX = maxX = transformed.x; minY = maxY = transformed.y; } minX = Math.min(minX, transformed.x); minY = Math.min(minY, transformed.y); maxX = Math.max(maxX, transformed.x); maxY = Math.max(maxY, transformed.y); }); return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }; }; Node.prototype._drawCachedSceneCanvas = function (context) { context.save(); context._applyOpacity(this); context._applyGlobalCompositeOperation(this); var canvasCache = this._getCanvasCache(); context.translate(canvasCache.x, canvasCache.y); var cacheCanvas = this._getCachedSceneCanvas(); var ratio = cacheCanvas.pixelRatio; context.drawImage(cacheCanvas._canvas, 0, 0, cacheCanvas.width / ratio, cacheCanvas.height / ratio); context.restore(); }; Node.prototype._drawCachedHitCanvas = function (context) { var canvasCache = this._getCanvasCache(), hitCanvas = canvasCache.hit; context.save(); context._applyGlobalCompositeOperation(this); context.translate(canvasCache.x, canvasCache.y); context.drawImage(hitCanvas._canvas, 0, 0); context.restore(); }; Node.prototype._getCachedSceneCanvas = function () { var filters = this.filters(), cachedCanvas = this._getCanvasCache(), sceneCanvas = cachedCanvas.scene, filterCanvas = cachedCanvas.filter, filterContext = filterCanvas.getContext(), len, imageData, n, filter; if (filters) { if (!this._filterUpToDate) { var ratio = sceneCanvas.pixelRatio; try { len = filters.length; filterContext.clear(); filterContext.drawImage(sceneCanvas._canvas, 0, 0, sceneCanvas.getWidth() / ratio, sceneCanvas.getHeight() / ratio); imageData = filterContext.getImageData(0, 0, filterCanvas.getWidth(), filterCanvas.getHeight()); for (n = 0; n < len; n++) { filter = filters[n]; if (typeof filter !== 'function') { Util_1.Util.error('Filter should be type of function, but got ' + typeof filter + ' insted. Please check correct filters'); continue; } filter.call(this, imageData); filterContext.putImageData(imageData, 0, 0); } } catch (e) { Util_1.Util.error('Unable to apply filter. ' + e.message); } this._filterUpToDate = true; } return filterCanvas; } return sceneCanvas; }; Node.prototype.on = function (evtStr, handler) { if (arguments.length === 3) { return this._delegate.apply(this, arguments); } var events = evtStr.split(SPACE), len = events.length, n, event, parts, baseEvent, name; for (n = 0; n < len; n++) { event = events[n]; parts = event.split('.'); baseEvent = parts[0]; name = parts[1] || ''; if (!this.eventListeners[baseEvent]) { this.eventListeners[baseEvent] = []; } this.eventListeners[baseEvent].push({ name: name, handler: handler }); } return this; }; Node.prototype.off = function (evtStr, callback) { var events = (evtStr || '').split(SPACE), len = events.length, n, t, event, parts, baseEvent, name; if (!evtStr) { for (t in this.eventListeners) { this._off(t); } } for (n = 0; n < len; n++) { event = events[n]; parts = event.split('.'); baseEvent = parts[0]; name = parts[1]; if (baseEvent) { if (this.eventListeners[baseEvent]) { this._off(baseEvent, name, callback); } } else { for (t in this.eventListeners) { this._off(t, name, callback); } } } return this; }; Node.prototype.dispatchEvent = function (evt) { var e = { target: this, type: evt.type, evt: evt }; this.fire(evt.type, e); return this; }; Node.prototype.addEventListener = function (type, handler) { this.on(type, function (evt) { handler.call(this, evt.evt); }); return this; }; Node.prototype.removeEventListener = function (type) { this.off(type); return this; }; Node.prototype._delegate = function (event, selector, handler) { var stopNode = this; this.on(event, function (evt) { var targets = evt.target.findAncestors(selector, true, stopNode); for (var i = 0; i < targets.length; i++) { evt = Util_1.Util.cloneObject(evt); evt.currentTarget = targets[i]; handler.call(targets[i], evt); } }); }; Node.prototype.remove = function () { if (this.isDragging()) { this.stopDrag(); } DragAndDrop_1.DD._dragElements.delete(this._id); this._remove(); return this; }; Node.prototype._remove = function () { this._clearSelfAndDescendantCache(STAGE); this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM); this._clearSelfAndDescendantCache(VISIBLE); this._clearSelfAndDescendantCache(LISTENING); this._clearSelfAndDescendantCache(ABSOLUTE_OPACITY); var parent = this.getParent(); if (parent && parent.children) { parent.children.splice(this.index, 1); parent._setChildrenIndices(); this.parent = null; } }; Node.prototype.destroy = function () { exports._removeId(this.id(), this); var names = (this.name() || '').split(/\s/g); for (var i = 0; i < names.length; i++) { var subname = names[i]; exports._removeName(subname, this._id); } this.remove(); return this; }; Node.prototype.getAttr = function (attr) { var method = 'get' + Util_1.Util._capitalize(attr); if (Util_1.Util._isFunction(this[method])) { return this[method](); } return this.attrs[attr]; }; Node.prototype.getAncestors = function () { var parent = this.getParent(), ancestors = new Util_1.Collection(); while (parent) { ancestors.push(parent); parent = parent.getParent(); } return ancestors; }; Node.prototype.getAttrs = function () { return this.attrs || {}; }; Node.prototype.setAttrs = function (config) { var key, method; if (!config) { return this; } for (key in config) { if (key === CHILDREN) { continue; } method = SET + Util_1.Util._capitalize(key); if (Util_1.Util._isFunction(this[method])) { this[method](config[key]); } else { this._setAttr(key, config[key]); } } return this; }; Node.prototype.isListening = function () { return this._getCache(LISTENING, this._isListening); }; Node.prototype._isListening = function () { var listening = this.listening(), parent = this.getParent(); if (listening === 'inherit') { if (parent) { return parent.isListening(); } else { return true; } } else { return listening; } }; Node.prototype.isVisible = function () { return this._getCache(VISIBLE, this._isVisible); }; Node.prototype._isVisible = function (relativeTo) { var visible = this.visible(), parent = this.getParent(); if (visible === 'inherit') { if (parent && parent !== relativeTo) { return parent._isVisible(relativeTo); } else { return true; } } else { return visible; } }; Node.prototype.shouldDrawHit = function () { var layer = this.getLayer(); return ((!layer && this.isListening() && this.isVisible()) || (layer && layer.hitGraphEnabled() && this.isListening() && this.isVisible())); }; Node.prototype.show = function () { this.visible(true); return this; }; Node.prototype.hide = function () { this.visible(false); return this; }; Node.prototype.getZIndex = function () { return this.index || 0; }; Node.prototype.getAbsoluteZIndex = function () { var depth = this.getDepth(), that = this, index = 0, nodes, len, n, child; function addChildren(children) { nodes = []; len = children.length; for (n = 0; n < len; n++) { child = children[n]; index++; if (child.nodeType !== SHAPE) { nodes = nodes.concat(child.getChildren().toArray()); } if (child._id === that._id) { n = len; } } if (nodes.length > 0 && nodes[0].getDepth() <= depth) { addChildren(nodes); } } if (that.nodeType !== UPPER_STAGE) { addChildren(that.getStage().getChildren()); } return index; }; Node.prototype.getDepth = function () { var depth = 0, parent = this.parent; while (parent) { depth++; parent = parent.parent; } return depth; }; Node.prototype.setPosition = function (pos) { this.x(pos.x); this.y(pos.y); return this; }; Node.prototype.getPosition = function () { return { x: this.x(), y: this.y() }; }; Node.prototype.getAbsolutePosition = function (top) { var absoluteMatrix = this.getAbsoluteTransform(top).getMatrix(), absoluteTransform = new Util_1.Transform(), offset = this.offset(); absoluteTransform.m = absoluteMatrix.slice(); absoluteTransform.translate(offset.x, offset.y); return absoluteTransform.getTranslation(); }; Node.prototype.setAbsolutePosition = function (pos) { var origTrans = this._clearTransform(), it; this.attrs.x = origTrans.x; this.attrs.y = origTrans.y; delete origTrans.x; delete origTrans.y; it = this.getAbsoluteTransform(); it.invert(); it.translate(pos.x, pos.y); pos = { x: this.attrs.x + it.getTranslation().x, y: this.attrs.y + it.getTranslation().y }; this.setPosition({ x: pos.x, y: pos.y }); this._setTransform(origTrans); return this; }; Node.prototype._setTransform = function (trans) { var key; for (key in trans) { this.attrs[key] = trans[key]; } this._clearCache(TRANSFORM); this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM); }; Node.prototype._clearTransform = function () { var trans = { x: this.x(), y: this.y(), rotation: this.rotation(), scaleX: this.scaleX(), scaleY: this.scaleY(), offsetX: this.offsetX(), offsetY: this.offsetY(), skewX: this.skewX(), skewY: this.skewY() }; this.attrs.x = 0; this.attrs.y = 0; this.attrs.rotation = 0; this.attrs.scaleX = 1; this.attrs.scaleY = 1; this.attrs.offsetX = 0; this.attrs.offsetY = 0; this.attrs.skewX = 0; this.attrs.skewY = 0; this._clearCache(TRANSFORM); this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM); return trans; }; Node.prototype.move = function (change) { var changeX = change.x, changeY = change.y, x = this.x(), y = this.y(); if (changeX !== undefined) { x += changeX; } if (changeY !== undefined) { y += changeY; } this.setPosition({ x: x, y: y }); return this; }; Node.prototype._eachAncestorReverse = function (func, top) { var family = [], parent = this.getParent(), len, n; if (top && top._id === this._id) { func(this); return; } family.unshift(this); while (parent && (!top || parent._id !== top._id)) { family.unshift(parent); parent = parent.parent; } len = family.length; for (n = 0; n < len; n++) { func(family[n]); } }; Node.prototype.rotate = function (theta) { this.rotation(this.rotation() + theta); return this; }; Node.prototype.moveToTop = function () { if (!this.parent) { Util_1.Util.warn('Node has no parent. moveToTop function is ignored.'); return false; } var index = this.index; this.parent.children.splice(index, 1); this.parent.children.push(this); this.parent._setChildrenIndices(); return true; }; Node.prototype.moveUp = function () { if (!this.parent) { Util_1.Util.warn('Node has no parent. moveUp function is ignored.'); return false; } var index = this.index, len = this.parent.getChildren().length; if (index < len - 1) { this.parent.children.splice(index, 1); this.parent.children.splice(index + 1, 0, this); this.parent._setChildrenIndices(); return true; } return false; }; Node.prototype.moveDown = function () { if (!this.parent) { Util_1.Util.warn('Node has no parent. moveDown function is ignored.'); return false; } 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; } return false; }; Node.prototype.moveToBottom = function () { if (!this.parent) { Util_1.Util.warn('Node has no parent. moveToBottom function is ignored.'); return false; } var index = this.index; if (index > 0) { this.parent.children.splice(index, 1); this.parent.children.unshift(this); this.parent._setChildrenIndices(); return true; } return false; }; Node.prototype.setZIndex = function (zIndex) { if (!this.parent) { Util_1.Util.warn('Node has no parent. zIndex parameter is ignored.'); return this; } if (zIndex < 0 || zIndex >= this.parent.children.length) { Util_1.Util.warn('Unexpected value ' + zIndex + ' for zIndex property. zIndex is just index of a node in children of its parent. Expected value is from 0 to ' + (this.parent.children.length - 1) + '.'); } var index = this.index; this.parent.children.splice(index, 1); this.parent.children.splice(zIndex, 0, this); this.parent._setChildrenIndices(); return this; }; Node.prototype.getAbsoluteOpacity = function () { return this._getCache(ABSOLUTE_OPACITY, this._getAbsoluteOpacity); }; Node.prototype._getAbsoluteOpacity = function () { var absOpacity = this.opacity(); var parent = this.getParent(); if (parent && !parent._isUnderCache) { absOpacity *= parent.getAbsoluteOpacity(); } return absOpacity; }; Node.prototype.moveTo = function (newContainer) { if (this.getParent() !== newContainer) { this._remove(); newContainer.add(this); } return this; }; Node.prototype.toObject = function () { var obj = {}, attrs = this.getAttrs(), key, val, getter, defaultValue, nonPlainObject; obj.attrs = {}; for (key in attrs) { val = attrs[key]; nonPlainObject = Util_1.Util.isObject(val) && !Util_1.Util._isPlainObject(val) && !Util_1.Util._isArray(val); if (nonPlainObject) { continue; } getter = typeof this[key] === 'function' && this[key]; delete attrs[key]; defaultValue = getter ? getter.call(this) : null; attrs[key] = val; if (defaultValue !== val) { obj.attrs[key] = val; } } obj.className = this.getClassName(); return Util_1.Util._prepareToStringify(obj); }; Node.prototype.toJSON = function () { return JSON.stringify(this.toObject()); }; Node.prototype.getParent = function () { return this.parent; }; Node.prototype.findAncestors = function (selector, includeSelf, stopNode) { var res = []; if (includeSelf && this._isMatch(selector)) { res.push(this); } var ancestor = this.parent; while (ancestor) { if (ancestor === stopNode) { return res; } if (ancestor._isMatch(selector)) { res.push(ancestor); } ancestor = ancestor.parent; } return res; }; Node.prototype.isAncestorOf = function (node) { return false; }; Node.prototype.findAncestor = function (selector, includeSelf, stopNode) { return this.findAncestors(selector, includeSelf, stopNode)[0]; }; Node.prototype._isMatch = function (selector) { if (!selector) { return false; } if (typeof selector === 'function') { return selector(this); } var selectorArr = selector.replace(/ /g, '').split(','), len = selectorArr.length, n, sel; for (n = 0; n < len; n++) { sel = selectorArr[n]; if (!Util_1.Util.isValidSelector(sel)) { Util_1.Util.warn('Selector "' + sel + '" is invalid. Allowed selectors examples are "#foo", ".bar" or "Group".'); Util_1.Util.warn('If you have a custom shape with such className, please change it to start with upper letter like "Triangle".'); Util_1.Util.warn('Konva is awesome, right?'); } if (sel.charAt(0) === '#') { if (this.id() === sel.slice(1)) { return true; } } else if (sel.charAt(0) === '.') { if (this.hasName(sel.slice(1))) { return true; } } else if (this.className === selector || this.nodeType === selector) { return true; } } return false; }; Node.prototype.getLayer = function () { var parent = this.getParent(); return parent ? parent.getLayer() : null; }; Node.prototype.getStage = function () { return this._getCache(STAGE, this._getStage); }; Node.prototype._getStage = function () { var parent = this.getParent(); if (parent) { return parent.getStage(); } else { return undefined; } }; Node.prototype.fire = function (eventType, evt, bubble) { evt = evt || {}; evt.target = evt.target || this; if (bubble) { this._fireAndBubble(eventType, evt); } else { this._fire(eventType, evt); } return this; }; Node.prototype.getAbsoluteTransform = function (top) { if (top) { return this._getAbsoluteTransform(top); } else { return this._getCache(ABSOLUTE_TRANSFORM, this._getAbsoluteTransform); } }; Node.prototype._getAbsoluteTransform = function (top) { var at = new Util_1.Transform(); this._eachAncestorReverse(function (node) { var transformsEnabled = node.getTransformsEnabled(); if (transformsEnabled === 'all') { at.multiply(node.getTransform()); } else if (transformsEnabled === 'position') { at.translate(node.getX() - node.getOffsetX(), node.getY() - node.getOffsetY()); } }, top); return at; }; Node.prototype.getAbsoluteScale = function (top) { if (top) { return this._getAbsoluteScale(top); } else { return this._getCache(ABSOLUTE_SCALE, this._getAbsoluteScale); } }; Node.prototype._getAbsoluteScale = function (top) { var parent = this; while (parent) { if (parent._isUnderCache) { top = parent; } parent = parent.getParent(); } var scaleX = 1, scaleY = 1; this._eachAncestorReverse(function (node) { scaleX *= node.scaleX(); scaleY *= node.scaleY(); }, top); return { x: scaleX, y: scaleY }; }; Node.prototype.getTransform = function () { return this._getCache(TRANSFORM, this._getTransform); }; Node.prototype._getTransform = function () { var m = new Util_1.Transform(), x = this.x(), y = this.y(), rotation = Global_1.Konva.getAngle(this.rotation()), scaleX = this.scaleX(), scaleY = this.scaleY(), skewX = this.skewX(), skewY = this.skewY(), offsetX = this.offsetX(), offsetY = this.offsetY(); if (x !== 0 || y !== 0) { m.translate(x, y); } if (rotation !== 0) { m.rotate(rotation); } if (skewX !== 0 || skewY !== 0) { m.skew(skewX, skewY); } if (scaleX !== 1 || scaleY !== 1) { m.scale(scaleX, scaleY); } if (offsetX !== 0 || offsetY !== 0) { m.translate(-1 * offsetX, -1 * offsetY); } return m; }; Node.prototype.clone = function (obj) { var attrs = Util_1.Util.cloneObject(this.attrs), key, allListeners, len, n, listener; for (var i in CLONE_BLACK_LIST) { var blockAttr = CLONE_BLACK_LIST[i]; delete attrs[blockAttr]; } for (key in obj) { attrs[key] = obj[key]; } var node = new this.constructor(attrs); for (key in this.eventListeners) { allListeners = this.eventListeners[key]; len = allListeners.length; for (n = 0; n < len; n++) { listener = allListeners[n]; if (listener.name.indexOf(KONVA) < 0) { if (!node.eventListeners[key]) { node.eventListeners[key] = []; } node.eventListeners[key].push(listener); } } } return node; }; Node.prototype._toKonvaCanvas = function (config) { config = config || {}; var box = this.getClientRect(); var stage = this.getStage(), x = config.x !== undefined ? config.x : box.x, y = config.y !== undefined ? config.y : box.y, pixelRatio = config.pixelRatio || 1, canvas = new Canvas_1.SceneCanvas({ width: config.width || box.width || (stage ? stage.width() : 0), height: config.height || box.height || (stage ? stage.height() : 0), pixelRatio: pixelRatio }), context = canvas.getContext(); context.save(); if (x || y) { context.translate(-1 * x, -1 * y); } this.drawScene(canvas); context.restore(); return canvas; }; Node.prototype.toCanvas = function (config) { return this._toKonvaCanvas(config)._canvas; }; Node.prototype.toDataURL = function (config) { config = config || {}; var mimeType = config.mimeType || null, quality = config.quality || null; var url = this._toKonvaCanvas(config).toDataURL(mimeType, quality); if (config.callback) { config.callback(url); } return url; }; Node.prototype.toImage = function (config) { if (!config || !config.callback) { throw 'callback required for toImage method config argument'; } var callback = config.callback; delete config.callback; Util_1.Util._urlToImage(this.toDataURL(config), function (img) { callback(img); }); }; Node.prototype.setSize = function (size) { this.width(size.width); this.height(size.height); return this; }; Node.prototype.getSize = function () { return { width: this.width(), height: this.height() }; }; Node.prototype.getClassName = function () { return this.className || this.nodeType; }; Node.prototype.getType = function () { return this.nodeType; }; Node.prototype.getDragDistance = function () { if (this.attrs.dragDistance !== undefined) { return this.attrs.dragDistance; } else if (this.parent) { return this.parent.getDragDistance(); } else { return Global_1.Konva.dragDistance; } }; Node.prototype._off = function (type, name, callback) { var evtListeners = this.eventListeners[type], i, evtName, handler; for (i = 0; i < evtListeners.length; i++) { evtName = evtListeners[i].name; handler = evtListeners[i].handler; if ((evtName !== 'konva' || name === 'konva') && (!name || evtName === name) && (!callback || callback === handler)) { evtListeners.splice(i, 1); if (evtListeners.length === 0) { delete this.eventListeners[type]; break; } i--; } } }; Node.prototype._fireChangeEvent = function (attr, oldVal, newVal) { this._fire(attr + CHANGE, { oldVal: oldVal, newVal: newVal }); }; Node.prototype.setId = function (id) { var oldId = this.id(); exports._removeId(oldId, this); _addId(this, id); this._setAttr('id', id); return this; }; Node.prototype.setName = function (name) { var oldNames = (this.name() || '').split(/\s/g); var newNames = (name || '').split(/\s/g); var subname, i; for (i = 0; i < oldNames.length; i++) { subname = oldNames[i]; if (newNames.indexOf(subname) === -1 && subname) { exports._removeName(subname, this._id); } } for (i = 0; i < newNames.length; i++) { subname = newNames[i]; if (oldNames.indexOf(subname) === -1 && subname) { exports._addName(this, subname); } } this._setAttr(NAME, name); return this; }; Node.prototype.addName = function (name) { if (!this.hasName(name)) { var oldName = this.name(); var newName = oldName ? oldName + ' ' + name : name; this.setName(newName); } return this; }; Node.prototype.hasName = function (name) { if (!name) { return false; } var fullName = this.name(); if (!fullName) { return false; } var names = (fullName || '').split(/\s/g); return names.indexOf(name) !== -1; }; Node.prototype.removeName = function (name) { var names = (this.name() || '').split(/\s/g); var index = names.indexOf(name); if (index !== -1) { names.splice(index, 1); this.setName(names.join(' ')); } return this; }; Node.prototype.setAttr = function (attr, val) { var func = this[SET + Util_1.Util._capitalize(attr)]; if (Util_1.Util._isFunction(func)) { func.call(this, val); } else { this._setAttr(attr, val); } return this; }; Node.prototype._setAttr = function (key, val) { var oldVal = this.attrs[key]; if (oldVal === val && !Util_1.Util.isObject(val)) { return; } if (val === undefined || val === null) { delete this.attrs[key]; } else { this.attrs[key] = val; } this._fireChangeEvent(key, oldVal, val); }; Node.prototype._setComponentAttr = function (key, component, val) { var oldVal; if (val !== undefined) { oldVal = this.attrs[key]; if (!oldVal) { this.attrs[key] = this.getAttr(key); } this.attrs[key][component] = val; this._fireChangeEvent(key, oldVal, val); } }; Node.prototype._fireAndBubble = function (eventType, evt, compareShape) { if (evt && this.nodeType === SHAPE) { evt.target = this; } var shouldStop = (eventType === MOUSEENTER || eventType === MOUSELEAVE) && ((compareShape && (this === compareShape || (this.isAncestorOf && this.isAncestorOf(compareShape)))) || (this.nodeType === 'Stage' && !compareShape)); if (!shouldStop) { this._fire(eventType, evt); var stopBubble = (eventType === MOUSEENTER || eventType === MOUSELEAVE) && (compareShape && compareShape.isAncestorOf && compareShape.isAncestorOf(this) && !compareShape.isAncestorOf(this.parent)); if (((evt && !evt.cancelBubble) || !evt) && this.parent && this.parent.isListening() && !stopBubble) { if (compareShape && compareShape.parent) { this._fireAndBubble.call(this.parent, eventType, evt, compareShape.parent); } else { this._fireAndBubble.call(this.parent, eventType, evt); } } } }; Node.prototype._fire = function (eventType, evt) { var events = this.eventListeners[eventType], i; if (events) { evt = evt || {}; evt.currentTarget = this; evt.type = eventType; for (i = 0; i < events.length; i++) { events[i].handler.call(this, evt); } } }; Node.prototype.draw = function () { this.drawScene(); this.drawHit(); return this; }; Node.prototype.startDrag = function (evt) { var forceDrag = !evt; var pointerId = evt ? evt.pointerId : undefined; var stage = this.getStage(), pos = stage._getPointerById(pointerId), ap = this.getAbsolutePosition(); if (pos || forceDrag) { DragAndDrop_1.DD._dragElements.set(this._id, { node: this, startPointerPos: pos, offset: forceDrag ? { x: 0, y: 0 } : { x: pos.x - ap.x, y: pos.y - ap.y }, isDragging: forceDrag ? true : false, pointerId: pointerId, dragStopped: false }); } }; Node.prototype._setDragPosition = function (evt, elem) { var pos = this.getStage()._getPointerById(elem.pointerId); var dbf = this.dragBoundFunc(); if (!pos) { return; } var newNodePos = { x: pos.x - elem.offset.x, y: pos.y - elem.offset.y }; if (dbf !== undefined) { newNodePos = dbf.call(this, newNodePos, evt); } if (!this._lastPos || this._lastPos.x !== newNodePos.x || this._lastPos.y !== newNodePos.y) { this.setAbsolutePosition(newNodePos); if (this.getLayer()) { this.getLayer().batchDraw(); } else if (this.getStage()) { this.getStage().batchDraw(); } } this._lastPos = newNodePos; }; Node.prototype.stopDrag = function () { var evt = {}; DragAndDrop_1.DD._dragElements.get(this._id).dragStopped = true; DragAndDrop_1.DD._endDragBefore(evt); DragAndDrop_1.DD._endDragAfter(evt); }; Node.prototype.setDraggable = function (draggable) { this._setAttr('draggable', draggable); this._dragChange(); }; Node.prototype.isDragging = function () { var elem = DragAndDrop_1.DD._dragElements.get(this._id); return elem ? elem.isDragging : false; }; Node.prototype._listenDrag = function () { this._dragCleanup(); this.on('mousedown.konva touchstart.konva', function (evt) { var shouldCheckButton = evt.evt['button'] !== undefined; var canDrag = !shouldCheckButton || Global_1.Konva.dragButtons.indexOf(evt.evt['button']) >= 0; if (!canDrag) { return; } if (this.isDragging()) { return; } this.startDrag(evt); }); }; Node.prototype._dragChange = function () { if (this.attrs.draggable) { this._listenDrag(); } else { this._dragCleanup(); var stage = this.getStage(); if (stage && DragAndDrop_1.DD._dragElements.has(this._id)) { this.stopDrag(); } } }; Node.prototype._dragCleanup = function () { this.off('mousedown.konva'); this.off('touchstart.konva'); }; Node.create = function (data, container) { if (Util_1.Util._isString(data)) { data = JSON.parse(data); } return this._createNode(data, container); }; Node._createNode = function (obj, container) { var className = Node.prototype.getClassName.call(obj), children = obj.children, no, len, n; if (container) { obj.attrs.container = container; } if (!Global_1._NODES_REGISTRY[className]) { Util_1.Util.warn('Can not find a node with class name "' + className + '". Fallback to "Shape".'); className = 'Shape'; } var Class = Global_1._NODES_REGISTRY[className]; no = new Class(obj.attrs); if (children) { len = children.length; for (n = 0; n < len; n++) { no.add(Node._createNode(children[n])); } } return no; }; return Node; }()); exports.Node = Node; Node.prototype.nodeType = 'Node'; Node.prototype._attrsAffectingSize = []; Factory_1.Factory.addGetterSetter(Node, 'zIndex'); Factory_1.Factory.addGetterSetter(Node, 'absolutePosition'); Factory_1.Factory.addGetterSetter(Node, 'position'); Factory_1.Factory.addGetterSetter(Node, 'x', 0, Validators_1.getNumberValidator()); Factory_1.Factory.addGetterSetter(Node, 'y', 0, Validators_1.getNumberValidator()); Factory_1.Factory.addGetterSetter(Node, 'globalCompositeOperation', 'source-over', Validators_1.getStringValidator()); Factory_1.Factory.addGetterSetter(Node, 'opacity', 1, Validators_1.getNumberValidator()); Factory_1.Factory.addGetterSetter(Node, 'name', '', Validators_1.getStringValidator()); Factory_1.Factory.addGetterSetter(Node, 'id', '', Validators_1.getStringValidator()); Factory_1.Factory.addGetterSetter(Node, 'rotation', 0, Validators_1.getNumberValidator()); Factory_1.Factory.addComponentsGetterSetter(Node, 'scale', ['x', 'y']); Factory_1.Factory.addGetterSetter(Node, 'scaleX', 1, Validators_1.getNumberValidator()); Factory_1.Factory.addGetterSetter(Node, 'scaleY', 1, Validators_1.getNumberValidator()); Factory_1.Factory.addComponentsGetterSetter(Node, 'skew', ['x', 'y']); Factory_1.Factory.addGetterSetter(Node, 'skewX', 0, Validators_1.getNumberValidator()); Factory_1.Factory.addGetterSetter(Node, 'skewY', 0, Validators_1.getNumberValidator()); Factory_1.Factory.addComponentsGetterSetter(Node, 'offset', ['x', 'y']); Factory_1.Factory.addGetterSetter(Node, 'offsetX', 0, Validators_1.getNumberValidator()); Factory_1.Factory.addGetterSetter(Node, 'offsetY', 0, Validators_1.getNumberValidator()); Factory_1.Factory.addGetterSetter(Node, 'dragDistance', null, Validators_1.getNumberValidator()); Factory_1.Factory.addGetterSetter(Node, 'width', 0, Validators_1.getNumberValidator()); Factory_1.Factory.addGetterSetter(Node, 'height', 0, Validators_1.getNumberValidator()); Factory_1.Factory.addGetterSetter(Node, 'listening', 'inherit', function (val) { var isValid = val === true || val === false || val === 'inherit'; if (!isValid) { Util_1.Util.warn(val + ' is a not valid value for "listening" attribute. The value may be true, false or "inherit".'); } return val; }); Factory_1.Factory.addGetterSetter(Node, 'preventDefault', true, Validators_1.getBooleanValidator()); Factory_1.Factory.addGetterSetter(Node, 'filters', null, function (val) { this._filterUpToDate = false; return val; }); Factory_1.Factory.addGetterSetter(Node, 'visible', 'inherit', function (val) { var isValid = val === true || val === false || val === 'inherit'; if (!isValid) { Util_1.Util.warn(val + ' is a not valid value for "visible" attribute. The value may be true, false or "inherit".'); } return val; }); Factory_1.Factory.addGetterSetter(Node, 'transformsEnabled', 'all', Validators_1.getStringValidator()); Factory_1.Factory.addGetterSetter(Node, 'size'); Factory_1.Factory.addGetterSetter(Node, 'dragBoundFunc'); Factory_1.Factory.addGetterSetter(Node, 'draggable', false, Validators_1.getBooleanValidator()); Factory_1.Factory.backCompat(Node, { rotateDeg: 'rotate', setRotationDeg: 'setRotation', getRotationDeg: 'getRotation' }); Util_1.Collection.mapMethods(Node);