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-04-04 23:17:20 -07:00
|
|
|
drawScene: function(canvas) {
|
2013-06-01 22:03:02 -07:00
|
|
|
canvas = canvas || this.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-04-04 23:17:20 -07:00
|
|
|
drawHit: function() {
|
|
|
|
|
var layer = this.getLayer();
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Kinetic.Container.prototype.drawHit.call(this);
|
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);
|
2012-12-01 12:04:10 -08:00
|
|
|
|
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
|
|
|
/**
|
2012-12-01 12:04:10 -08:00
|
|
|
* set flag which determines if the layer is cleared or not
|
|
|
|
|
* before drawing
|
|
|
|
|
* @name setClearBeforeDraw
|
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 {Node}
|
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
|
|
|
*/
|
2012-07-21 15:38:25 -07:00
|
|
|
|
2012-08-26 18:25:51 -07:00
|
|
|
/**
|
2012-12-01 12:04:10 -08:00
|
|
|
* get flag which determines if the layer is cleared or not
|
|
|
|
|
* before drawing
|
|
|
|
|
* @name getClearBeforeDraw
|
2013-05-15 09:27:22 -07:00
|
|
|
* @method
|
2013-12-09 22:31:18 -08:00
|
|
|
* @memberof Kinetic.Layer.prototype
|
|
|
|
|
* @returns {Boolean}
|
2012-08-26 18:25:51 -07:00
|
|
|
*/
|
2013-12-09 22:31:18 -08:00
|
|
|
|
|
|
|
|
Kinetic.Factory.addGetterSetter(Kinetic.Layer, 'hitGraphEnabled', true);
|
|
|
|
|
|
|
|
|
|
/**
|
2013-12-09 22:46:58 -08:00
|
|
|
* enable/disable hit graph
|
2013-12-09 22:31:18 -08:00
|
|
|
* @name setHitGraphEnabled
|
|
|
|
|
* @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 {Node}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
2013-12-09 22:46:58 -08:00
|
|
|
* determine if hit graph is enabled
|
2013-12-09 22:31:18 -08:00
|
|
|
* @name getHitGraphEnabled
|
|
|
|
|
* @method
|
|
|
|
|
* @memberof Kinetic.Layer.prototype
|
|
|
|
|
* @returns {Boolean}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Kinetic.Layer.prototype.isHitGraphEnabled = Kinetic.Layer.prototype.getHitGraphEnabled;
|
2012-12-01 12:04:10 -08:00
|
|
|
})();
|