mirror of
https://github.com/konvajs/konva.git
synced 2025-06-27 16:36:58 +08:00
finished pixel detection algo which can be applied to any Shape. This enables a lot of new functionality, such as image pixel detection, shape border detection, and custom shape detection that isn't drawn with a standard path
This commit is contained in:
parent
08e2b74da9
commit
95fabe9160
43
dist/kinetic-core.js
vendored
43
dist/kinetic-core.js
vendored
@ -1280,7 +1280,7 @@ Kinetic.Stage.prototype = {
|
||||
this.targetFound = true;
|
||||
}
|
||||
|
||||
if(shape.visible && pos !== undefined && shape._isPointInPath(pos)) {
|
||||
if(shape.visible && pos !== undefined && shape._isPointInShape(pos)) {
|
||||
// handle onmousedown
|
||||
if(!isDragging && this.mouseDown) {
|
||||
this.mouseDown = false;
|
||||
@ -1482,8 +1482,8 @@ Kinetic.Stage.prototype = {
|
||||
* clear default layers
|
||||
*/
|
||||
_clearDefaultLayers: function() {
|
||||
var pathLayer = this.pathLayer;
|
||||
pathLayer.clear();
|
||||
this.bufferLayer.clear();
|
||||
this.pathLayer.clear();
|
||||
},
|
||||
/**
|
||||
* begin listening for events by adding event handlers
|
||||
@ -1902,6 +1902,8 @@ Kinetic.GlobalObject.extend(Kinetic.Group, Kinetic.Node);
|
||||
* @config {Number} [strokeWidth] stroke width
|
||||
* @config {String} [lineJoin] line join. Can be "miter", "round", or "bevel". The default
|
||||
* is "miter"
|
||||
* @config {String} [detectionType] shape detection type. Can be "path" or "pixel".
|
||||
* The default is "path" because it performs better
|
||||
*/
|
||||
Kinetic.Shape = function(config) {
|
||||
this.className = 'Shape';
|
||||
@ -1916,6 +1918,10 @@ Kinetic.Shape = function(config) {
|
||||
}
|
||||
}
|
||||
|
||||
if(config.detectionType === undefined) {
|
||||
config.detectionType = 'path';
|
||||
}
|
||||
|
||||
// required
|
||||
this.drawFunc = config.drawFunc;
|
||||
|
||||
@ -2066,12 +2072,33 @@ Kinetic.Shape.prototype = {
|
||||
* custom isPointInPath method which can use path detection
|
||||
* or pixel detection
|
||||
*/
|
||||
_isPointInPath: function(pos) {
|
||||
_isPointInShape: function(pos) {
|
||||
var stage = this.getStage();
|
||||
var pathLayer = stage.pathLayer;
|
||||
var pathLayerContext = pathLayer.getContext();
|
||||
this._draw(pathLayer);
|
||||
return pathLayerContext.isPointInPath(pos.x, pos.y);
|
||||
|
||||
if(this.detectionType === 'path') {
|
||||
var pathLayer = stage.pathLayer;
|
||||
var pathLayerContext = pathLayer.getContext();
|
||||
|
||||
this._draw(pathLayer);
|
||||
|
||||
return pathLayerContext.isPointInPath(pos.x, pos.y);
|
||||
}
|
||||
else {
|
||||
var bufferLayer = stage.bufferLayer;
|
||||
var bufferLayerContext = bufferLayer.getContext();
|
||||
|
||||
this._draw(bufferLayer);
|
||||
|
||||
var w = stage.width;
|
||||
var h = stage.height;
|
||||
var x = pos.x;
|
||||
var y = pos.y;
|
||||
var imageData = bufferLayerContext.getImageData(0, 0, w, h);
|
||||
var data = imageData.data;
|
||||
var alpha = data[((w * y) + x) * 4 + 3];
|
||||
|
||||
return (alpha !== undefined && alpha !== 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
// extend Node
|
||||
|
2
dist/kinetic-core.min.js
vendored
2
dist/kinetic-core.min.js
vendored
File diff suppressed because one or more lines are too long
37
src/Shape.js
37
src/Shape.js
@ -12,6 +12,8 @@
|
||||
* @config {Number} [strokeWidth] stroke width
|
||||
* @config {String} [lineJoin] line join. Can be "miter", "round", or "bevel". The default
|
||||
* is "miter"
|
||||
* @config {String} [detectionType] shape detection type. Can be "path" or "pixel".
|
||||
* The default is "path" because it performs better
|
||||
*/
|
||||
Kinetic.Shape = function(config) {
|
||||
this.className = 'Shape';
|
||||
@ -26,6 +28,10 @@ Kinetic.Shape = function(config) {
|
||||
}
|
||||
}
|
||||
|
||||
if(config.detectionType === undefined) {
|
||||
config.detectionType = 'path';
|
||||
}
|
||||
|
||||
// required
|
||||
this.drawFunc = config.drawFunc;
|
||||
|
||||
@ -176,12 +182,33 @@ Kinetic.Shape.prototype = {
|
||||
* custom isPointInPath method which can use path detection
|
||||
* or pixel detection
|
||||
*/
|
||||
_isPointInPath: function(pos) {
|
||||
_isPointInShape: function(pos) {
|
||||
var stage = this.getStage();
|
||||
var pathLayer = stage.pathLayer;
|
||||
var pathLayerContext = pathLayer.getContext();
|
||||
this._draw(pathLayer);
|
||||
return pathLayerContext.isPointInPath(pos.x, pos.y);
|
||||
|
||||
if(this.detectionType === 'path') {
|
||||
var pathLayer = stage.pathLayer;
|
||||
var pathLayerContext = pathLayer.getContext();
|
||||
|
||||
this._draw(pathLayer);
|
||||
|
||||
return pathLayerContext.isPointInPath(pos.x, pos.y);
|
||||
}
|
||||
else {
|
||||
var bufferLayer = stage.bufferLayer;
|
||||
var bufferLayerContext = bufferLayer.getContext();
|
||||
|
||||
this._draw(bufferLayer);
|
||||
|
||||
var w = stage.width;
|
||||
var h = stage.height;
|
||||
var x = pos.x;
|
||||
var y = pos.y;
|
||||
var imageData = bufferLayerContext.getImageData(0, 0, w, h);
|
||||
var data = imageData.data;
|
||||
var alpha = data[((w * y) + x) * 4 + 3];
|
||||
|
||||
return (alpha !== undefined && alpha !== 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
// extend Node
|
||||
|
@ -254,7 +254,7 @@ Kinetic.Stage.prototype = {
|
||||
this.targetFound = true;
|
||||
}
|
||||
|
||||
if(shape.visible && pos !== undefined && shape._isPointInPath(pos)) {
|
||||
if(shape.visible && pos !== undefined && shape._isPointInShape(pos)) {
|
||||
// handle onmousedown
|
||||
if(!isDragging && this.mouseDown) {
|
||||
this.mouseDown = false;
|
||||
@ -456,8 +456,8 @@ Kinetic.Stage.prototype = {
|
||||
* clear default layers
|
||||
*/
|
||||
_clearDefaultLayers: function() {
|
||||
var pathLayer = this.pathLayer;
|
||||
pathLayer.clear();
|
||||
this.bufferLayer.clear();
|
||||
this.pathLayer.clear();
|
||||
},
|
||||
/**
|
||||
* begin listening for events by adding event handlers
|
||||
|
@ -519,6 +519,75 @@ Test.prototype.tests = {
|
||||
};
|
||||
imageObj.src = '../darth-vader.jpg';
|
||||
},
|
||||
/*
|
||||
* WARNING: this functional test will only pass if it's hosted on
|
||||
* a webserver due to cross domain security issues
|
||||
*/
|
||||
'EVENTS - image pixel detection': function(containerId) {
|
||||
var imageObj = new Image();
|
||||
imageObj.onload = function() {
|
||||
var stage = new Kinetic.Stage({
|
||||
container: containerId,
|
||||
width: 578,
|
||||
height: 200
|
||||
});
|
||||
var layer = new Kinetic.Layer();
|
||||
var darth = new Kinetic.Image({
|
||||
x: 200,
|
||||
y: 40,
|
||||
image: imageObj,
|
||||
detectionType: 'pixel',
|
||||
draggable: true
|
||||
});
|
||||
|
||||
darth.on('mouseover', function() {
|
||||
log('mouseover');
|
||||
});
|
||||
|
||||
darth.on('mouseout', function() {
|
||||
log('mouseout');
|
||||
});
|
||||
|
||||
layer.add(darth);
|
||||
stage.add(layer);
|
||||
};
|
||||
imageObj.src = '../lion.png';
|
||||
},
|
||||
'EVENTS - star pixel detection': function(containerId) {
|
||||
var imageObj = new Image();
|
||||
imageObj.onload = function() {
|
||||
var stage = new Kinetic.Stage({
|
||||
container: containerId,
|
||||
width: 578,
|
||||
height: 200
|
||||
});
|
||||
var layer = new Kinetic.Layer();
|
||||
var star = new Kinetic.Star({
|
||||
x: 200,
|
||||
y: 100,
|
||||
points: 10,
|
||||
innerRadius: 40,
|
||||
outerRadius: 70,
|
||||
fill: 'green',
|
||||
stroke: 'blue',
|
||||
strokeWidth: 20,
|
||||
detectionType: 'pixel',
|
||||
draggable: true
|
||||
});
|
||||
|
||||
star.on('mouseover', function() {
|
||||
log('mouseover');
|
||||
});
|
||||
|
||||
star.on('mouseout', function() {
|
||||
log('mouseout');
|
||||
});
|
||||
|
||||
layer.add(star);
|
||||
stage.add(layer);
|
||||
};
|
||||
imageObj.src = '../lion.png';
|
||||
},
|
||||
'EVENTS - drag events click': function(containerId) {
|
||||
var stage = new Kinetic.Stage({
|
||||
container: containerId,
|
||||
|
BIN
tests/lion.png
Normal file
BIN
tests/lion.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
Loading…
Reference in New Issue
Block a user