2014-02-27 08:49:18 +08:00
|
|
|
/*jshint unused:false */
|
2012-12-02 04:04:10 +08:00
|
|
|
(function() {
|
2013-03-22 11:24:03 +08:00
|
|
|
// CONSTANTS
|
2013-03-24 14:50:51 +08:00
|
|
|
var STAGE = 'Stage',
|
|
|
|
STRING = 'string',
|
|
|
|
PX = 'px',
|
2013-09-21 07:17:32 +08:00
|
|
|
|
2013-03-24 14:50:51 +08:00
|
|
|
MOUSEOUT = 'mouseout',
|
|
|
|
MOUSELEAVE = 'mouseleave',
|
|
|
|
MOUSEOVER = 'mouseover',
|
|
|
|
MOUSEENTER = 'mouseenter',
|
|
|
|
MOUSEMOVE = 'mousemove',
|
|
|
|
MOUSEDOWN = 'mousedown',
|
|
|
|
MOUSEUP = 'mouseup',
|
|
|
|
CLICK = 'click',
|
|
|
|
DBL_CLICK = 'dblclick',
|
2013-06-02 13:03:02 +08:00
|
|
|
TOUCHSTART = 'touchstart',
|
|
|
|
TOUCHEND = 'touchend',
|
2013-03-24 14:50:51 +08:00
|
|
|
TAP = 'tap',
|
|
|
|
DBL_TAP = 'dbltap',
|
|
|
|
TOUCHMOVE = 'touchmove',
|
2014-05-01 21:11:03 +08:00
|
|
|
DOMMOUSESCROLL = 'DOMMouseScroll',
|
|
|
|
MOUSEWHEEL = 'mousewheel',
|
|
|
|
WHEEL = 'wheel',
|
2013-09-21 07:17:32 +08:00
|
|
|
|
|
|
|
CONTENT_MOUSEOUT = 'contentMouseout',
|
|
|
|
CONTENT_MOUSEOVER = 'contentMouseover',
|
|
|
|
CONTENT_MOUSEMOVE = 'contentMousemove',
|
|
|
|
CONTENT_MOUSEDOWN = 'contentMousedown',
|
|
|
|
CONTENT_MOUSEUP = 'contentMouseup',
|
|
|
|
CONTENT_CLICK = 'contentClick',
|
|
|
|
CONTENT_DBL_CLICK = 'contentDblclick',
|
|
|
|
CONTENT_TOUCHSTART = 'contentTouchstart',
|
|
|
|
CONTENT_TOUCHEND = 'contentTouchend',
|
|
|
|
CONTENT_DBL_TAP = 'contentDbltap',
|
|
|
|
CONTENT_TOUCHMOVE = 'contentTouchmove',
|
|
|
|
|
2013-03-24 14:50:51 +08:00
|
|
|
DIV = 'div',
|
|
|
|
RELATIVE = 'relative',
|
2015-01-27 16:13:43 +08:00
|
|
|
KONVA_CONTENT = 'konvajs-content',
|
2013-03-24 14:50:51 +08:00
|
|
|
SPACE = ' ',
|
2013-06-01 14:11:21 +08:00
|
|
|
UNDERSCORE = '_',
|
2013-03-24 14:50:51 +08:00
|
|
|
CONTAINER = 'container',
|
2013-06-09 05:29:58 +08:00
|
|
|
EMPTY_STRING = '',
|
2014-05-01 21:11:03 +08:00
|
|
|
EVENTS = [MOUSEDOWN, MOUSEMOVE, MOUSEUP, MOUSEOUT, TOUCHSTART, TOUCHMOVE, TOUCHEND, MOUSEOVER, DOMMOUSESCROLL, MOUSEWHEEL, WHEEL],
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-11-28 13:34:06 +08:00
|
|
|
// cached variables
|
|
|
|
eventsLength = EVENTS.length;
|
2013-04-08 16:02:08 +08:00
|
|
|
|
|
|
|
function addEvent(ctx, eventName) {
|
2014-02-27 08:49:18 +08:00
|
|
|
ctx.content.addEventListener(eventName, function(evt) {
|
|
|
|
ctx[UNDERSCORE + eventName](evt);
|
|
|
|
}, false);
|
2013-04-08 16:02:08 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2015-04-08 23:26:43 +08:00
|
|
|
/**
|
|
|
|
* Stage constructor. A stage is used to contain multiple layers
|
|
|
|
* @constructor
|
|
|
|
* @memberof Konva
|
|
|
|
* @augments Konva.Container
|
|
|
|
* @param {Object} config
|
|
|
|
* @param {String|Element} config.container Container id or DOM element
|
|
|
|
* @@nodeParams
|
|
|
|
* @example
|
|
|
|
* var stage = new Konva.Stage({
|
|
|
|
* width: 500,
|
|
|
|
* height: 800,
|
|
|
|
* container: 'containerId'
|
|
|
|
* });
|
|
|
|
*/
|
|
|
|
Konva.Stage = function(config) {
|
|
|
|
this.___init(config);
|
|
|
|
};
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Util.addMethods(Konva.Stage, {
|
2013-07-23 12:41:41 +08:00
|
|
|
___init: function(config) {
|
2013-09-29 12:55:57 +08:00
|
|
|
this.nodeType = STAGE;
|
2012-12-02 04:04:10 +08:00
|
|
|
// call super constructor
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Container.call(this, config);
|
|
|
|
this._id = Konva.idCounter++;
|
2012-12-02 04:04:10 +08:00
|
|
|
this._buildDOM();
|
|
|
|
this._bindContentEvents();
|
2013-12-06 14:29:50 +08:00
|
|
|
this._enableNestedTransforms = false;
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.stages.push(this);
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
2013-07-23 13:47:13 +08:00
|
|
|
_validateAdd: function(child) {
|
|
|
|
if (child.getType() !== 'Layer') {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Util.error('You may only add layers to the stage.');
|
2013-07-23 13:47:13 +08:00
|
|
|
}
|
|
|
|
},
|
2012-12-17 12:52:07 +08:00
|
|
|
/**
|
|
|
|
* set container dom element which contains the stage wrapper div element
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2012-12-17 12:52:07 +08:00
|
|
|
* @param {DomElement} container can pass in a dom element or id string
|
|
|
|
*/
|
2012-12-02 04:04:10 +08:00
|
|
|
setContainer: function(container) {
|
2013-03-24 14:50:51 +08:00
|
|
|
if( typeof container === STRING) {
|
2014-03-01 17:45:35 +08:00
|
|
|
var id = container;
|
2015-01-27 15:07:51 +08:00
|
|
|
container = Konva.document.getElementById(container);
|
2014-03-01 17:45:35 +08:00
|
|
|
if (!container) {
|
|
|
|
throw 'Can not find container in document with id ' + id;
|
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
2013-05-15 13:37:33 +08:00
|
|
|
this._setAttr(CONTAINER, container);
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
2013-12-10 14:31:18 +08:00
|
|
|
shouldDrawHit: function() {
|
|
|
|
return true;
|
|
|
|
},
|
2013-03-24 11:02:11 +08:00
|
|
|
draw: function() {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Node.prototype.draw.call(this);
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2013-03-24 11:02:11 +08:00
|
|
|
},
|
2012-12-02 04:04:10 +08:00
|
|
|
/**
|
2012-12-17 12:52:07 +08:00
|
|
|
* draw layer scene graphs
|
2012-12-02 04:04:10 +08:00
|
|
|
* @name draw
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2012-12-02 04:04:10 +08:00
|
|
|
*/
|
2012-10-08 10:14:14 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
/**
|
2012-12-17 12:52:07 +08:00
|
|
|
* draw layer hit graphs
|
2012-12-02 04:04:10 +08:00
|
|
|
* @name drawHit
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2012-12-02 04:04:10 +08:00
|
|
|
*/
|
2012-11-19 11:50:50 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
/**
|
|
|
|
* set height
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2012-12-02 04:04:10 +08:00
|
|
|
* @param {Number} height
|
2012-07-22 04:29:22 +08:00
|
|
|
*/
|
2012-12-02 04:04:10 +08:00
|
|
|
setHeight: function(height) {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Node.prototype.setHeight.call(this, height);
|
2012-12-02 04:04:10 +08:00
|
|
|
this._resizeDOM();
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* set width
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2012-12-02 04:04:10 +08:00
|
|
|
* @param {Number} width
|
|
|
|
*/
|
|
|
|
setWidth: function(width) {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Node.prototype.setWidth.call(this, width);
|
2012-12-02 04:04:10 +08:00
|
|
|
this._resizeDOM();
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* clear all layers
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2012-12-02 04:04:10 +08:00
|
|
|
*/
|
|
|
|
clear: function() {
|
2013-03-24 14:50:51 +08:00
|
|
|
var layers = this.children,
|
2013-04-04 03:43:32 +08:00
|
|
|
len = layers.length,
|
2013-03-24 14:50:51 +08:00
|
|
|
n;
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-03-24 14:50:51 +08:00
|
|
|
for(n = 0; n < len; n++) {
|
2012-12-02 04:04:10 +08:00
|
|
|
layers[n].clear();
|
2012-07-22 06:38:25 +08:00
|
|
|
}
|
2013-06-07 13:45:31 +08:00
|
|
|
return this;
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
2014-03-07 22:51:26 +08:00
|
|
|
clone: function(obj) {
|
|
|
|
if (!obj) {
|
|
|
|
obj = {};
|
|
|
|
}
|
2015-01-27 15:07:51 +08:00
|
|
|
obj.container = Konva.document.createElement(DIV);
|
2014-03-07 22:51:26 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
return Konva.Container.prototype.clone.call(this, obj);
|
2014-03-07 22:51:26 +08:00
|
|
|
},
|
2013-01-13 14:01:12 +08:00
|
|
|
/**
|
2014-03-28 13:08:34 +08:00
|
|
|
* destroy stage
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2013-01-13 14:01:12 +08:00
|
|
|
*/
|
2013-06-09 06:57:36 +08:00
|
|
|
destroy: function() {
|
2013-01-13 14:01:12 +08:00
|
|
|
var content = this.content;
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Container.prototype.destroy.call(this);
|
2013-01-13 14:01:12 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
if(content && Konva.Util._isInDocument(content)) {
|
2013-03-24 14:50:51 +08:00
|
|
|
this.getContainer().removeChild(content);
|
2013-01-13 14:01:12 +08:00
|
|
|
}
|
2015-01-27 15:07:51 +08:00
|
|
|
var index = Konva.stages.indexOf(this);
|
2014-02-27 22:53:30 +08:00
|
|
|
if (index > -1) {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.stages.splice(index, 1);
|
2014-02-27 22:53:30 +08:00
|
|
|
}
|
2013-01-13 14:01:12 +08:00
|
|
|
},
|
2012-12-02 04:04:10 +08:00
|
|
|
/**
|
2013-10-09 00:29:08 +08:00
|
|
|
* get pointer position which can be a touch position or mouse position
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2014-01-13 01:15:35 +08:00
|
|
|
* @returns {Object}
|
2012-12-02 04:04:10 +08:00
|
|
|
*/
|
2013-03-24 11:15:49 +08:00
|
|
|
getPointerPosition: function() {
|
2013-10-09 00:29:08 +08:00
|
|
|
return this.pointerPos;
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
getStage: function() {
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
/**
|
2013-01-13 14:01:12 +08:00
|
|
|
* get stage content div element which has the
|
2015-01-27 15:07:51 +08:00
|
|
|
* the class name "konvajs-content"
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2012-12-02 04:04:10 +08:00
|
|
|
*/
|
2013-01-13 14:01:12 +08:00
|
|
|
getContent: function() {
|
2012-12-02 04:04:10 +08:00
|
|
|
return this.content;
|
|
|
|
},
|
|
|
|
/**
|
2012-12-17 12:52:07 +08:00
|
|
|
* Creates a composite data URL and requires a callback because the composite is generated asynchronously.
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2012-12-02 04:04:10 +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-12-02 04:04:10 +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-12-02 04:04:10 +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
|
|
|
|
*/
|
|
|
|
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,
|
|
|
|
quality = config.quality || null,
|
|
|
|
x = config.x || 0,
|
|
|
|
y = config.y || 0,
|
2015-01-27 15:07:51 +08:00
|
|
|
canvas = new Konva.SceneCanvas({
|
2013-07-22 11:14:09 +08:00
|
|
|
width: config.width || this.getWidth(),
|
2013-04-15 00:41:59 +08:00
|
|
|
height: config.height || this.getHeight(),
|
|
|
|
pixelRatio: 1
|
2013-07-22 11:14:09 +08:00
|
|
|
}),
|
2013-09-01 12:49:18 +08:00
|
|
|
_context = canvas.getContext()._context,
|
2013-03-15 23:33:05 +08:00
|
|
|
layers = this.children;
|
2012-12-11 16:21:43 +08:00
|
|
|
|
|
|
|
if(x || y) {
|
2013-09-01 12:49:18 +08:00
|
|
|
_context.translate(-1 * x, -1 * y);
|
2012-12-11 16:21:43 +08:00
|
|
|
}
|
2012-08-17 14:03:28 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
function drawLayer(n) {
|
2013-03-24 14:50:51 +08:00
|
|
|
var layer = layers[n],
|
|
|
|
layerUrl = layer.toDataURL(),
|
2015-01-27 15:07:51 +08:00
|
|
|
imageObj = new Konva.window.Image();
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
imageObj.onload = function() {
|
2013-09-01 12:49:18 +08:00
|
|
|
_context.drawImage(imageObj, 0, 0);
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
if(n < layers.length - 1) {
|
|
|
|
drawLayer(n + 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
config.callback(canvas.toDataURL(mimeType, quality));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
imageObj.src = layerUrl;
|
|
|
|
}
|
|
|
|
drawLayer(0);
|
|
|
|
},
|
|
|
|
/**
|
2013-01-13 15:39:56 +08:00
|
|
|
* converts stage into an image.
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2012-12-02 04:04:10 +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-12-02 04:04:10 +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-12-02 04:04:10 +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
|
2012-08-17 14:03:28 +08:00
|
|
|
*/
|
2012-12-02 04:04:10 +08:00
|
|
|
toImage: function(config) {
|
2012-12-11 16:21:43 +08:00
|
|
|
var cb = config.callback;
|
|
|
|
|
|
|
|
config.callback = function(dataUrl) {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Util._getImage(dataUrl, function(img) {
|
2012-12-11 16:21:43 +08:00
|
|
|
cb(img);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
this.toDataURL(config);
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
/**
|
2013-11-28 13:32:36 +08:00
|
|
|
* get visible intersection shape. This is the preferred
|
2013-05-18 11:56:24 +08:00
|
|
|
* method for determining if a point intersects a shape or not
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2013-12-03 13:25:20 +08:00
|
|
|
* @param {Object} pos
|
|
|
|
* @param {Number} pos.x
|
|
|
|
* @param {Number} pos.y
|
2015-01-27 15:07:51 +08:00
|
|
|
* @returns {Konva.Shape}
|
2012-12-02 04:04:10 +08:00
|
|
|
*/
|
2013-12-03 13:25:20 +08:00
|
|
|
getIntersection: function(pos) {
|
|
|
|
var layers = this.getChildren(),
|
2013-03-24 14:50:51 +08:00
|
|
|
len = layers.length,
|
|
|
|
end = len - 1,
|
2013-11-28 13:32:36 +08:00
|
|
|
n, shape;
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2013-03-24 14:50:51 +08:00
|
|
|
for(n = end; n >= 0; n--) {
|
2013-11-28 13:32:36 +08:00
|
|
|
shape = layers[n].getIntersection(pos);
|
|
|
|
if (shape) {
|
|
|
|
return shape;
|
2014-02-27 08:49:18 +08:00
|
|
|
}
|
2012-08-17 14:03:28 +08:00
|
|
|
}
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
return null;
|
|
|
|
},
|
|
|
|
_resizeDOM: function() {
|
|
|
|
if(this.content) {
|
2013-03-24 14:50:51 +08:00
|
|
|
var width = this.getWidth(),
|
|
|
|
height = this.getHeight(),
|
|
|
|
layers = this.getChildren(),
|
|
|
|
len = layers.length,
|
2013-07-22 13:17:53 +08:00
|
|
|
n, layer;
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
// set content dimensions
|
2013-03-24 14:50:51 +08:00
|
|
|
this.content.style.width = width + PX;
|
|
|
|
this.content.style.height = height + PX;
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2013-09-27 13:10:37 +08:00
|
|
|
this.bufferCanvas.setSize(width, height);
|
2015-01-28 06:26:18 +08:00
|
|
|
// this.bufferCanvas2.setSize(width, height);
|
2013-09-27 13:10:37 +08:00
|
|
|
this.bufferHitCanvas.setSize(width, height);
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-09-27 13:10:37 +08:00
|
|
|
// set layer dimensions
|
2013-03-24 14:50:51 +08:00
|
|
|
for(n = 0; n < len; n++) {
|
|
|
|
layer = layers[n];
|
2014-04-09 21:23:16 +08:00
|
|
|
layer.setSize(width, height);
|
2012-12-02 04:04:10 +08:00
|
|
|
layer.draw();
|
|
|
|
}
|
2012-09-26 12:23:35 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
/**
|
2014-03-14 11:30:46 +08:00
|
|
|
* add layer or layers to stage
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
|
|
|
* @param {...Konva.Layer} layer
|
2014-03-14 11:30:46 +08:00
|
|
|
* @example
|
|
|
|
* stage.add(layer1, layer2, layer3);
|
2012-12-02 04:04:10 +08:00
|
|
|
*/
|
2014-03-14 13:20:39 +08:00
|
|
|
add: function(layer) {
|
2014-03-14 11:30:46 +08:00
|
|
|
if (arguments.length > 1) {
|
|
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
|
|
this.add(arguments[i]);
|
|
|
|
}
|
2014-03-14 13:20:39 +08:00
|
|
|
return;
|
2014-03-14 11:30:46 +08:00
|
|
|
}
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Container.prototype.add.call(this, layer);
|
2014-03-09 10:05:14 +08:00
|
|
|
layer._setCanvasSize(this.width(), this.height());
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
// draw layer and append canvas to container
|
|
|
|
layer.draw();
|
2013-09-01 12:49:18 +08:00
|
|
|
this.content.appendChild(layer.canvas._canvas);
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
// chainable
|
|
|
|
return this;
|
|
|
|
},
|
2013-03-22 15:46:41 +08:00
|
|
|
getParent: function() {
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
getLayer: function() {
|
|
|
|
return null;
|
|
|
|
},
|
2013-05-06 11:57:31 +08:00
|
|
|
/**
|
2015-01-27 15:07:51 +08:00
|
|
|
* returns a {@link Konva.Collection} of layers
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2013-05-06 11:57:31 +08:00
|
|
|
*/
|
2013-05-20 12:07:43 +08:00
|
|
|
getLayers: function() {
|
|
|
|
return this.getChildren();
|
|
|
|
},
|
2012-12-02 04:04:10 +08:00
|
|
|
_bindContentEvents: function() {
|
2014-02-27 08:49:18 +08:00
|
|
|
for (var n = 0; n < eventsLength; n++) {
|
|
|
|
addEvent(this, EVENTS[n]);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
},
|
2013-07-06 01:38:02 +08:00
|
|
|
_mouseover: function(evt) {
|
2015-01-27 15:07:51 +08:00
|
|
|
if (!Konva.UA.mobile) {
|
2014-02-28 11:07:10 +08:00
|
|
|
this._setPointerPosition(evt);
|
2014-03-21 12:55:30 +08:00
|
|
|
this._fire(CONTENT_MOUSEOVER, {evt: evt});
|
2014-02-27 00:46:26 +08:00
|
|
|
}
|
2013-07-06 01:38:02 +08:00
|
|
|
},
|
2012-12-02 04:04:10 +08:00
|
|
|
_mouseout: function(evt) {
|
2015-01-27 15:07:51 +08:00
|
|
|
if (!Konva.UA.mobile) {
|
2014-02-27 00:46:26 +08:00
|
|
|
this._setPointerPosition(evt);
|
|
|
|
var targetShape = this.targetShape;
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
if(targetShape && !Konva.isDragging()) {
|
2014-03-21 12:55:30 +08:00
|
|
|
targetShape._fireAndBubble(MOUSEOUT, {evt: evt});
|
|
|
|
targetShape._fireAndBubble(MOUSELEAVE, {evt: evt});
|
2014-02-27 00:46:26 +08:00
|
|
|
this.targetShape = null;
|
|
|
|
}
|
|
|
|
this.pointerPos = undefined;
|
2013-07-06 01:38:02 +08:00
|
|
|
|
2014-03-21 12:55:30 +08:00
|
|
|
this._fire(CONTENT_MOUSEOUT, {evt: evt});
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
},
|
2014-02-28 11:07:10 +08:00
|
|
|
_mousemove: function(evt) {
|
2014-05-14 21:18:41 +08:00
|
|
|
|
|
|
|
// workaround for mobile IE to force touch event when unhandled pointer event elevates into a mouse event
|
2015-01-27 15:07:51 +08:00
|
|
|
if (Konva.UA.ieMobile) {
|
2014-05-21 21:25:31 +08:00
|
|
|
return this._touchmove(evt);
|
2014-05-14 21:18:41 +08:00
|
|
|
}
|
|
|
|
|
2014-04-29 13:45:30 +08:00
|
|
|
// workaround fake mousemove event in chrome browser https://code.google.com/p/chromium/issues/detail?id=161464
|
|
|
|
if ((typeof evt.webkitMovementX !== 'undefined' || typeof evt.webkitMovementY !== 'undefined') && evt.webkitMovementY === 0 && evt.webkitMovementX === 0) {
|
|
|
|
return;
|
|
|
|
}
|
2015-01-27 15:07:51 +08:00
|
|
|
if (Konva.UA.mobile) {
|
2014-05-03 11:32:47 +08:00
|
|
|
return;
|
|
|
|
}
|
2013-03-24 11:15:49 +08:00
|
|
|
this._setPointerPosition(evt);
|
2015-01-27 15:07:51 +08:00
|
|
|
var dd = Konva.DD, shape;
|
2014-02-27 00:46:26 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
if (!Konva.isDragging()) {
|
2013-11-28 13:32:36 +08:00
|
|
|
shape = this.getIntersection(this.getPointerPosition());
|
2014-02-27 00:46:26 +08:00
|
|
|
if(shape && shape.isListening()) {
|
2015-01-27 15:07:51 +08:00
|
|
|
if(!Konva.isDragging() && (!this.targetShape || this.targetShape._id !== shape._id)) {
|
2014-02-27 00:46:26 +08:00
|
|
|
if(this.targetShape) {
|
2014-03-21 12:55:30 +08:00
|
|
|
this.targetShape._fireAndBubble(MOUSEOUT, {evt: evt}, shape);
|
|
|
|
this.targetShape._fireAndBubble(MOUSELEAVE, {evt: evt}, shape);
|
2014-02-27 00:46:26 +08:00
|
|
|
}
|
2014-03-21 12:55:30 +08:00
|
|
|
shape._fireAndBubble(MOUSEOVER, {evt: evt}, this.targetShape);
|
|
|
|
shape._fireAndBubble(MOUSEENTER, {evt: evt}, this.targetShape);
|
2014-02-27 00:46:26 +08:00
|
|
|
this.targetShape = shape;
|
|
|
|
}
|
|
|
|
else {
|
2014-03-21 12:55:30 +08:00
|
|
|
shape._fireAndBubble(MOUSEMOVE, {evt: evt});
|
2012-08-17 14:03:28 +08:00
|
|
|
}
|
2013-09-21 07:17:32 +08:00
|
|
|
}
|
2014-02-27 00:46:26 +08:00
|
|
|
/*
|
|
|
|
* if no shape was detected, clear target shape and try
|
|
|
|
* to run mouseout from previous target shape
|
|
|
|
*/
|
2013-09-21 07:17:32 +08:00
|
|
|
else {
|
2015-01-27 15:07:51 +08:00
|
|
|
if(this.targetShape && !Konva.isDragging()) {
|
2014-03-21 12:55:30 +08:00
|
|
|
this.targetShape._fireAndBubble(MOUSEOUT, {evt: evt});
|
|
|
|
this.targetShape._fireAndBubble(MOUSELEAVE, {evt: evt});
|
2014-02-27 09:13:55 +08:00
|
|
|
this.targetShape = null;
|
|
|
|
}
|
2013-09-21 07:45:59 +08:00
|
|
|
|
2012-08-12 14:14:49 +08:00
|
|
|
}
|
2012-06-16 02:47:55 +08:00
|
|
|
|
2014-02-27 00:46:26 +08:00
|
|
|
// content event
|
2014-03-21 12:55:30 +08:00
|
|
|
this._fire(CONTENT_MOUSEMOVE, {evt: evt});
|
2014-05-03 11:32:47 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
if(dd) {
|
2012-12-31 15:14:23 +08:00
|
|
|
dd._drag(evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
2013-07-22 11:14:09 +08:00
|
|
|
|
|
|
|
// always call preventDefault for desktop events because some browsers
|
|
|
|
// try to drag and drop the canvas element
|
2013-07-24 02:15:04 +08:00
|
|
|
if (evt.preventDefault) {
|
|
|
|
evt.preventDefault();
|
|
|
|
}
|
2014-02-28 11:07:10 +08:00
|
|
|
},
|
2012-12-02 04:04:10 +08:00
|
|
|
_mousedown: function(evt) {
|
2014-05-14 21:18:41 +08:00
|
|
|
|
|
|
|
// workaround for mobile IE to force touch event when unhandled pointer event elevates into a mouse event
|
2015-01-27 15:07:51 +08:00
|
|
|
if (Konva.UA.ieMobile) {
|
2014-05-21 21:25:31 +08:00
|
|
|
return this._touchstart(evt);
|
2014-05-14 21:18:41 +08:00
|
|
|
}
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
if (!Konva.UA.mobile) {
|
2014-02-27 00:46:26 +08:00
|
|
|
this._setPointerPosition(evt);
|
|
|
|
var shape = this.getIntersection(this.getPointerPosition());
|
2012-06-15 14:46:52 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.listenClickTap = true;
|
2013-09-21 07:17:32 +08:00
|
|
|
|
2014-02-27 00:46:26 +08:00
|
|
|
if (shape && shape.isListening()) {
|
|
|
|
this.clickStartShape = shape;
|
2014-03-21 12:55:30 +08:00
|
|
|
shape._fireAndBubble(MOUSEDOWN, {evt: evt});
|
2014-02-27 00:46:26 +08:00
|
|
|
}
|
2013-09-21 07:17:32 +08:00
|
|
|
|
2014-02-27 00:46:26 +08:00
|
|
|
// content event
|
2014-03-21 12:55:30 +08:00
|
|
|
this._fire(CONTENT_MOUSEDOWN, {evt: evt});
|
2014-02-27 00:46:26 +08:00
|
|
|
}
|
2013-07-22 11:14:09 +08:00
|
|
|
|
|
|
|
// always call preventDefault for desktop events because some browsers
|
|
|
|
// try to drag and drop the canvas element
|
2013-07-24 02:15:04 +08:00
|
|
|
if (evt.preventDefault) {
|
|
|
|
evt.preventDefault();
|
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
_mouseup: function(evt) {
|
2015-02-14 23:12:54 +08:00
|
|
|
|
2014-05-14 21:18:41 +08:00
|
|
|
// workaround for mobile IE to force touch event when unhandled pointer event elevates into a mouse event
|
2015-01-27 15:07:51 +08:00
|
|
|
if (Konva.UA.ieMobile) {
|
2014-05-21 21:25:31 +08:00
|
|
|
return this._touchend(evt);
|
2014-08-19 19:27:46 +08:00
|
|
|
}
|
2015-01-27 15:07:51 +08:00
|
|
|
if (!Konva.UA.mobile) {
|
2014-02-27 00:46:26 +08:00
|
|
|
this._setPointerPosition(evt);
|
2014-03-05 04:27:38 +08:00
|
|
|
var shape = this.getIntersection(this.getPointerPosition()),
|
2014-02-27 00:46:26 +08:00
|
|
|
clickStartShape = this.clickStartShape,
|
2014-03-05 04:27:38 +08:00
|
|
|
fireDblClick = false,
|
2015-01-27 15:07:51 +08:00
|
|
|
dd = Konva.DD;
|
2013-09-21 07:17:32 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
if(Konva.inDblClickWindow) {
|
2014-02-27 00:46:26 +08:00
|
|
|
fireDblClick = true;
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.inDblClickWindow = false;
|
2014-02-27 00:46:26 +08:00
|
|
|
}
|
2014-03-05 04:27:38 +08:00
|
|
|
// don't set inDblClickWindow after dragging
|
|
|
|
else if (!dd || !dd.justDragged) {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.inDblClickWindow = true;
|
2014-03-05 04:27:38 +08:00
|
|
|
} else if (dd) {
|
|
|
|
dd.justDragged = false;
|
2014-02-27 00:46:26 +08:00
|
|
|
}
|
2013-09-21 07:17:32 +08:00
|
|
|
|
2014-02-27 00:46:26 +08:00
|
|
|
setTimeout(function() {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.inDblClickWindow = false;
|
|
|
|
}, Konva.dblClickWindow);
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2014-02-27 00:46:26 +08:00
|
|
|
if (shape && shape.isListening()) {
|
2014-03-21 12:55:30 +08:00
|
|
|
shape._fireAndBubble(MOUSEUP, {evt: evt});
|
2013-07-24 02:42:38 +08:00
|
|
|
|
2014-02-27 00:46:26 +08:00
|
|
|
// detect if click or double click occurred
|
2015-01-27 15:07:51 +08:00
|
|
|
if(Konva.listenClickTap && clickStartShape && clickStartShape._id === shape._id) {
|
2014-03-21 12:55:30 +08:00
|
|
|
shape._fireAndBubble(CLICK, {evt: evt});
|
2013-09-21 07:17:32 +08:00
|
|
|
|
2014-02-27 00:46:26 +08:00
|
|
|
if(fireDblClick) {
|
2014-03-21 12:55:30 +08:00
|
|
|
shape._fireAndBubble(DBL_CLICK, {evt: evt});
|
2014-02-27 00:46:26 +08:00
|
|
|
}
|
2013-09-21 07:17:32 +08:00
|
|
|
}
|
2013-07-24 02:42:38 +08:00
|
|
|
}
|
2014-02-27 00:46:26 +08:00
|
|
|
// content events
|
2014-03-21 12:55:30 +08:00
|
|
|
this._fire(CONTENT_MOUSEUP, {evt: evt});
|
2015-01-27 15:07:51 +08:00
|
|
|
if (Konva.listenClickTap) {
|
2014-03-21 12:55:30 +08:00
|
|
|
this._fire(CONTENT_CLICK, {evt: evt});
|
2014-02-27 00:46:26 +08:00
|
|
|
if(fireDblClick) {
|
2014-03-21 12:55:30 +08:00
|
|
|
this._fire(CONTENT_DBL_CLICK, {evt: evt});
|
2014-02-27 00:46:26 +08:00
|
|
|
}
|
2012-08-12 14:14:49 +08:00
|
|
|
}
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.listenClickTap = false;
|
2014-02-27 00:46:26 +08:00
|
|
|
}
|
2013-07-22 11:14:09 +08:00
|
|
|
|
|
|
|
// always call preventDefault for desktop events because some browsers
|
|
|
|
// try to drag and drop the canvas element
|
2013-07-24 02:15:04 +08:00
|
|
|
if (evt.preventDefault) {
|
|
|
|
evt.preventDefault();
|
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
_touchstart: function(evt) {
|
2013-06-02 13:03:02 +08:00
|
|
|
this._setPointerPosition(evt);
|
2013-11-28 13:32:36 +08:00
|
|
|
var shape = this.getIntersection(this.getPointerPosition());
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.listenClickTap = true;
|
2013-09-21 07:17:32 +08:00
|
|
|
|
2013-11-28 08:05:35 +08:00
|
|
|
if (shape && shape.isListening()) {
|
2013-09-21 07:17:32 +08:00
|
|
|
this.tapStartShape = shape;
|
2014-03-21 12:55:30 +08:00
|
|
|
shape._fireAndBubble(TOUCHSTART, {evt: evt});
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-09-21 07:45:59 +08:00
|
|
|
// only call preventDefault if the shape is listening for events
|
|
|
|
if (shape.isListening() && evt.preventDefault) {
|
|
|
|
evt.preventDefault();
|
|
|
|
}
|
2013-07-22 11:14:09 +08:00
|
|
|
}
|
2013-09-21 07:45:59 +08:00
|
|
|
// content event
|
2014-03-21 12:55:30 +08:00
|
|
|
this._fire(CONTENT_TOUCHSTART, {evt: evt});
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
_touchend: function(evt) {
|
2013-03-24 11:15:49 +08:00
|
|
|
this._setPointerPosition(evt);
|
2014-02-27 08:49:18 +08:00
|
|
|
var shape = this.getIntersection(this.getPointerPosition()),
|
2013-09-21 07:17:32 +08:00
|
|
|
fireDblClick = false;
|
2013-07-24 02:42:38 +08:00
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
if(Konva.inDblClickWindow) {
|
2014-02-27 08:49:18 +08:00
|
|
|
fireDblClick = true;
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.inDblClickWindow = false;
|
2014-02-27 08:49:18 +08:00
|
|
|
}
|
|
|
|
else {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.inDblClickWindow = true;
|
2014-02-27 08:49:18 +08:00
|
|
|
}
|
2013-07-24 02:42:38 +08:00
|
|
|
|
2014-02-27 08:49:18 +08:00
|
|
|
setTimeout(function() {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.inDblClickWindow = false;
|
|
|
|
}, Konva.dblClickWindow);
|
2013-09-21 07:17:32 +08:00
|
|
|
|
2013-11-28 08:05:35 +08:00
|
|
|
if (shape && shape.isListening()) {
|
2014-03-21 12:55:30 +08:00
|
|
|
shape._fireAndBubble(TOUCHEND, {evt: evt});
|
2013-09-21 07:17:32 +08:00
|
|
|
|
|
|
|
// detect if tap or double tap occurred
|
2015-01-27 15:07:51 +08:00
|
|
|
if(Konva.listenClickTap && shape._id === this.tapStartShape._id) {
|
2014-03-21 12:55:30 +08:00
|
|
|
shape._fireAndBubble(TAP, {evt: evt});
|
2013-09-21 07:17:32 +08:00
|
|
|
|
|
|
|
if(fireDblClick) {
|
2014-03-21 12:55:30 +08:00
|
|
|
shape._fireAndBubble(DBL_TAP, {evt: evt});
|
2013-09-21 07:17:32 +08:00
|
|
|
}
|
|
|
|
}
|
2013-09-21 07:45:59 +08:00
|
|
|
// only call preventDefault if the shape is listening for events
|
|
|
|
if (shape.isListening() && evt.preventDefault) {
|
|
|
|
evt.preventDefault();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// content events
|
2015-01-27 15:07:51 +08:00
|
|
|
if (Konva.listenClickTap) {
|
2014-03-21 12:55:30 +08:00
|
|
|
this._fire(CONTENT_TOUCHEND, {evt: evt});
|
2013-09-21 07:45:59 +08:00
|
|
|
if(fireDblClick) {
|
2014-03-21 12:55:30 +08:00
|
|
|
this._fire(CONTENT_DBL_TAP, {evt: evt});
|
2013-09-21 07:45:59 +08:00
|
|
|
}
|
2012-08-12 14:14:49 +08:00
|
|
|
}
|
|
|
|
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.listenClickTap = false;
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
2014-02-28 11:07:10 +08:00
|
|
|
_touchmove: function(evt) {
|
2013-03-24 11:15:49 +08:00
|
|
|
this._setPointerPosition(evt);
|
2015-01-27 15:07:51 +08:00
|
|
|
var dd = Konva.DD,
|
2014-05-03 11:32:47 +08:00
|
|
|
shape;
|
2015-01-27 15:07:51 +08:00
|
|
|
if (!Konva.isDragging()) {
|
2013-11-28 13:32:36 +08:00
|
|
|
shape = this.getIntersection(this.getPointerPosition());
|
2014-05-03 11:32:47 +08:00
|
|
|
if (shape && shape.isListening()) {
|
|
|
|
shape._fireAndBubble(TOUCHMOVE, {evt: evt});
|
|
|
|
// only call preventDefault if the shape is listening for events
|
|
|
|
if (shape.isListening() && evt.preventDefault) {
|
|
|
|
evt.preventDefault();
|
|
|
|
}
|
2013-09-21 07:45:59 +08:00
|
|
|
}
|
2014-05-03 11:32:47 +08:00
|
|
|
this._fire(CONTENT_TOUCHMOVE, {evt: evt});
|
2013-09-21 07:45:59 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
if(dd) {
|
2012-12-31 15:14:23 +08:00
|
|
|
dd._drag(evt);
|
2015-01-27 15:07:51 +08:00
|
|
|
if (Konva.isDragging()) {
|
2014-05-03 12:11:34 +08:00
|
|
|
evt.preventDefault();
|
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
2014-02-28 11:07:10 +08:00
|
|
|
},
|
2014-05-01 21:11:03 +08:00
|
|
|
_DOMMouseScroll: function(evt) {
|
|
|
|
this._mousewheel(evt);
|
|
|
|
},
|
|
|
|
_mousewheel: function(evt) {
|
|
|
|
this._setPointerPosition(evt);
|
|
|
|
var shape = this.getIntersection(this.getPointerPosition());
|
|
|
|
|
|
|
|
if (shape && shape.isListening()) {
|
|
|
|
shape._fireAndBubble(MOUSEWHEEL, {evt: evt});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_wheel: function(evt) {
|
|
|
|
this._mousewheel(evt);
|
|
|
|
},
|
2013-10-09 00:29:08 +08:00
|
|
|
_setPointerPosition: function(evt) {
|
2014-02-27 08:49:18 +08:00
|
|
|
var contentPosition = this._getContentPosition(),
|
2013-09-26 01:37:44 +08:00
|
|
|
offsetX = evt.offsetX,
|
|
|
|
clientX = evt.clientX,
|
2013-11-08 16:30:26 +08:00
|
|
|
x = null,
|
|
|
|
y = null,
|
2013-10-09 00:29:08 +08:00
|
|
|
touch;
|
2014-02-27 08:49:18 +08:00
|
|
|
evt = evt ? evt : window.event;
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-10-09 00:29:08 +08:00
|
|
|
// touch events
|
2013-11-08 16:30:26 +08:00
|
|
|
if(evt.touches !== undefined) {
|
|
|
|
// currently, only handle one finger
|
2014-03-21 01:33:16 +08:00
|
|
|
if (evt.touches.length > 0) {
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-11-08 16:30:26 +08:00
|
|
|
touch = evt.touches[0];
|
|
|
|
|
|
|
|
// get the information for finger #1
|
|
|
|
x = touch.clientX - contentPosition.left;
|
2014-02-27 08:49:18 +08:00
|
|
|
y = touch.clientY - contentPosition.top;
|
2013-11-08 16:30:26 +08:00
|
|
|
}
|
2012-04-09 02:01:31 +08:00
|
|
|
}
|
2013-10-09 00:29:08 +08:00
|
|
|
// mouse events
|
|
|
|
else {
|
|
|
|
// if offsetX is defined, assume that offsetY is defined as well
|
|
|
|
if (offsetX !== undefined) {
|
|
|
|
x = offsetX;
|
|
|
|
y = evt.offsetY;
|
|
|
|
}
|
2014-05-14 21:18:41 +08:00
|
|
|
// we unfortunately have to use UA detection here because accessing
|
|
|
|
// the layerX or layerY properties in newer versions of Chrome
|
2013-10-09 00:29:08 +08:00
|
|
|
// throws a JS warning. layerX and layerY are required for FF
|
|
|
|
// when the container is transformed via CSS.
|
2015-01-27 15:07:51 +08:00
|
|
|
else if (Konva.UA.browser === 'mozilla') {
|
2015-02-09 08:21:55 +08:00
|
|
|
x = evt.layerX || (evt.clientX - contentPosition.left);
|
|
|
|
y = evt.layerY || (evt.clientY - contentPosition.top);
|
2013-10-09 00:29:08 +08:00
|
|
|
}
|
|
|
|
// if clientX is defined, assume that clientY is defined as well
|
|
|
|
else if (clientX !== undefined && contentPosition) {
|
|
|
|
x = clientX - contentPosition.left;
|
|
|
|
y = evt.clientY - contentPosition.top;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-08 16:30:26 +08:00
|
|
|
if (x !== null && y !== null) {
|
|
|
|
this.pointerPos = {
|
|
|
|
x: x,
|
|
|
|
y: y
|
|
|
|
};
|
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
_getContentPosition: function() {
|
2013-08-25 17:24:20 +08:00
|
|
|
var rect = this.content.getBoundingClientRect ? this.content.getBoundingClientRect() : { top: 0, left: 0 };
|
2012-12-02 04:04:10 +08:00
|
|
|
return {
|
|
|
|
top: rect.top,
|
|
|
|
left: rect.left
|
|
|
|
};
|
|
|
|
},
|
|
|
|
_buildDOM: function() {
|
2013-06-09 05:29:58 +08:00
|
|
|
var container = this.getContainer();
|
2014-03-01 18:09:27 +08:00
|
|
|
if (!container) {
|
2015-01-27 15:07:51 +08:00
|
|
|
if (Konva.Util.isBrowser()) {
|
2014-07-30 00:47:53 +08:00
|
|
|
throw 'Stage has no container. A container is required.';
|
2014-03-01 18:09:27 +08:00
|
|
|
} else {
|
|
|
|
// automatically create element for jsdom in nodejs env
|
2015-01-27 15:07:51 +08:00
|
|
|
container = Konva.document.createElement(DIV);
|
2014-03-01 18:09:27 +08:00
|
|
|
}
|
|
|
|
}
|
2013-06-09 05:29:58 +08:00
|
|
|
// clear content inside container
|
|
|
|
container.innerHTML = EMPTY_STRING;
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
// content
|
2015-01-27 15:07:51 +08:00
|
|
|
this.content = Konva.document.createElement(DIV);
|
2013-03-24 14:50:51 +08:00
|
|
|
this.content.style.position = RELATIVE;
|
2015-01-27 16:13:43 +08:00
|
|
|
this.content.className = KONVA_CONTENT;
|
2013-11-03 13:39:24 +08:00
|
|
|
this.content.setAttribute('role', 'presentation');
|
2013-06-09 05:29:58 +08:00
|
|
|
container.appendChild(this.content);
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2013-11-03 13:31:09 +08:00
|
|
|
// the buffer canvas pixel ratio must be 1 because it is used as an
|
|
|
|
// intermediate canvas before copying the result onto a scene canvas.
|
|
|
|
// not setting it to 1 will result in an over compensation
|
2015-01-27 15:07:51 +08:00
|
|
|
this.bufferCanvas = new Konva.SceneCanvas({
|
2013-11-03 13:31:09 +08:00
|
|
|
pixelRatio: 1
|
|
|
|
});
|
2015-01-28 06:26:18 +08:00
|
|
|
// this.bufferCanvas2 = new Konva.SceneCanvas({
|
|
|
|
// pixelRatio: 1
|
|
|
|
// });
|
2015-01-27 15:07:51 +08:00
|
|
|
this.bufferHitCanvas = new Konva.HitCanvas();
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
this._resizeDOM();
|
|
|
|
},
|
|
|
|
_onContent: function(typesStr, handler) {
|
2013-03-24 14:50:51 +08:00
|
|
|
var types = typesStr.split(SPACE),
|
|
|
|
len = types.length,
|
|
|
|
n, baseEvent;
|
2013-07-22 11:14:09 +08:00
|
|
|
|
2013-03-24 14:50:51 +08:00
|
|
|
for(n = 0; n < len; n++) {
|
|
|
|
baseEvent = types[n];
|
2012-12-02 04:04:10 +08:00
|
|
|
this.content.addEventListener(baseEvent, handler, false);
|
|
|
|
}
|
2014-03-15 16:58:26 +08:00
|
|
|
},
|
|
|
|
// currently cache function is now working for stage, because stage has no its own canvas element
|
2014-03-21 14:45:38 +08:00
|
|
|
// TODO: may be it is better to cache all children layers?
|
2014-03-15 16:58:26 +08:00
|
|
|
cache: function() {
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Util.warn('Cache function is not allowed for stage. You may use cache only for layers, groups and shapes.');
|
2014-03-15 16:58:26 +08:00
|
|
|
},
|
|
|
|
clearCache : function() {
|
2012-04-09 08:37:49 +08:00
|
|
|
}
|
2013-05-08 14:17:57 +08:00
|
|
|
});
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Util.extend(Konva.Stage, Konva.Container);
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
// add getters and setters
|
2015-01-27 15:07:51 +08:00
|
|
|
Konva.Factory.addGetter(Konva.Stage, 'container');
|
|
|
|
Konva.Factory.addOverloadedGetterSetter(Konva.Stage, 'container');
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2012-04-29 04:46:54 +08:00
|
|
|
/**
|
2012-12-02 04:04:10 +08:00
|
|
|
* get container DOM element
|
2014-01-06 12:52:09 +08:00
|
|
|
* @name container
|
2013-05-16 00:27:22 +08:00
|
|
|
* @method
|
2015-01-27 15:07:51 +08:00
|
|
|
* @memberof Konva.Stage.prototype
|
2014-01-06 12:52:09 +08:00
|
|
|
* @returns {DomElement} container
|
|
|
|
* @example
|
2014-04-04 11:17:09 +08:00
|
|
|
* // get container
|
|
|
|
* var container = stage.container();
|
2014-01-08 15:56:49 +08:00
|
|
|
*
|
2014-04-04 11:17:09 +08:00
|
|
|
* // set container
|
|
|
|
* var container = document.createElement('div');
|
|
|
|
* body.appendChild(container);
|
2014-01-08 15:56:49 +08:00
|
|
|
* stage.container(container);
|
2012-04-29 04:46:54 +08:00
|
|
|
*/
|
2013-12-10 14:46:58 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
})();
|