mirror of
https://github.com/konvajs/konva.git
synced 2026-01-23 13:26:07 +08:00
292 lines
9.3 KiB
JavaScript
292 lines
9.3 KiB
JavaScript
(function() {
|
|
// constants
|
|
var HASH = '#',
|
|
BEFORE_DRAW ='beforeDraw',
|
|
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;
|
|
|
|
|
|
Kinetic.Util.addMethods(Kinetic.Layer, {
|
|
___init: function(config) {
|
|
this.nodeType = 'Layer';
|
|
this.canvas = new Kinetic.SceneCanvas();
|
|
this.hitCanvas = new Kinetic.HitCanvas();
|
|
// call super constructor
|
|
Kinetic.Container.call(this, config);
|
|
},
|
|
_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.');
|
|
}
|
|
},
|
|
/**
|
|
* get visible intersection shape. This is the preferred
|
|
* method for determining if a point intersects a shape or not
|
|
* @method
|
|
* @memberof Kinetic.Layer.prototype
|
|
* @param {Object} pos
|
|
* @param {Number} pos.x
|
|
* @param {Number} pos.y
|
|
* @returns {Kinetic.Shape}
|
|
*/
|
|
getIntersection: function(pos) {
|
|
var obj, i, intersectionOffset, shape;
|
|
|
|
if(this.isVisible()) {
|
|
for (i=0; i<INTERSECTION_OFFSETS_LEN; i++) {
|
|
intersectionOffset = INTERSECTION_OFFSETS[i];
|
|
obj = this._getIntersection({
|
|
x: pos.x + intersectionOffset.x,
|
|
y: pos.y + intersectionOffset.y
|
|
});
|
|
shape = obj.shape;
|
|
if (shape) {
|
|
return shape;
|
|
}
|
|
else if (!obj.antialiased) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
return null;
|
|
}
|
|
},
|
|
_getIntersection: function(pos) {
|
|
var p = this.hitCanvas.context._context.getImageData(pos.x, pos.y, 1, 1).data,
|
|
p3 = p[3],
|
|
colorKey, shape;
|
|
|
|
// fully opaque pixel
|
|
if(p3 === 255) {
|
|
colorKey = Kinetic.Util._rgbToHex(p[0], p[1], p[2]);
|
|
shape = Kinetic.shapes[HASH + colorKey];
|
|
return {
|
|
shape: shape
|
|
};
|
|
}
|
|
// antialiased pixel
|
|
else if(p3 > 0) {
|
|
return {
|
|
antialiased: true
|
|
};
|
|
}
|
|
// empty pixel
|
|
else {
|
|
return {};
|
|
}
|
|
},
|
|
drawScene: function(canvas) {
|
|
canvas = canvas || this.getCanvas();
|
|
|
|
this._fire(BEFORE_DRAW, {
|
|
node: this
|
|
});
|
|
|
|
if(this.getClearBeforeDraw()) {
|
|
canvas.getContext().clear();
|
|
}
|
|
|
|
Kinetic.Container.prototype.drawScene.call(this, canvas);
|
|
|
|
this._fire(DRAW, {
|
|
node: this
|
|
});
|
|
|
|
return this;
|
|
},
|
|
drawHit: function() {
|
|
var layer = this.getLayer();
|
|
|
|
if(layer && layer.getClearBeforeDraw()) {
|
|
layer.getHitCanvas().getContext().clear();
|
|
}
|
|
|
|
Kinetic.Container.prototype.drawHit.call(this);
|
|
return this;
|
|
},
|
|
/**
|
|
* get layer canvas
|
|
* @method
|
|
* @memberof Kinetic.Node.prototype
|
|
*/
|
|
getCanvas: function() {
|
|
return this.canvas;
|
|
},
|
|
/**
|
|
* get layer hit canvas
|
|
* @method
|
|
* @memberof Kinetic.Node.prototype
|
|
*/
|
|
getHitCanvas: function() {
|
|
return this.hitCanvas;
|
|
},
|
|
/**
|
|
* get layer canvas context
|
|
* @method
|
|
* @memberof Kinetic.Node.prototype
|
|
*/
|
|
getContext: function() {
|
|
return this.getCanvas().getContext();
|
|
},
|
|
/**
|
|
* clear scene and hit canvas contexts tied to the layer
|
|
* @method
|
|
* @memberof Kinetic.Node.prototype
|
|
* @param {Object} [bounds]
|
|
* @param {Number} [bounds.x]
|
|
* @param {Number} [bounds.y]
|
|
* @param {Number} [bounds.width]
|
|
* @param {Number} [bounds.height]
|
|
* @example
|
|
* layer.clear();<br>
|
|
* layer.clear(0, 0, 100, 100);
|
|
*/
|
|
clear: function(bounds) {
|
|
var context = this.getContext(),
|
|
hitContext = this.getHitCanvas().getContext();
|
|
|
|
context.clear(bounds);
|
|
hitContext.clear(bounds);
|
|
return this;
|
|
},
|
|
// extend Node.prototype.setVisible
|
|
setVisible: function(visible) {
|
|
Kinetic.Node.prototype.setVisible.call(this, visible);
|
|
if(visible) {
|
|
this.getCanvas()._canvas.style.display = 'block';
|
|
this.hitCanvas._canvas.style.display = 'block';
|
|
}
|
|
else {
|
|
this.getCanvas()._canvas.style.display = 'none';
|
|
this.hitCanvas._canvas.style.display = 'none';
|
|
}
|
|
return this;
|
|
},
|
|
// extend Node.prototype.setZIndex
|
|
setZIndex: function(index) {
|
|
Kinetic.Node.prototype.setZIndex.call(this, index);
|
|
var stage = this.getStage();
|
|
if(stage) {
|
|
stage.content.removeChild(this.getCanvas()._canvas);
|
|
|
|
if(index < stage.getChildren().length - 1) {
|
|
stage.content.insertBefore(this.getCanvas()._canvas, stage.getChildren()[index + 1].getCanvas()._canvas);
|
|
}
|
|
else {
|
|
stage.content.appendChild(this.getCanvas()._canvas);
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
// extend Node.prototype.moveToTop
|
|
moveToTop: function() {
|
|
Kinetic.Node.prototype.moveToTop.call(this);
|
|
var stage = this.getStage();
|
|
if(stage) {
|
|
stage.content.removeChild(this.getCanvas()._canvas);
|
|
stage.content.appendChild(this.getCanvas()._canvas);
|
|
}
|
|
},
|
|
// extend Node.prototype.moveUp
|
|
moveUp: function() {
|
|
if(Kinetic.Node.prototype.moveUp.call(this)) {
|
|
var stage = this.getStage();
|
|
if(stage) {
|
|
stage.content.removeChild(this.getCanvas()._canvas);
|
|
|
|
if(this.index < stage.getChildren().length - 1) {
|
|
stage.content.insertBefore(this.getCanvas()._canvas, stage.getChildren()[this.index + 1].getCanvas()._canvas);
|
|
}
|
|
else {
|
|
stage.content.appendChild(this.getCanvas()._canvas);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
// extend Node.prototype.moveDown
|
|
moveDown: function() {
|
|
if(Kinetic.Node.prototype.moveDown.call(this)) {
|
|
var stage = this.getStage();
|
|
if(stage) {
|
|
var children = stage.getChildren();
|
|
stage.content.removeChild(this.getCanvas()._canvas);
|
|
stage.content.insertBefore(this.getCanvas()._canvas, children[this.index + 1].getCanvas()._canvas);
|
|
}
|
|
}
|
|
},
|
|
// extend Node.prototype.moveToBottom
|
|
moveToBottom: function() {
|
|
if(Kinetic.Node.prototype.moveToBottom.call(this)) {
|
|
var stage = this.getStage();
|
|
if(stage) {
|
|
var children = stage.getChildren();
|
|
stage.content.removeChild(this.getCanvas()._canvas);
|
|
stage.content.insertBefore(this.getCanvas()._canvas, children[1].getCanvas()._canvas);
|
|
}
|
|
}
|
|
},
|
|
getLayer: function() {
|
|
return this;
|
|
},
|
|
remove: function() {
|
|
var stage = this.getStage(),
|
|
canvas = this.getCanvas(),
|
|
_canvas = canvas._canvas;
|
|
|
|
Kinetic.Node.prototype.remove.call(this);
|
|
|
|
if(stage && _canvas && Kinetic.Util._isInDocument(_canvas)) {
|
|
stage.content.removeChild(_canvas);
|
|
}
|
|
return this;
|
|
},
|
|
getStage: function() {
|
|
return this.parent;
|
|
}
|
|
});
|
|
Kinetic.Util.extend(Kinetic.Layer, Kinetic.Container);
|
|
|
|
// add getters and setters
|
|
Kinetic.Factory.addGetterSetter(Kinetic.Layer, 'clearBeforeDraw', function() {
|
|
return true;
|
|
});
|
|
|
|
/**
|
|
* set flag which determines if the layer is cleared or not
|
|
* before drawing
|
|
* @name setClearBeforeDraw
|
|
* @method
|
|
* @memberof Kinetic.Node.prototype
|
|
* @param {Boolean} clearBeforeDraw
|
|
*/
|
|
|
|
/**
|
|
* get flag which determines if the layer is cleared or not
|
|
* before drawing
|
|
* @name getClearBeforeDraw
|
|
* @method
|
|
* @memberof Kinetic.Node.prototype
|
|
*/
|
|
})();
|