mirror of
https://github.com/konvajs/konva.git
synced 2025-06-28 00:14:29 +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;
|
this.targetFound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(shape.visible && pos !== undefined && shape._isPointInPath(pos)) {
|
if(shape.visible && pos !== undefined && shape._isPointInShape(pos)) {
|
||||||
// handle onmousedown
|
// handle onmousedown
|
||||||
if(!isDragging && this.mouseDown) {
|
if(!isDragging && this.mouseDown) {
|
||||||
this.mouseDown = false;
|
this.mouseDown = false;
|
||||||
@ -1482,8 +1482,8 @@ Kinetic.Stage.prototype = {
|
|||||||
* clear default layers
|
* clear default layers
|
||||||
*/
|
*/
|
||||||
_clearDefaultLayers: function() {
|
_clearDefaultLayers: function() {
|
||||||
var pathLayer = this.pathLayer;
|
this.bufferLayer.clear();
|
||||||
pathLayer.clear();
|
this.pathLayer.clear();
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* begin listening for events by adding event handlers
|
* 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 {Number} [strokeWidth] stroke width
|
||||||
* @config {String} [lineJoin] line join. Can be "miter", "round", or "bevel". The default
|
* @config {String} [lineJoin] line join. Can be "miter", "round", or "bevel". The default
|
||||||
* is "miter"
|
* 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) {
|
Kinetic.Shape = function(config) {
|
||||||
this.className = 'Shape';
|
this.className = 'Shape';
|
||||||
@ -1916,6 +1918,10 @@ Kinetic.Shape = function(config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(config.detectionType === undefined) {
|
||||||
|
config.detectionType = 'path';
|
||||||
|
}
|
||||||
|
|
||||||
// required
|
// required
|
||||||
this.drawFunc = config.drawFunc;
|
this.drawFunc = config.drawFunc;
|
||||||
|
|
||||||
@ -2066,12 +2072,33 @@ Kinetic.Shape.prototype = {
|
|||||||
* custom isPointInPath method which can use path detection
|
* custom isPointInPath method which can use path detection
|
||||||
* or pixel detection
|
* or pixel detection
|
||||||
*/
|
*/
|
||||||
_isPointInPath: function(pos) {
|
_isPointInShape: function(pos) {
|
||||||
var stage = this.getStage();
|
var stage = this.getStage();
|
||||||
var pathLayer = stage.pathLayer;
|
|
||||||
var pathLayerContext = pathLayer.getContext();
|
if(this.detectionType === 'path') {
|
||||||
this._draw(pathLayer);
|
var pathLayer = stage.pathLayer;
|
||||||
return pathLayerContext.isPointInPath(pos.x, pos.y);
|
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
|
// 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 {Number} [strokeWidth] stroke width
|
||||||
* @config {String} [lineJoin] line join. Can be "miter", "round", or "bevel". The default
|
* @config {String} [lineJoin] line join. Can be "miter", "round", or "bevel". The default
|
||||||
* is "miter"
|
* 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) {
|
Kinetic.Shape = function(config) {
|
||||||
this.className = 'Shape';
|
this.className = 'Shape';
|
||||||
@ -26,6 +28,10 @@ Kinetic.Shape = function(config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(config.detectionType === undefined) {
|
||||||
|
config.detectionType = 'path';
|
||||||
|
}
|
||||||
|
|
||||||
// required
|
// required
|
||||||
this.drawFunc = config.drawFunc;
|
this.drawFunc = config.drawFunc;
|
||||||
|
|
||||||
@ -176,12 +182,33 @@ Kinetic.Shape.prototype = {
|
|||||||
* custom isPointInPath method which can use path detection
|
* custom isPointInPath method which can use path detection
|
||||||
* or pixel detection
|
* or pixel detection
|
||||||
*/
|
*/
|
||||||
_isPointInPath: function(pos) {
|
_isPointInShape: function(pos) {
|
||||||
var stage = this.getStage();
|
var stage = this.getStage();
|
||||||
var pathLayer = stage.pathLayer;
|
|
||||||
var pathLayerContext = pathLayer.getContext();
|
if(this.detectionType === 'path') {
|
||||||
this._draw(pathLayer);
|
var pathLayer = stage.pathLayer;
|
||||||
return pathLayerContext.isPointInPath(pos.x, pos.y);
|
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
|
// extend Node
|
||||||
|
@ -254,7 +254,7 @@ Kinetic.Stage.prototype = {
|
|||||||
this.targetFound = true;
|
this.targetFound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(shape.visible && pos !== undefined && shape._isPointInPath(pos)) {
|
if(shape.visible && pos !== undefined && shape._isPointInShape(pos)) {
|
||||||
// handle onmousedown
|
// handle onmousedown
|
||||||
if(!isDragging && this.mouseDown) {
|
if(!isDragging && this.mouseDown) {
|
||||||
this.mouseDown = false;
|
this.mouseDown = false;
|
||||||
@ -456,8 +456,8 @@ Kinetic.Stage.prototype = {
|
|||||||
* clear default layers
|
* clear default layers
|
||||||
*/
|
*/
|
||||||
_clearDefaultLayers: function() {
|
_clearDefaultLayers: function() {
|
||||||
var pathLayer = this.pathLayer;
|
this.bufferLayer.clear();
|
||||||
pathLayer.clear();
|
this.pathLayer.clear();
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* begin listening for events by adding event handlers
|
* begin listening for events by adding event handlers
|
||||||
|
@ -519,6 +519,75 @@ Test.prototype.tests = {
|
|||||||
};
|
};
|
||||||
imageObj.src = '../darth-vader.jpg';
|
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) {
|
'EVENTS - drag events click': function(containerId) {
|
||||||
var stage = new Kinetic.Stage({
|
var stage = new Kinetic.Stage({
|
||||||
container: containerId,
|
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