How To Do Mouse Hit Testing On The Edge / Border / Stroked Part Of A Shape
Solution 1:
To detect mouse hits on the edge of a shape only, use the fillEnabled:false property. What this does is tell Konva to disregard fill - meaning that any event-listening on the fill-part of the shape will be switched off. However, with great power great responsibility comes and the fillEnabled property also stops any visual fill you might want to appear.
Putting that together, if you want to hit-test the stroke part of a shape only you will need another transparent shape drawn on top of the visual shape to detect mouse events.
As a bonus, you can use the hitStrokeWidth property to make the hit-detecting region of the stroke wider - as if you set the stroke 'thicker' for purposes of mouse detection.
Snippet below shows this approach on a rect and random polygon.
// Set up a stage
stage = newKonva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
}),
// add a layer to draw on
layer = newKonva.Layer(),
rect = newKonva.Rect({
name: 'r1',
x: 220,
y: 20,
width: 100,
height: 40,
stroke: 'cyan',
fill: 'transparent',
fillEnabled: false
}),
poly = newKonva.Line({
points: [23, 20, 23, 160, 70, 93, 150, 109, 290, 139, 270, 93],
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 5,
closed: true,
fillEnabled: false,
hitStrokeWidth: 10
});
// Add the layer to the stage
stage.add(layer);
layer.add(rect, poly)
stage.draw();
rect.on('mouseover', function() {
$('#info').html('Rect MouseEnter')
})
rect.on('mouseout', function() {
$('#info').html('Rect mouseOut')
})
poly.on('mouseover', function() {
$('#info').html('Poly MouseEnter')
})
poly.on('mouseout', function() {
$('#info').html('Poly mouseOut')
})
body {
margin: 10;
padding: 10;
overflow: hidden;
background-color: #f0f0f0;
}
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><scriptsrc="https://unpkg.com/konva@^3/konva.min.js"></script><p>Move mouse over the shapes </p><pid='info'>Events show here</p><divid="container"></div>
It is easy to clone a shape to make an edge-event detecting version and place the clone over the original shape so that you can detect the edge-events specifically. See the following working snippet - enable the console to view the events sequence.
// Set up a stage
stage = newKonva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
}),
// add a layer to draw on
layer = newKonva.Layer(),
rect = newKonva.Rect({
name: 'r1',
x: 220,
y: 20,
width: 100,
height: 40,
stroke: 'cyan',
fill: 'magenta'
}),
poly = newKonva.Line({
points: [23, 20, 23, 160, 70, 93, 150, 109, 290, 139, 270, 93],
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 5,
closed: true,
hitStrokeWidth: 10
}),
// this is a clone of rect with fillEnabled set to false, placed 'above' rect in the z-order.
rect2 = rect.clone({
fillEnabled: false
}),
poly2 = poly.clone({
fillEnabled: false
}),
// Add the layer to the stage
stage.add(layer);
layer.add(rect, rect2, poly, poly2)
stage.draw();
rect.on('mouseover', function() {
showMsg('Rect MouseEnter');
})
rect2.on('mouseover', function() {
showMsg('Rect2 Edge MouseEnter');
})
rect2.on('mouseout', function() {
showMsg('Rect2 Edge mouseOut');
})
poly.on('mouseover', function() {
showMsg('Poly MouseEnter');
})
poly.on('mouseout', function() {
showMsg('Poly MouseOut');
})
poly2.on('mouseover', function() {
showMsg('Poly2 Edge MouseEnter');
})
poly2.on('mouseout', function() {
showMsg('Poly2 Edge MouseOut');
})
functionshowMsg(msg) {
console.log(msg)
$('#info').html(msg)
}
body {
margin: 10;
padding: 10;
overflow: hidden;
background-color: #f0f0f0;
}
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><scriptsrc="https://unpkg.com/konva@^3/konva.min.js"></script><p>Move mouse over the shapes </p><pid='info'>Events show here</p><divid="container"></div>
Solution 2:
It's not a precise approach ,just a approximate way which detect if the cursor just near the out edge of the object.
stage.on('mousemove', function (e) {
var deta = 3;
var node8 = stage.getIntersection({x: e.evt.clientX, y: e.evt.clientY});
if(node8){
console.log(node8.getClassName()+"====mouse on object=====");
return;
}
var node = stage.getIntersection({x: e.evt.clientX+deta, y: e.evt.clientY});
if(node){
console.log(node.getClassName()+"====mouse on edge=====");
return;
}
var node1 = stage.getIntersection({x: e.evt.clientX, y: e.evt.clientY+deta});
if(node1){
console.log(node1.getClassName()+"====mouse on edge=====");
return;
}
var node2 = stage.getIntersection({x: e.evt.clientX+deta, y: e.evt.clientY+deta});
if(node2){
console.log(node2.getClassName()+"====mouse on edge=====");
return;
}
var node3 = stage.getIntersection({x: e.evt.clientX-deta, y: e.evt.clientY});
if(node3){
console.log(node3.getClassName()+"====mouse on edge=====");
return;
}
var node4 = stage.getIntersection({x: e.evt.clientX, y: e.evt.clientY-deta});
if(node4){
console.log(node4.getClassName()+"====mouse on edge=====");
return;
}
var node5 = stage.getIntersection({x: e.evt.clientX-deta, y: e.evt.clientY-deta});
if(node5){
console.log(node5.getClassName()+"====mouse on edge=====");
return;
}
var node6 = stage.getIntersection({x: e.evt.clientX-deta, y: e.evt.clientY+deta});
if(node6){
console.log(node6.getClassName()+"====mouse on edge=====");
return;
}
var node7 = stage.getIntersection({x: e.evt.clientX+deta, y: e.evt.clientY-deta});
if(node7){
console.log(node7.getClassName()+"====mouse on edge=====");
return;
}
});
Post a Comment for "How To Do Mouse Hit Testing On The Edge / Border / Stroked Part Of A Shape"