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',
|
|
|
|
MOUSEOUT = 'mouseout',
|
|
|
|
MOUSELEAVE = 'mouseleave',
|
|
|
|
MOUSEOUT = 'mouseout',
|
|
|
|
MOUSEOVER = 'mouseover',
|
|
|
|
MOUSEENTER = 'mouseenter',
|
|
|
|
MOUSEMOVE = 'mousemove',
|
|
|
|
MOUSEDOWN = 'mousedown',
|
|
|
|
MOUSEUP = 'mouseup',
|
|
|
|
CLICK = 'click',
|
|
|
|
DBL_CLICK = 'dblclick',
|
|
|
|
TOUCHSTART = 'touchstart'
|
|
|
|
TOUCHEND = 'touchend'
|
|
|
|
TAP = 'tap',
|
|
|
|
DBL_TAP = 'dbltap',
|
|
|
|
TOUCHMOVE = 'touchmove',
|
|
|
|
DIV = 'div',
|
|
|
|
RELATIVE = 'relative',
|
|
|
|
INLINE_BLOCK = 'inline-block',
|
|
|
|
KINETICJS_CONTENT = 'kineticjs-content',
|
|
|
|
SPACE = ' ',
|
|
|
|
CONTAINER = 'container',
|
|
|
|
EVENTS = [MOUSEDOWN, MOUSEMOVE, MOUSEUP, MOUSEOUT, TOUCHSTART, TOUCHMOVE, TOUCHEND],
|
|
|
|
|
2013-03-22 11:24:03 +08:00
|
|
|
// cached variables
|
|
|
|
eventsLength = EVENTS.length;
|
2013-04-08 16:02:08 +08:00
|
|
|
|
|
|
|
function addEvent(ctx, eventName) {
|
|
|
|
ctx.content.addEventListener(eventName, function(evt) {
|
|
|
|
ctx['_' + eventName](evt);
|
|
|
|
}, false);
|
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2013-05-08 14:51:02 +08:00
|
|
|
Kinetic.Util.addMethods(Kinetic.Stage, {
|
2012-12-02 04:04:10 +08:00
|
|
|
_initStage: function(config) {
|
2013-03-15 23:33:05 +08:00
|
|
|
this.createAttrs();
|
2012-12-02 04:04:10 +08:00
|
|
|
// call super constructor
|
|
|
|
Kinetic.Container.call(this, config);
|
2013-03-24 14:50:51 +08:00
|
|
|
this.nodeType = STAGE;
|
|
|
|
this.dblClickWindow = 400;
|
2012-12-02 04:04:10 +08:00
|
|
|
this._id = Kinetic.Global.idCounter++;
|
|
|
|
this._buildDOM();
|
|
|
|
this._bindContentEvents();
|
2012-12-31 15:14:23 +08:00
|
|
|
Kinetic.Global.stages.push(this);
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
2012-12-17 12:52:07 +08:00
|
|
|
/**
|
|
|
|
* set container dom element which contains the stage wrapper div element
|
|
|
|
* @name setContainer
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
* @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) {
|
2012-12-02 04:04:10 +08:00
|
|
|
container = document.getElementById(container);
|
|
|
|
}
|
2013-03-24 14:50:51 +08:00
|
|
|
this.setAttr(CONTAINER, container);
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
2013-03-24 11:02:11 +08:00
|
|
|
draw: function() {
|
|
|
|
// clear children layers
|
|
|
|
var children = this.getChildren(),
|
|
|
|
len = children.length,
|
|
|
|
n, layer;
|
|
|
|
|
|
|
|
for(n = 0; n < len; n++) {
|
|
|
|
layer = children[n];
|
|
|
|
if (layer.getClearBeforeDraw()) {
|
|
|
|
layer.getCanvas().clear();
|
|
|
|
layer.getHitCanvas().clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Kinetic.Node.prototype.draw.call(this);
|
|
|
|
},
|
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
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
*/
|
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
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
*/
|
2012-11-19 11:50:50 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
/**
|
|
|
|
* set height
|
|
|
|
* @name setHeight
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
* @param {Number} height
|
2012-07-22 04:29:22 +08:00
|
|
|
*/
|
2012-12-02 04:04:10 +08:00
|
|
|
setHeight: function(height) {
|
|
|
|
Kinetic.Node.prototype.setHeight.call(this, height);
|
|
|
|
this._resizeDOM();
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* set width
|
|
|
|
* @name setWidth
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
* @param {Number} width
|
|
|
|
*/
|
|
|
|
setWidth: function(width) {
|
|
|
|
Kinetic.Node.prototype.setWidth.call(this, width);
|
|
|
|
this._resizeDOM();
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* clear all layers
|
|
|
|
* @name clear
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
*/
|
|
|
|
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;
|
|
|
|
|
|
|
|
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
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
2013-01-13 14:01:12 +08:00
|
|
|
/**
|
|
|
|
* remove stage
|
|
|
|
*/
|
|
|
|
remove: function() {
|
|
|
|
var content = this.content;
|
|
|
|
Kinetic.Node.prototype.remove.call(this);
|
|
|
|
|
2013-05-08 14:51:02 +08:00
|
|
|
if(content && Kinetic.Util._isInDocument(content)) {
|
2013-03-24 14:50:51 +08:00
|
|
|
this.getContainer().removeChild(content);
|
2013-01-13 14:01:12 +08:00
|
|
|
}
|
|
|
|
},
|
2012-12-02 04:04:10 +08:00
|
|
|
/**
|
|
|
|
* get mouse position for desktop apps
|
|
|
|
* @name getMousePosition
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
*/
|
2012-12-17 12:52:07 +08:00
|
|
|
getMousePosition: function() {
|
2012-12-02 04:04:10 +08:00
|
|
|
return this.mousePos;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get touch position for mobile apps
|
|
|
|
* @name getTouchPosition
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
*/
|
2012-12-17 12:52:07 +08:00
|
|
|
getTouchPosition: function() {
|
2012-12-02 04:04:10 +08:00
|
|
|
return this.touchPos;
|
|
|
|
},
|
|
|
|
/**
|
2013-03-24 11:15:49 +08:00
|
|
|
* get pointer position which can be a touc position or mouse position
|
|
|
|
* @name getPointerPosition
|
2012-12-02 04:04:10 +08:00
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
*/
|
2013-03-24 11:15:49 +08:00
|
|
|
getPointerPosition: function() {
|
2012-12-02 04:04:10 +08:00
|
|
|
return this.getTouchPosition() || this.getMousePosition();
|
|
|
|
},
|
|
|
|
getStage: function() {
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
/**
|
2013-01-13 14:01:12 +08:00
|
|
|
* get stage content div element which has the
|
|
|
|
* the class name "kineticjs-content"
|
|
|
|
* @name getContent
|
2012-12-02 04:04:10 +08:00
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
*/
|
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.
|
2012-12-02 04:04:10 +08:00
|
|
|
* @name toDataURL
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
* @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-03-24 14:50:51 +08:00
|
|
|
var config = config || {},
|
|
|
|
mimeType = config.mimeType || null,
|
2013-03-15 23:33:05 +08:00
|
|
|
quality = config.quality || null,
|
|
|
|
x = config.x || 0,
|
|
|
|
y = config.y || 0,
|
2013-03-22 15:46:41 +08:00
|
|
|
canvas = new Kinetic.SceneCanvas({
|
|
|
|
width: config.width || this.getWidth(),
|
2013-04-15 00:41:59 +08:00
|
|
|
height: config.height || this.getHeight(),
|
|
|
|
pixelRatio: 1
|
2013-03-22 15:46:41 +08:00
|
|
|
}),
|
2013-03-15 23:33:05 +08:00
|
|
|
context = canvas.getContext(),
|
|
|
|
layers = this.children;
|
2012-12-11 16:21:43 +08:00
|
|
|
|
|
|
|
if(x || y) {
|
|
|
|
context.translate(-1 * x, -1 * y);
|
|
|
|
}
|
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(),
|
|
|
|
imageObj = new Image();
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
imageObj.onload = function() {
|
|
|
|
context.drawImage(imageObj, 0, 0);
|
|
|
|
|
|
|
|
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.
|
2012-12-02 04:04:10 +08:00
|
|
|
* @name toImage
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
* @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) {
|
2013-05-08 14:51:02 +08:00
|
|
|
Kinetic.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
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get intersection object that contains shape and pixel data
|
|
|
|
* @name getIntersection
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
* @param {Object} pos point object
|
|
|
|
*/
|
2013-04-12 14:51:21 +08:00
|
|
|
getIntersection: function() {
|
2013-05-08 14:51:02 +08:00
|
|
|
var pos = Kinetic.Util._getXY(Array.prototype.slice.call(arguments)),
|
2013-04-12 14:51:21 +08:00
|
|
|
layers = this.getChildren(),
|
2013-03-24 14:50:51 +08:00
|
|
|
len = layers.length,
|
|
|
|
end = len - 1,
|
2013-04-12 14:51:21 +08:00
|
|
|
n, obj;
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2013-03-24 14:50:51 +08:00
|
|
|
for(n = end; n >= 0; n--) {
|
2013-04-12 14:51:21 +08:00
|
|
|
obj = layers[n].getIntersection(pos);
|
|
|
|
if (obj) {
|
|
|
|
return obj;
|
2012-10-03 15:04:56 +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,
|
|
|
|
n;
|
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-02-13 02:29:23 +08:00
|
|
|
this.bufferCanvas.setSize(width, height, 1);
|
2012-12-02 04:04:10 +08:00
|
|
|
this.hitCanvas.setSize(width, height);
|
2013-03-24 14:50:51 +08:00
|
|
|
|
2013-03-24 11:15:49 +08:00
|
|
|
// set pointer defined layer dimensions
|
2013-03-24 14:50:51 +08:00
|
|
|
for(n = 0; n < len; n++) {
|
|
|
|
layer = layers[n];
|
2012-12-02 04:04:10 +08:00
|
|
|
layer.getCanvas().setSize(width, height);
|
|
|
|
layer.hitCanvas.setSize(width, height);
|
|
|
|
layer.draw();
|
|
|
|
}
|
2012-09-26 12:23:35 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* add layer to stage
|
2012-12-17 12:52:07 +08:00
|
|
|
* @param {Kinetic.Layer} layer
|
2012-12-02 04:04:10 +08:00
|
|
|
*/
|
|
|
|
add: function(layer) {
|
|
|
|
Kinetic.Container.prototype.add.call(this, layer);
|
|
|
|
layer.canvas.setSize(this.attrs.width, this.attrs.height);
|
|
|
|
layer.hitCanvas.setSize(this.attrs.width, this.attrs.height);
|
|
|
|
|
|
|
|
// draw layer and append canvas to container
|
|
|
|
layer.draw();
|
|
|
|
this.content.appendChild(layer.canvas.element);
|
2013-02-13 01:58:47 +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
|
|
|
/**
|
|
|
|
* get layers
|
|
|
|
* @name getLayers
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
|
|
|
*/
|
|
|
|
getLayers: function() {
|
|
|
|
return this.getChildren();
|
|
|
|
},
|
2013-03-24 11:15:49 +08:00
|
|
|
_setPointerPosition: function(evt) {
|
2012-12-02 04:04:10 +08:00
|
|
|
if(!evt) {
|
|
|
|
evt = window.event;
|
|
|
|
}
|
|
|
|
this._setMousePosition(evt);
|
|
|
|
this._setTouchPosition(evt);
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* begin listening for events by adding event handlers
|
|
|
|
* to the container
|
|
|
|
*/
|
|
|
|
_bindContentEvents: function() {
|
2013-03-22 11:24:03 +08:00
|
|
|
var that = this,
|
2013-04-08 16:02:08 +08:00
|
|
|
n;
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2013-03-24 14:50:51 +08:00
|
|
|
for (n = 0; n < eventsLength; n++) {
|
2013-04-08 16:02:08 +08:00
|
|
|
addEvent(this, EVENTS[n]);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
_mouseout: function(evt) {
|
2013-03-24 11:15:49 +08:00
|
|
|
this._setPointerPosition(evt);
|
2013-03-24 14:50:51 +08:00
|
|
|
var go = Kinetic.Global,
|
|
|
|
targetShape = this.targetShape;
|
|
|
|
|
2013-03-24 14:19:24 +08:00
|
|
|
if(targetShape && !go.isDragging()) {
|
2013-05-13 14:37:24 +08:00
|
|
|
targetShape.fire(MOUSEOUT, evt);
|
|
|
|
targetShape.fire(MOUSELEAVE, evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
this.targetShape = null;
|
|
|
|
}
|
|
|
|
this.mousePos = undefined;
|
|
|
|
},
|
|
|
|
_mousemove: function(evt) {
|
2013-03-24 11:15:49 +08:00
|
|
|
this._setPointerPosition(evt);
|
2013-03-24 14:19:24 +08:00
|
|
|
var go = Kinetic.Global,
|
|
|
|
dd = Kinetic.DD,
|
2013-03-24 14:50:51 +08:00
|
|
|
obj = this.getIntersection(this.getPointerPosition()),
|
|
|
|
shape;
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
if(obj) {
|
2013-03-24 14:50:51 +08:00
|
|
|
shape = obj.shape;
|
2012-12-02 04:04:10 +08:00
|
|
|
if(shape) {
|
2013-03-24 14:19:24 +08:00
|
|
|
if(!go.isDragging() && obj.pixel[3] === 255 && (!this.targetShape || this.targetShape._id !== shape._id)) {
|
2012-12-02 04:04:10 +08:00
|
|
|
if(this.targetShape) {
|
2013-05-13 14:37:24 +08:00
|
|
|
this.targetShape.fire(MOUSEOUT, evt, shape);
|
|
|
|
this.targetShape.fire(MOUSELEAVE, evt, shape);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
2013-05-13 14:37:24 +08:00
|
|
|
shape.fire(MOUSEOVER, evt, this.targetShape);
|
|
|
|
shape.fire(MOUSEENTER, evt, this.targetShape);
|
2012-12-02 04:04:10 +08:00
|
|
|
this.targetShape = shape;
|
|
|
|
}
|
|
|
|
else {
|
2013-05-13 14:37:24 +08:00
|
|
|
shape.fire(MOUSEMOVE, evt);
|
2012-08-17 14:03:28 +08:00
|
|
|
}
|
2012-08-12 14:14:49 +08:00
|
|
|
}
|
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
/*
|
|
|
|
* if no shape was detected, clear target shape and try
|
|
|
|
* to run mouseout from previous target shape
|
|
|
|
*/
|
2013-03-24 14:19:24 +08:00
|
|
|
else if(this.targetShape && !go.isDragging()) {
|
2013-05-13 14:37:24 +08:00
|
|
|
this.targetShape.fire(MOUSEOUT, evt);
|
|
|
|
this.targetShape.fire(MOUSELEAVE, evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
this.targetShape = null;
|
|
|
|
}
|
2012-06-16 02:47:55 +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
|
|
|
}
|
|
|
|
},
|
|
|
|
_mousedown: function(evt) {
|
2013-03-24 11:15:49 +08:00
|
|
|
this._setPointerPosition(evt);
|
2013-04-03 13:29:56 +08:00
|
|
|
var go = Kinetic.Global,
|
|
|
|
obj = this.getIntersection(this.getPointerPosition()),
|
|
|
|
shape;
|
2013-03-24 14:50:51 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
if(obj && obj.shape) {
|
2013-03-24 14:50:51 +08:00
|
|
|
shape = obj.shape;
|
2012-12-02 04:04:10 +08:00
|
|
|
this.clickStart = true;
|
2013-03-24 13:56:22 +08:00
|
|
|
this.clickStartShape = shape;
|
2013-05-13 14:37:24 +08:00
|
|
|
shape.fire(MOUSEDOWN, evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
2012-06-15 14:46:52 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
//init stage drag and drop
|
2013-04-03 13:29:56 +08:00
|
|
|
if(this.isDraggable() && !go.isDragReady()) {
|
2013-03-24 17:31:39 +08:00
|
|
|
this.startDrag(evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
_mouseup: function(evt) {
|
2013-03-24 11:15:49 +08:00
|
|
|
this._setPointerPosition(evt);
|
2013-03-24 11:02:11 +08:00
|
|
|
var that = this,
|
2013-03-24 14:19:24 +08:00
|
|
|
go = Kinetic.Global,
|
2013-03-24 14:50:51 +08:00
|
|
|
obj = this.getIntersection(this.getPointerPosition()),
|
|
|
|
shape;
|
2013-03-24 11:02:11 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
if(obj && obj.shape) {
|
2013-03-24 14:50:51 +08:00
|
|
|
shape = obj.shape;
|
2013-05-13 14:37:24 +08:00
|
|
|
shape.fire(MOUSEUP, evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
// detect if click or double click occurred
|
|
|
|
if(this.clickStart) {
|
|
|
|
/*
|
2013-03-24 13:56:22 +08:00
|
|
|
* if dragging and dropping, or if click doesn't map to
|
|
|
|
* the correct shape, don't fire click or dbl click event
|
2012-12-02 04:04:10 +08:00
|
|
|
*/
|
2013-03-24 14:19:24 +08:00
|
|
|
if(!go.isDragging() && shape._id === this.clickStartShape._id) {
|
2013-05-13 14:37:24 +08:00
|
|
|
shape.fire(CLICK, evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
if(this.inDoubleClickWindow) {
|
2013-05-13 14:37:24 +08:00
|
|
|
shape.fire(DBL_CLICK, evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
this.inDoubleClickWindow = true;
|
|
|
|
setTimeout(function() {
|
|
|
|
that.inDoubleClickWindow = false;
|
|
|
|
}, this.dblClickWindow);
|
2012-08-12 14:14:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
this.clickStart = false;
|
|
|
|
},
|
|
|
|
_touchstart: function(evt) {
|
2013-03-24 14:50:51 +08:00
|
|
|
this._setPointerPosition(evt);
|
2013-04-07 13:29:35 +08:00
|
|
|
var go = Kinetic.Global,
|
2013-03-24 14:50:51 +08:00
|
|
|
obj = this.getIntersection(this.getPointerPosition()),
|
|
|
|
shape;
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
evt.preventDefault();
|
|
|
|
|
|
|
|
if(obj && obj.shape) {
|
2013-03-24 14:50:51 +08:00
|
|
|
shape = obj.shape;
|
2012-12-02 04:04:10 +08:00
|
|
|
this.tapStart = true;
|
2013-03-24 14:50:51 +08:00
|
|
|
this.tapStartShape = shape;
|
2013-05-13 14:37:24 +08:00
|
|
|
shape.fire(TOUCHSTART, evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
2012-08-12 14:14:49 +08:00
|
|
|
|
2013-04-07 13:29:35 +08:00
|
|
|
//init stage drag and drop
|
|
|
|
if(this.isDraggable() && !go.isDragReady()) {
|
2013-03-24 17:31:39 +08:00
|
|
|
this.startDrag(evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
_touchend: function(evt) {
|
2013-03-24 11:15:49 +08:00
|
|
|
this._setPointerPosition(evt);
|
2013-03-24 14:50:51 +08:00
|
|
|
var that = this,
|
|
|
|
go = Kinetic.Global,
|
|
|
|
obj = this.getIntersection(this.getPointerPosition()),
|
|
|
|
shape;
|
2013-01-14 11:59:35 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
if(obj && obj.shape) {
|
2013-03-24 14:50:51 +08:00
|
|
|
shape = obj.shape;
|
2013-05-13 14:37:24 +08:00
|
|
|
shape.fire(TOUCHEND, evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
// detect if tap or double tap occurred
|
|
|
|
if(this.tapStart) {
|
|
|
|
/*
|
|
|
|
* if dragging and dropping, don't fire tap or dbltap
|
|
|
|
* event
|
|
|
|
*/
|
2013-03-24 14:50:51 +08:00
|
|
|
if(!go.isDragging() && shape._id === this.tapStartShape._id) {
|
2013-05-13 14:37:24 +08:00
|
|
|
shape.fire(TAP, evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
if(this.inDoubleClickWindow) {
|
2013-05-13 14:37:24 +08:00
|
|
|
shape.fire(DBL_TAP, evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
this.inDoubleClickWindow = true;
|
|
|
|
setTimeout(function() {
|
|
|
|
that.inDoubleClickWindow = false;
|
|
|
|
}, this.dblClickWindow);
|
2012-08-12 14:14:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
this.tapStart = false;
|
|
|
|
},
|
|
|
|
_touchmove: function(evt) {
|
2013-03-24 11:15:49 +08:00
|
|
|
this._setPointerPosition(evt);
|
2013-03-24 14:50:51 +08:00
|
|
|
var dd = Kinetic.DD,
|
|
|
|
obj = this.getIntersection(this.getPointerPosition()),
|
|
|
|
shape;
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
evt.preventDefault();
|
2013-03-24 14:50:51 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
if(obj && obj.shape) {
|
2013-03-24 14:50:51 +08:00
|
|
|
shape = obj.shape;
|
2013-05-13 14:37:24 +08:00
|
|
|
shape.fire(TOUCHMOVE, evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
2012-06-16 02:47:55 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
// start drag and drop
|
|
|
|
if(dd) {
|
2012-12-31 15:14:23 +08:00
|
|
|
dd._drag(evt);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* set mouse positon for desktop apps
|
|
|
|
* @param {Event} evt
|
|
|
|
*/
|
|
|
|
_setMousePosition: function(evt) {
|
2013-03-24 14:50:51 +08:00
|
|
|
var mouseX = evt.clientX - this._getContentPosition().left,
|
|
|
|
mouseY = evt.clientY - this._getContentPosition().top;
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
this.mousePos = {
|
|
|
|
x: mouseX,
|
|
|
|
y: mouseY
|
2012-03-07 13:45:48 +08:00
|
|
|
};
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* set touch position for mobile apps
|
|
|
|
* @param {Event} evt
|
|
|
|
*/
|
|
|
|
_setTouchPosition: function(evt) {
|
2013-03-24 14:50:51 +08:00
|
|
|
var touch, touchX, touchY;
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
if(evt.touches !== undefined && evt.touches.length === 1) {
|
|
|
|
// one finger
|
2013-03-24 14:50:51 +08:00
|
|
|
touch = evt.touches[0];
|
|
|
|
|
|
|
|
// get the information for finger #1
|
|
|
|
touchX = touch.clientX - this._getContentPosition().left;
|
|
|
|
touchY = touch.clientY - this._getContentPosition().top;
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
this.touchPos = {
|
|
|
|
x: touchX,
|
|
|
|
y: touchY
|
|
|
|
};
|
2012-04-09 02:01:31 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get container position
|
|
|
|
*/
|
|
|
|
_getContentPosition: function() {
|
|
|
|
var rect = this.content.getBoundingClientRect();
|
|
|
|
return {
|
|
|
|
top: rect.top,
|
|
|
|
left: rect.left
|
|
|
|
};
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* build dom
|
|
|
|
*/
|
|
|
|
_buildDOM: function() {
|
|
|
|
// content
|
2013-03-24 14:50:51 +08:00
|
|
|
this.content = document.createElement(DIV);
|
|
|
|
this.content.style.position = RELATIVE;
|
|
|
|
this.content.style.display = INLINE_BLOCK;
|
|
|
|
this.content.className = KINETICJS_CONTENT;
|
2012-12-02 04:04:10 +08:00
|
|
|
this.attrs.container.appendChild(this.content);
|
|
|
|
|
2012-12-10 01:52:33 +08:00
|
|
|
this.bufferCanvas = new Kinetic.SceneCanvas();
|
2012-12-22 14:51:57 +08:00
|
|
|
this.hitCanvas = new Kinetic.HitCanvas();
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
this._resizeDOM();
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* bind event listener to container DOM element
|
|
|
|
* @param {String} typesStr
|
|
|
|
* @param {function} handler
|
|
|
|
*/
|
|
|
|
_onContent: function(typesStr, handler) {
|
2013-03-24 14:50:51 +08:00
|
|
|
var types = typesStr.split(SPACE),
|
|
|
|
len = types.length,
|
|
|
|
n, baseEvent;
|
|
|
|
|
|
|
|
for(n = 0; n < len; n++) {
|
|
|
|
baseEvent = types[n];
|
2012-12-02 04:04:10 +08:00
|
|
|
this.content.addEventListener(baseEvent, handler, false);
|
|
|
|
}
|
2012-04-09 08:37:49 +08:00
|
|
|
}
|
2013-05-08 14:17:57 +08:00
|
|
|
});
|
2013-05-08 14:51:02 +08:00
|
|
|
Kinetic.Util.extend(Kinetic.Stage, Kinetic.Container);
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
// add getters and setters
|
2013-03-15 23:33:05 +08:00
|
|
|
Kinetic.Node.addGetter(Kinetic.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
|
|
|
|
* @name getContainer
|
|
|
|
* @methodOf Kinetic.Stage.prototype
|
2012-04-29 04:46:54 +08:00
|
|
|
*/
|
2012-12-02 04:04:10 +08:00
|
|
|
})();
|