2 回答
TA贡献1911条经验 获得超7个赞
有很多方法可以做到这一点。基本思路:
mousedown
在源对象上创建一条线mousemove
更新事件的行位置在 上检查目标形状
mouseup
。如果那是“可连接”的东西,请保留一条线,否则将其摧毁。
const stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
});
const layer = new Konva.Layer();
stage.add(layer);
layer.add(new Konva.Text({ text: 'try to drag a green source into any red target', padding: 10}))
const source = new Konva.Circle({
x: 20,
y: 50,
radius: 10,
fill: 'green'
});
layer.add(source);
const target1 = new Konva.Circle({
x: 20,
y: 220,
radius: 10,
fill: 'red',
name: 'target'
});
layer.add(target1);
const target2 = new Konva.Circle({
x: 120,
y: 220,
radius: 10,
fill: 'red',
name: 'target'
});
layer.add(target2);
let drawingLine = false;
let line;
source.on('mousedown', () => {
drawingLine = true;
const pos = stage.getPointerPosition();
line = new Konva.Line({
stroke: 'black',
// remove line from hit graph, so we can check intersections
listening: false,
points: [source.x(), source.y(), pos.x, pos.y]
});
layer.add(line);
});
stage.on('mouseover', (e) => {
if (e.target.hasName('target')) {
e.target.stroke('black');
layer.draw();
}
});
stage.on('mouseout', (e) => {
if (e.target.hasName('target')) {
e.target.stroke(null);
layer.draw();
}
});
stage.on('mousemove', (e) => {
if (!line) {
return;
}
const pos = stage.getPointerPosition();
const points = line.points().slice();
points[2] = pos.x;
points[3] = pos.y;
line.points(points);
layer.batchDraw();
});
stage.on('mouseup', (e) => {
if (!line) {
return;
}
if (!e.target.hasName('target')) {
line.destroy();
layer.draw();
line = null;
} else {
line = null;
}
});
layer.draw();
https://jsbin.com/rumizocise/1/edit?html,js,output
TA贡献1784条经验 获得超8个赞
看来您真正的问题是如何在鼠标移动或鼠标抬起操作期间检查鼠标下方是否有形状。
Konva 有一种命中检测方法,我会让@lavarton 解释一下。如果您处理的是纯矩形 - 而不是例如圆形 - 您可以使用形状位置进行自己的命中测试并运行一些简单的数学检查。请参阅我对这个问题的解决方案“通过在 konva 中的对象周围绘制一个框来选择”,它涵盖了相同的命中测试基础,应该会向您展示一个简单的前进方向。
关于“纯矩形”的要点涉及这样一个事实,即这种方法很容易用于非旋转的矩形形状。但是,旋转的矩形或非矩形形状需要更多工作,如果这是您的用例,那么 Konva 的内置命中测试将为您的代码学习和未来支持提供更低的时间成本。
关于@lavrton 的回答缺少将线放置在连接形状的中心位置的要求,请更改代码中的 stage.on('mouseup') 侦听器,如下所示。
stage.on('mouseup', (e) => {
if (!line) {
return;
}
if (!e.target.hasName('target')) {
line.destroy();
layer.draw();
line = null;
} else {
let pos = e.target.getClientRect();
const points = line.points().slice();
points[2] = pos.x + (e.target.width()/2);
points[3] = pos.y + (e.target.height()/2);;
line.points(points);
layer.batchDraw();
line = null;
}
});
这是通过获取目标形状的左上角(getClientRect 值),然后将形状宽度的一半添加到 x 并将形状高度的一半添加到 y 值以给出中心点。然后我们获取当前线点数组,设置插槽 2 和 3 中的值,即 end.x 和 end.y,将其返回给线并重绘图层。
@lavrton 应该修改他的例子如上并获得正确答案。
添加回答
举报