2012-12-01 12:04:10 -08:00
|
|
|
(function() {
|
2013-05-18 10:40:05 -07:00
|
|
|
// constants
|
2013-08-09 20:22:51 -07:00
|
|
|
var HASH = '#',
|
|
|
|
|
BEFORE_DRAW ='beforeDraw',
|
2013-11-27 21:32:36 -08:00
|
|
|
DRAW = 'draw',
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 2 - 3 - 4
|
|
|
|
|
* | |
|
|
|
|
|
* 1 - 0 5
|
|
|
|
|
* |
|
|
|
|
|
* 8 - 7 - 6
|
|
|
|
|
*/
|
|
|
|
|
INTERSECTION_OFFSETS = [
|
|
|
|
|
{x: 0, y: 0}, // 0
|
|
|
|
|
{x: -1, y: 0}, // 1
|
|
|
|
|
{x: -1, y: -1}, // 2
|
|
|
|
|
{x: 0, y: -1}, // 3
|
|
|
|
|
{x: 1, y: -1}, // 4
|
|
|
|
|
{x: 1, y: 0}, // 5
|
|
|
|
|
{x: 1, y: 1}, // 6
|
|
|
|
|
{x: 0, y: 1}, // 7
|
|
|
|
|
{x: -1, y: 1} // 8
|
|
|
|
|
],
|
|
|
|
|
INTERSECTION_OFFSETS_LEN = INTERSECTION_OFFSETS.length;
|
|
|
|
|
|
2013-05-18 10:40:05 -07:00
|
|
|
|
2013-05-07 23:51:02 -07:00
|
|
|
Kinetic.Util.addMethods(Kinetic.Layer, {
|
2013-07-22 21:41:41 -07:00
|
|
|
___init: function(config) {
|
2012-12-01 12:04:10 -08:00
|
|
|
this.nodeType = 'Layer';
|
2013-04-12 23:45:22 -07:00
|
|
|
this.canvas = new Kinetic.SceneCanvas();
|
2013-04-12 00:48:41 -07:00
|
|
|
this.hitCanvas = new Kinetic.HitCanvas();
|
2013-05-20 22:12:43 -07:00
|
|
|
// call super constructor
|
|
|
|
|
Kinetic.Container.call(this, config);
|
2012-12-01 12:04:10 -08:00
|
|
|
},
|
2013-07-22 22:47:13 -07:00
|
|
|
_validateAdd: function(child) {
|
|
|
|
|
var type = child.getType();
|
|
|
|
|
if (type !== 'Group' && type !== 'Shape') {
|
|
|
|
|
Kinetic.Util.error('You may only add groups and shapes to a layer.');
|
|
|
|
|
}
|
|
|
|
|
},
|
2013-04-11 23:51:21 -07:00
|
|
|
/**
|
2013-11-27 21:32:36 -08:00
|
|
|
* get visible intersection shape. This is the preferred
|
2013-05-17 15:50:53 -07:00
|
|
|
* method for determining if a point intersects a shape or not
|
2013-05-15 09:27:22 -07:00
|
|
|
* @method
|
2013-05-17 15:50:53 -07:00
|
|
|
* @memberof Kinetic.Layer.prototype
|
2013-12-02 21:25:20 -08:00
|
|
|
* @param {Object} pos
|
|
|
|
|
* @param {Number} pos.x
|
|
|
|
|
* @param {Number} pos.y
|
|
|
|
|
* @returns {Kinetic.Shape}
|
2013-04-11 23:51:21 -07:00
|
|
|
*/
|
2013-12-02 21:25:20 -08:00
|
|
|
getIntersection: function(pos) {
|
|
|
|
|
var obj, i, intersectionOffset, shape;
|
2013-04-11 23:51:21 -07:00
|
|
|
|
2013-11-27 16:05:35 -08:00
|
|
|
if(this.isVisible()) {
|
2013-11-27 21:32:36 -08:00
|
|
|
for (i=0; i<INTERSECTION_OFFSETS_LEN; i++) {
|
|
|
|
|
intersectionOffset = INTERSECTION_OFFSETS[i];
|
2013-11-27 21:53:41 -08:00
|
|
|
obj = this._getIntersection({
|
2013-11-27 21:32:36 -08:00
|
|
|
x: pos.x + intersectionOffset.x,
|
|
|
|
|
y: pos.y + intersectionOffset.y
|
|
|
|
|
});
|
2013-11-27 21:53:41 -08:00
|
|
|
shape = obj.shape;
|
2013-11-27 21:32:36 -08:00
|
|
|
if (shape) {
|
|
|
|
|
return shape;
|
|
|
|
|
}
|
2013-11-27 21:53:41 -08:00
|
|
|
else if (!obj.antialiased) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2013-04-11 23:51:21 -07:00
|
|
|
}
|
|
|
|
|
}
|
2013-11-27 16:05:35 -08:00
|
|
|
else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2013-04-11 23:51:21 -07:00
|
|
|
},
|
2013-11-27 21:32:36 -08:00
|
|
|
_getIntersection: function(pos) {
|
|
|
|
|
var p = this.hitCanvas.context._context.getImageData(pos.x, pos.y, 1, 1).data,
|
2013-11-27 21:53:41 -08:00
|
|
|
p3 = p[3],
|
2013-11-27 21:32:36 -08:00
|
|
|
colorKey, shape;
|
|
|
|
|
|
2013-11-27 21:53:41 -08:00
|
|
|
// fully opaque pixel
|
|
|
|
|
if(p3 === 255) {
|
2013-11-27 21:32:36 -08:00
|
|
|
colorKey = Kinetic.Util._rgbToHex(p[0], p[1], p[2]);
|
|
|
|
|
shape = Kinetic.shapes[HASH + colorKey];
|
2013-11-27 21:53:41 -08:00
|
|
|
return {
|
|
|
|
|
shape: shape
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
// antialiased pixel
|
|
|
|
|
else if(p3 > 0) {
|
|
|
|
|
return {
|
|
|
|
|
antialiased: true
|
|
|
|
|
};
|
2013-11-27 21:32:36 -08:00
|
|
|
}
|
2013-11-27 21:53:41 -08:00
|
|
|
// empty pixel
|
2013-11-27 21:32:36 -08:00
|
|
|
else {
|
2013-11-27 21:53:41 -08:00
|
|
|
return {};
|
2013-11-27 21:32:36 -08:00
|
|
|
}
|
|
|
|
|
},
|
2013-12-29 19:46:53 -08:00
|
|
|
drawScene: function(can) {
|
|
|
|
|
var layer = this.getLayer(),
|
|
|
|
|
canvas = can || (layer && layer.getCanvas());
|
2013-04-04 23:17:20 -07:00
|
|
|
|
2013-08-09 20:22:51 -07:00
|
|
|
this._fire(BEFORE_DRAW, {
|
|
|
|
|
node: this
|
|
|
|
|
});
|
|
|
|
|
|
2013-04-14 09:41:59 -07:00
|
|
|
if(this.getClearBeforeDraw()) {
|
2013-08-31 21:49:18 -07:00
|
|
|
canvas.getContext().clear();
|
2013-04-04 23:17:20 -07:00
|
|
|
}
|
2013-08-09 20:22:51 -07:00
|
|
|
|
2013-04-04 23:17:20 -07:00
|
|
|
Kinetic.Container.prototype.drawScene.call(this, canvas);
|
2013-08-09 20:22:51 -07:00
|
|
|
|
|
|
|
|
this._fire(DRAW, {
|
|
|
|
|
node: this
|
|
|
|
|
});
|
|
|
|
|
|
2013-06-06 22:45:31 -07:00
|
|
|
return this;
|
2012-12-01 12:04:10 -08:00
|
|
|
},
|
2013-12-29 19:46:53 -08:00
|
|
|
drawHit: function(can) {
|
|
|
|
|
var layer = this.getLayer(),
|
|
|
|
|
canvas = can || (layer && layer.hitCanvas);
|
2013-07-21 23:14:41 -07:00
|
|
|
|
2013-04-04 23:17:20 -07:00
|
|
|
if(layer && layer.getClearBeforeDraw()) {
|
2013-08-31 21:49:18 -07:00
|
|
|
layer.getHitCanvas().getContext().clear();
|
2013-04-04 23:17:20 -07:00
|
|
|
}
|
|
|
|
|
|
2013-12-29 19:46:53 -08:00
|
|
|
Kinetic.Container.prototype.drawHit.call(this, canvas);
|
2013-06-06 22:45:31 -07:00
|
|
|
return this;
|
2012-12-01 12:04:10 -08:00
|
|
|
},
|
|
|
|
|
/**
|
|
|
|
|
* get layer canvas
|
2013-05-15 09:27:22 -07:00
|
|
|
* @method
|
|
|
|
|
* @memberof Kinetic.Node.prototype
|
2012-12-01 12:04:10 -08:00
|
|
|
*/
|
|
|
|
|
getCanvas: function() {
|
2013-07-21 23:14:41 -07:00
|
|
|
return this.canvas;
|
2012-12-01 12:04:10 -08:00
|
|
|
},
|
2013-03-23 20:02:11 -07:00
|
|
|
/**
|
|
|
|
|
* get layer hit canvas
|
2013-05-15 09:27:22 -07:00
|
|
|
* @method
|
|
|
|
|
* @memberof Kinetic.Node.prototype
|
2013-03-23 20:02:11 -07:00
|
|
|
*/
|
|
|
|
|
getHitCanvas: function() {
|
|
|
|
|
return this.hitCanvas;
|
|
|
|
|
},
|
2012-12-01 12:04:10 -08:00
|
|
|
/**
|
|
|
|
|
* get layer canvas context
|
2013-05-15 09:27:22 -07:00
|
|
|
* @method
|
|
|
|
|
* @memberof Kinetic.Node.prototype
|
2012-12-01 12:04:10 -08:00
|
|
|
*/
|
|
|
|
|
getContext: function() {
|
2013-07-21 23:14:41 -07:00
|
|
|
return this.getCanvas().getContext();
|
2012-12-01 12:04:10 -08:00
|
|
|
},
|
|
|
|
|
/**
|
2013-09-23 08:31:14 -07:00
|
|
|
* clear scene and hit canvas contexts tied to the layer
|
2013-05-15 09:27:22 -07:00
|
|
|
* @method
|
|
|
|
|
* @memberof Kinetic.Node.prototype
|
2013-12-02 21:32:46 -08:00
|
|
|
* @param {Object} [bounds]
|
|
|
|
|
* @param {Number} [bounds.x]
|
|
|
|
|
* @param {Number} [bounds.y]
|
|
|
|
|
* @param {Number} [bounds.width]
|
|
|
|
|
* @param {Number} [bounds.height]
|
2013-08-11 20:34:54 -07:00
|
|
|
* @example
|
2013-09-23 08:31:14 -07:00
|
|
|
* layer.clear();<br>
|
|
|
|
|
* layer.clear(0, 0, 100, 100);
|
2012-12-01 12:04:10 -08:00
|
|
|
*/
|
2013-12-02 21:32:46 -08:00
|
|
|
clear: function(bounds) {
|
2013-09-23 08:31:14 -07:00
|
|
|
var context = this.getContext(),
|
|
|
|
|
hitContext = this.getHitCanvas().getContext();
|
|
|
|
|
|
2013-12-02 21:32:46 -08:00
|
|
|
context.clear(bounds);
|
|
|
|
|
hitContext.clear(bounds);
|
2013-06-06 22:45:31 -07:00
|
|
|
return this;
|
2012-12-01 12:04:10 -08:00
|
|
|
},
|
2013-08-31 21:49:18 -07:00
|
|
|
// extend Node.prototype.setVisible
|
2012-12-01 12:04:10 -08:00
|
|
|
setVisible: function(visible) {
|
|
|
|
|
Kinetic.Node.prototype.setVisible.call(this, visible);
|
|
|
|
|
if(visible) {
|
2013-08-31 21:49:18 -07:00
|
|
|
this.getCanvas()._canvas.style.display = 'block';
|
|
|
|
|
this.hitCanvas._canvas.style.display = 'block';
|
2012-10-05 18:59:03 -07:00
|
|
|
}
|
|
|
|
|
else {
|
2013-08-31 21:49:18 -07:00
|
|
|
this.getCanvas()._canvas.style.display = 'none';
|
|
|
|
|
this.hitCanvas._canvas.style.display = 'none';
|
2012-10-05 18:59:03 -07:00
|
|
|
}
|
2013-06-06 22:45:31 -07:00
|
|
|
return this;
|
2012-12-01 12:04:10 -08:00
|
|
|
},
|
2013-08-31 21:49:18 -07:00
|
|
|
// extend Node.prototype.setZIndex
|
2012-12-01 12:04:10 -08:00
|
|
|
setZIndex: function(index) {
|
|
|
|
|
Kinetic.Node.prototype.setZIndex.call(this, index);
|
2012-09-25 15:57:57 -07:00
|
|
|
var stage = this.getStage();
|
|
|
|
|
if(stage) {
|
2013-08-31 21:49:18 -07:00
|
|
|
stage.content.removeChild(this.getCanvas()._canvas);
|
2012-09-25 15:57:57 -07:00
|
|
|
|
2012-12-01 12:04:10 -08:00
|
|
|
if(index < stage.getChildren().length - 1) {
|
2013-08-31 21:49:18 -07:00
|
|
|
stage.content.insertBefore(this.getCanvas()._canvas, stage.getChildren()[index + 1].getCanvas()._canvas);
|
2012-09-25 15:57:57 -07:00
|
|
|
}
|
|
|
|
|
else {
|
2013-08-31 21:49:18 -07:00
|
|
|
stage.content.appendChild(this.getCanvas()._canvas);
|
2012-09-25 15:57:57 -07:00
|
|
|
}
|
|
|
|
|
}
|
2013-06-06 22:45:31 -07:00
|
|
|
return this;
|
2012-12-01 12:04:10 -08:00
|
|
|
},
|
2013-08-31 21:49:18 -07:00
|
|
|
// extend Node.prototype.moveToTop
|
2012-12-01 12:04:10 -08:00
|
|
|
moveToTop: function() {
|
|
|
|
|
Kinetic.Node.prototype.moveToTop.call(this);
|
2012-09-25 15:57:57 -07:00
|
|
|
var stage = this.getStage();
|
|
|
|
|
if(stage) {
|
2013-08-31 21:49:18 -07:00
|
|
|
stage.content.removeChild(this.getCanvas()._canvas);
|
|
|
|
|
stage.content.appendChild(this.getCanvas()._canvas);
|
2012-09-25 15:57:57 -07:00
|
|
|
}
|
2012-12-01 12:04:10 -08:00
|
|
|
},
|
2013-08-31 21:49:18 -07:00
|
|
|
// extend Node.prototype.moveUp
|
2012-12-01 12:04:10 -08:00
|
|
|
moveUp: function() {
|
|
|
|
|
if(Kinetic.Node.prototype.moveUp.call(this)) {
|
|
|
|
|
var stage = this.getStage();
|
|
|
|
|
if(stage) {
|
2013-08-31 21:49:18 -07:00
|
|
|
stage.content.removeChild(this.getCanvas()._canvas);
|
2012-12-01 12:04:10 -08:00
|
|
|
|
|
|
|
|
if(this.index < stage.getChildren().length - 1) {
|
2013-08-31 21:49:18 -07:00
|
|
|
stage.content.insertBefore(this.getCanvas()._canvas, stage.getChildren()[this.index + 1].getCanvas()._canvas);
|
2012-12-01 12:04:10 -08:00
|
|
|
}
|
|
|
|
|
else {
|
2013-08-31 21:49:18 -07:00
|
|
|
stage.content.appendChild(this.getCanvas()._canvas);
|
2012-12-01 12:04:10 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
2013-08-31 21:49:18 -07:00
|
|
|
// extend Node.prototype.moveDown
|
2012-12-01 12:04:10 -08:00
|
|
|
moveDown: function() {
|
|
|
|
|
if(Kinetic.Node.prototype.moveDown.call(this)) {
|
|
|
|
|
var stage = this.getStage();
|
|
|
|
|
if(stage) {
|
|
|
|
|
var children = stage.getChildren();
|
2013-08-31 21:49:18 -07:00
|
|
|
stage.content.removeChild(this.getCanvas()._canvas);
|
|
|
|
|
stage.content.insertBefore(this.getCanvas()._canvas, children[this.index + 1].getCanvas()._canvas);
|
2012-12-01 12:04:10 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
2013-08-31 21:49:18 -07:00
|
|
|
// extend Node.prototype.moveToBottom
|
2012-12-01 12:04:10 -08:00
|
|
|
moveToBottom: function() {
|
|
|
|
|
if(Kinetic.Node.prototype.moveToBottom.call(this)) {
|
|
|
|
|
var stage = this.getStage();
|
|
|
|
|
if(stage) {
|
|
|
|
|
var children = stage.getChildren();
|
2013-08-31 21:49:18 -07:00
|
|
|
stage.content.removeChild(this.getCanvas()._canvas);
|
|
|
|
|
stage.content.insertBefore(this.getCanvas()._canvas, children[1].getCanvas()._canvas);
|
2012-12-01 12:04:10 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getLayer: function() {
|
|
|
|
|
return this;
|
|
|
|
|
},
|
|
|
|
|
remove: function() {
|
2013-08-31 21:49:18 -07:00
|
|
|
var stage = this.getStage(),
|
|
|
|
|
canvas = this.getCanvas(),
|
|
|
|
|
_canvas = canvas._canvas;
|
|
|
|
|
|
2012-12-01 12:04:10 -08:00
|
|
|
Kinetic.Node.prototype.remove.call(this);
|
2013-01-12 22:01:12 -08:00
|
|
|
|
2013-08-31 21:49:18 -07:00
|
|
|
if(stage && _canvas && Kinetic.Util._isInDocument(_canvas)) {
|
|
|
|
|
stage.content.removeChild(_canvas);
|
2012-09-25 15:57:57 -07:00
|
|
|
}
|
2013-06-06 22:45:31 -07:00
|
|
|
return this;
|
2013-08-11 20:34:54 -07:00
|
|
|
},
|
|
|
|
|
getStage: function() {
|
|
|
|
|
return this.parent;
|
2013-12-09 22:31:18 -08:00
|
|
|
},
|
|
|
|
|
/**
|
|
|
|
|
* enable hit graph
|
|
|
|
|
* @name enableHitGraph
|
|
|
|
|
* @method
|
|
|
|
|
* @memberof Kinetic.Layer.prototype
|
|
|
|
|
* @returns {Node}
|
|
|
|
|
*/
|
|
|
|
|
enableHitGraph: function() {
|
|
|
|
|
this.setHitGraphEnabled(true);
|
|
|
|
|
return this;
|
|
|
|
|
},
|
|
|
|
|
/**
|
|
|
|
|
* disable hit graph
|
|
|
|
|
* @name enableHitGraph
|
|
|
|
|
* @method
|
|
|
|
|
* @memberof Kinetic.Layer.prototype
|
|
|
|
|
* @returns {Node}
|
|
|
|
|
*/
|
|
|
|
|
disableHitGraph: function() {
|
|
|
|
|
this.setHitGraphEnabled(false);
|
|
|
|
|
return this;
|
2012-09-25 15:57:57 -07:00
|
|
|
}
|
2013-05-07 23:17:57 -07:00
|
|
|
});
|
2013-05-07 23:51:02 -07:00
|
|
|
Kinetic.Util.extend(Kinetic.Layer, Kinetic.Container);
|
2012-12-01 12:04:10 -08:00
|
|
|
|
|
|
|
|
// add getters and setters
|
2013-12-09 22:31:18 -08:00
|
|
|
Kinetic.Factory.addGetterSetter(Kinetic.Layer, 'clearBeforeDraw', true);
|
toDataURL() is now synchronous, and works with all nodes, including the stage, layers, groups, and shapes. This also sets things up nicely for node caching. You can now cache anything, including the whole stage, layers, groups, or shapes, manifested as Kinetic Images that were instantiated with data urls
2012-07-14 18:10:37 -07:00
|
|
|
/**
|
2014-01-05 20:52:09 -08:00
|
|
|
* get/set clearBeforeDraw flag which determines if the layer is cleared or not
|
2012-12-01 12:04:10 -08:00
|
|
|
* before drawing
|
2014-01-05 20:52:09 -08:00
|
|
|
* @name clearBeforeDraw
|
2013-05-15 09:27:22 -07:00
|
|
|
* @method
|
2013-12-09 22:31:18 -08:00
|
|
|
* @memberof Kinetic.Layer.prototype
|
2012-12-01 12:04:10 -08:00
|
|
|
* @param {Boolean} clearBeforeDraw
|
2013-12-09 22:31:18 -08:00
|
|
|
* @returns {Boolean}
|
2014-01-05 20:52:09 -08:00
|
|
|
* @example
|
|
|
|
|
* // get clearBeforeDraw flag<br>
|
|
|
|
|
* var clearBeforeDraw = layer.clearBeforeDraw();<br><br>
|
|
|
|
|
*
|
|
|
|
|
* // disable clear before draw<br>
|
|
|
|
|
* layer.clearBeforeDraw(false);<br><br>
|
|
|
|
|
*
|
|
|
|
|
* // enable clear before draw<br>
|
|
|
|
|
* layer.clearBeforeDraw(true);
|
2012-08-26 18:25:51 -07:00
|
|
|
*/
|
2013-12-09 22:31:18 -08:00
|
|
|
|
|
|
|
|
Kinetic.Factory.addGetterSetter(Kinetic.Layer, 'hitGraphEnabled', true);
|
|
|
|
|
/**
|
2014-01-05 20:52:09 -08:00
|
|
|
* get/set hitGraphEnabled flag. Disabling the hit graph will greatly increase
|
|
|
|
|
* draw performance because the hit graph will not be redrawn each time the layer is
|
|
|
|
|
* drawn. This, however, also disables mouse/touch event detection
|
|
|
|
|
* @name hitGraphEnabled
|
2013-12-09 22:31:18 -08:00
|
|
|
* @method
|
|
|
|
|
* @memberof Kinetic.Layer.prototype
|
2013-12-09 22:46:58 -08:00
|
|
|
* @param {Boolean} enabled
|
2013-12-09 22:31:18 -08:00
|
|
|
* @returns {Boolean}
|
2014-01-05 20:52:09 -08:00
|
|
|
* @example
|
|
|
|
|
* // get hitGraphEnabled flag<br>
|
|
|
|
|
* var hitGraphEnabled = layer.hitGraphEnabled();<br><br>
|
|
|
|
|
*
|
|
|
|
|
* // disable hit graph<br>
|
|
|
|
|
* layer.hitGraphEnabled(false);<br><br>
|
|
|
|
|
*
|
|
|
|
|
* // enable hit graph<br>
|
|
|
|
|
* layer.hitGraphEnabled(true);
|
2013-12-09 22:31:18 -08:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Kinetic.Layer.prototype.isHitGraphEnabled = Kinetic.Layer.prototype.getHitGraphEnabled;
|
2012-12-01 12:04:10 -08:00
|
|
|
})();
|