This commit is contained in:
Eric Rowell 2013-11-27 21:32:36 -08:00
parent bc9bd291fc
commit aa78d632db
4 changed files with 114 additions and 48 deletions

View File

@ -2,7 +2,28 @@
// constants
var HASH = '#',
BEFORE_DRAW ='beforeDraw',
DRAW = 'draw';
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) {
@ -19,39 +40,46 @@
}
},
/**
* get visible intersection object that contains shape and pixel data. This is the preferred
* 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 point object
* @param {Kinetic.Shape} shape
*/
getIntersection: function() {
var pos = Kinetic.Util._getXY(Array.prototype.slice.call(arguments)),
p, colorKey, shape;
shape, i, intersectionOffset;
if(this.isVisible()) {
p = this.hitCanvas.context._context.getImageData(pos.x | 0, pos.y | 0, 1, 1).data;
// this indicates that a hit pixel may have been found
if(p[3] === 255) {
colorKey = Kinetic.Util._rgbToHex(p[0], p[1], p[2]);
shape = Kinetic.shapes[HASH + colorKey];
return {
shape: shape,
pixel: p
};
}
else {
// if no shape mapped to that pixel, just return the pixel array
return {
pixel: p
};
for (i=0; i<INTERSECTION_OFFSETS_LEN; i++) {
intersectionOffset = INTERSECTION_OFFSETS[i];
shape = this._getIntersection({
x: pos.x + intersectionOffset.x,
y: pos.y + intersectionOffset.y
});
if (shape) {
return shape;
}
}
}
else {
return null;
}
},
_getIntersection: function(pos) {
var p = this.hitCanvas.context._context.getImageData(pos.x, pos.y, 1, 1).data,
colorKey, shape;
// this indicates that a hit pixel may have been found
if(p[3] === 255) {
colorKey = Kinetic.Util._rgbToHex(p[0], p[1], p[2]);
shape = Kinetic.shapes[HASH + colorKey];
return shape;
}
else {
return null
}
},
drawScene: function(canvas) {
canvas = canvas || this.getCanvas();

View File

@ -42,7 +42,7 @@
UNDERSCORE = '_',
CONTAINER = 'container',
EMPTY_STRING = '',
EVENTS = [MOUSEDOWN, MOUSEMOVE, MOUSEUP, MOUSEOUT, TOUCHSTART, TOUCHMOVE, TOUCHEND, MOUSEOVER],
EVENTS = [MOUSEDOWN, MOUSEMOVE, MOUSEUP, MOUSEOUT, TOUCHSTART, TOUCHMOVE, TOUCHEND, MOUSEOVER];
// cached variables
eventsLength = EVENTS.length;
@ -250,24 +250,24 @@
this.toDataURL(config);
},
/**
* get visible intersection object that contains shape and pixel data. This is the preferred
* get visible intersection shape. This is the preferred
* method for determining if a point intersects a shape or not
* @method
* @memberof Kinetic.Stage.prototype
* @param {Object} pos point object
* @param {Kinetic.Shape} shape
*/
getIntersection: function() {
var pos = Kinetic.Util._getXY(Array.prototype.slice.call(arguments)),
layers = this.getChildren(),
len = layers.length,
end = len - 1,
n, obj;
n, shape;
for(n = end; n >= 0; n--) {
obj = layers[n].getIntersection(pos);
if (obj) {
return obj;
}
shape = layers[n].getIntersection(pos);
if (shape) {
return shape;
}
}
return null;
@ -355,11 +355,10 @@
_mousemove: function(evt) {
this._setPointerPosition(evt);
var dd = Kinetic.DD,
obj = this.getIntersection(this.getPointerPosition()),
shape = obj && obj.shape ? obj.shape : undefined;
shape = this.getIntersection(this.getPointerPosition());
if(shape && shape.isListening()) {
if(!Kinetic.isDragging() && obj.pixel[3] === 255 && (!this.targetShape || this.targetShape._id !== shape._id)) {
if(!Kinetic.isDragging() && (!this.targetShape || this.targetShape._id !== shape._id)) {
if(this.targetShape) {
this.targetShape._fireAndBubble(MOUSEOUT, evt, shape);
this.targetShape._fireAndBubble(MOUSELEAVE, evt, shape);
@ -400,8 +399,7 @@
},
_mousedown: function(evt) {
this._setPointerPosition(evt);
var obj = this.getIntersection(this.getPointerPosition()),
shape = obj && obj.shape ? obj.shape : undefined;
var shape = this.getIntersection(this.getPointerPosition());
Kinetic.listenClickTap = true;
@ -422,8 +420,7 @@
_mouseup: function(evt) {
this._setPointerPosition(evt);
var that = this,
obj = this.getIntersection(this.getPointerPosition()),
shape = obj && obj.shape ? obj.shape : undefined,
shape = this.getIntersection(this.getPointerPosition()),
fireDblClick = false;
if(Kinetic.inDblClickWindow) {
@ -469,8 +466,7 @@
},
_touchstart: function(evt) {
this._setPointerPosition(evt);
var obj = this.getIntersection(this.getPointerPosition()),
shape = obj && obj.shape ? obj.shape : undefined;
var shape = this.getIntersection(this.getPointerPosition());
Kinetic.listenClickTap = true;
@ -489,8 +485,7 @@
_touchend: function(evt) {
this._setPointerPosition(evt);
var that = this,
obj = this.getIntersection(this.getPointerPosition()),
shape = obj && obj.shape ? obj.shape : undefined,
shape = this.getIntersection(this.getPointerPosition());
fireDblClick = false;
if(Kinetic.inDblClickWindow) {
@ -534,8 +529,7 @@
_touchmove: function(evt) {
this._setPointerPosition(evt);
var dd = Kinetic.DD,
obj = this.getIntersection(this.getPointerPosition()),
shape = obj && obj.shape ? obj.shape : undefined;
shape = this.getIntersection(this.getPointerPosition());
if (shape && shape.isListening()) {
shape._fireAndBubble(TOUCHMOVE, evt);

View File

@ -130,9 +130,9 @@ suite('Layer', function() {
layer.add(greenCircle);
stage.add(layer);
assert.equal(layer.getIntersection(300, 100).shape.getId(), 'greenCircle', 'shape should be greenCircle');
assert.equal(layer.getIntersection(380, 100).shape.getId(), 'redCircle', 'shape should be redCircle');
assert.equal(layer.getIntersection(100, 100).shape, null, 'shape should be null');
assert.equal(layer.getIntersection(300, 100).getId(), 'greenCircle', 'shape should be greenCircle');
assert.equal(layer.getIntersection(380, 100).getId(), 'redCircle', 'shape should be redCircle');
assert.equal(layer.getIntersection(100, 100), null, 'shape should be null');
});

View File

@ -141,7 +141,7 @@ suite('Stage', function() {
});
// ======================================================
test('stage getAllIntersections()', function() {
test('stage getIntersection()', function() {
var stage = addStage();
var layer = new Kinetic.Layer();
@ -169,9 +169,53 @@ suite('Stage', function() {
layer.add(greenCircle);
stage.add(layer);
assert.equal(stage.getIntersection(300, 100).shape.getId(), 'greenCircle', 'shape should be greenCircle');
assert.equal(stage.getIntersection(380, 100).shape.getId(), 'redCircle', 'shape should be redCircle');
assert.equal(stage.getIntersection(100, 100).shape, null, 'shape should be null');
assert.equal(stage.getIntersection(300, 100).getId(), 'greenCircle', 'shape should be greenCircle');
assert.equal(stage.getIntersection(380, 100).getId(), 'redCircle', 'shape should be redCircle');
assert.equal(stage.getIntersection(100, 100), null, 'shape should be null');
});
// ======================================================
test('stage getIntersection() edge detection', function() {
var stage = addStage();
var layer = new Kinetic.Layer();
var redCircle = new Kinetic.Circle({
x: 380,
y: stage.getHeight() / 2,
radius: 70,
strokeWidth: 4,
fill: 'red',
stroke: 'black',
id: 'redCircle'
});
var greenCircle = new Kinetic.Circle({
x: 300,
y: stage.getHeight() / 2,
radius: 70,
strokeWidth: 4,
fill: 'green',
stroke: 'black',
id: 'greenCircle'
});
stage.on('contentMousemove', function() {
var pos = stage.getPointerPosition();
var shape = stage.getIntersection(pos);
if (!shape){
//console.log(pos);
}
});
layer.add(redCircle);
layer.add(greenCircle);
stage.add(layer);
assert.equal(stage.getIntersection(370, 93).getId(), 'greenCircle', 'shape should be greenCircle');
assert.equal(stage.getIntersection(371, 93).getId(), 'greenCircle', 'shape should be greenCircle');
assert.equal(stage.getIntersection(372, 93).getId(), 'redCircle', 'shape should be greenCircle');
});