如何在形状的边缘/边框/描边部分进行鼠标点击测试
How to do mouse hit testing on the edge / border / stroked part of a shape
在我的应用程序中,我需要检测形状的边缘/边框/描边部分上的鼠标事件 - 但不是填充部分上的鼠标事件。我还没有找到执行此操作的方法。
我不知道如何开始,但这是我正在尝试做的伪代码。
shape.on('mousemove', function () {
if (mouse on the edge of the shape) {
// change the cursor to a star
} else {
// do nothing
}
});
要仅检测鼠标点击形状的边缘,请使用 fillEnabled:false 属性。这样做是告诉 Konva 忽略填充——这意味着形状填充部分的任何事件监听都将被关闭。然而,能力越大,责任越大,fillEnabled 属性 也会停止任何您可能希望出现的视觉填充。
综上所述,如果您只想对形状的笔划部分进行命中测试,则需要在可视形状之上绘制另一个透明形状来检测鼠标事件。
作为奖励,您可以使用 hitStrokeWidth 属性 使笔画的命中检测区域更宽 - 就好像您将笔画 'thicker' 设置为鼠标的目的一样检测.
下面的代码片段显示了在矩形和随机多边形上的这种方法。
// Set up a stage
stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
}),
// add a layer to draw on
layer = new Konva.Layer(),
rect = new Konva.Rect({
name: 'r1',
x: 220,
y: 20,
width: 100,
height: 40,
stroke: 'cyan',
fill: 'transparent',
fillEnabled: false
}),
poly = new Konva.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;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/konva@^3/konva.min.js"></script>
<p>Move mouse over the shapes </p>
<p id='info'>Events show here</p>
<div id="container"></div>
很容易克隆一个形状来制作边缘事件检测版本,并将克隆体放在原始形状上,这样您就可以专门检测边缘事件。请参阅以下工作片段 - 启用控制台以查看事件序列。
// Set up a stage
stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
}),
// add a layer to draw on
layer = new Konva.Layer(),
rect = new Konva.Rect({
name: 'r1',
x: 220,
y: 20,
width: 100,
height: 40,
stroke: 'cyan',
fill: 'magenta'
}),
poly = new Konva.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');
})
function showMsg(msg) {
console.log(msg)
$('#info').html(msg)
}
body {
margin: 10;
padding: 10;
overflow: hidden;
background-color: #f0f0f0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/konva@^3/konva.min.js"></script>
<p>Move mouse over the shapes </p>
<p id='info'>Events show here</p>
<div id="container"></div>
这不是一种精确的方法,只是一种检测光标是否刚好接近对象外边缘的近似方法。
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;
}
});
在我的应用程序中,我需要检测形状的边缘/边框/描边部分上的鼠标事件 - 但不是填充部分上的鼠标事件。我还没有找到执行此操作的方法。
我不知道如何开始,但这是我正在尝试做的伪代码。
shape.on('mousemove', function () {
if (mouse on the edge of the shape) {
// change the cursor to a star
} else {
// do nothing
}
});
要仅检测鼠标点击形状的边缘,请使用 fillEnabled:false 属性。这样做是告诉 Konva 忽略填充——这意味着形状填充部分的任何事件监听都将被关闭。然而,能力越大,责任越大,fillEnabled 属性 也会停止任何您可能希望出现的视觉填充。
综上所述,如果您只想对形状的笔划部分进行命中测试,则需要在可视形状之上绘制另一个透明形状来检测鼠标事件。
作为奖励,您可以使用 hitStrokeWidth 属性 使笔画的命中检测区域更宽 - 就好像您将笔画 'thicker' 设置为鼠标的目的一样检测.
下面的代码片段显示了在矩形和随机多边形上的这种方法。
// Set up a stage
stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
}),
// add a layer to draw on
layer = new Konva.Layer(),
rect = new Konva.Rect({
name: 'r1',
x: 220,
y: 20,
width: 100,
height: 40,
stroke: 'cyan',
fill: 'transparent',
fillEnabled: false
}),
poly = new Konva.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;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/konva@^3/konva.min.js"></script>
<p>Move mouse over the shapes </p>
<p id='info'>Events show here</p>
<div id="container"></div>
很容易克隆一个形状来制作边缘事件检测版本,并将克隆体放在原始形状上,这样您就可以专门检测边缘事件。请参阅以下工作片段 - 启用控制台以查看事件序列。
// Set up a stage
stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
}),
// add a layer to draw on
layer = new Konva.Layer(),
rect = new Konva.Rect({
name: 'r1',
x: 220,
y: 20,
width: 100,
height: 40,
stroke: 'cyan',
fill: 'magenta'
}),
poly = new Konva.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');
})
function showMsg(msg) {
console.log(msg)
$('#info').html(msg)
}
body {
margin: 10;
padding: 10;
overflow: hidden;
background-color: #f0f0f0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/konva@^3/konva.min.js"></script>
<p>Move mouse over the shapes </p>
<p id='info'>Events show here</p>
<div id="container"></div>
这不是一种精确的方法,只是一种检测光标是否刚好接近对象外边缘的近似方法。
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;
}
});