2 回答

TA貢獻(xiàn)1911條經(jīng)驗(yàn) 獲得超7個(gè)贊
有很多方法可以做到這一點(diǎn)?;舅悸罚?/p>
mousedown
在源對(duì)象上創(chuàng)建一條線mousemove
更新事件的行位置在 上檢查目標(biāo)形狀
mouseup
。如果那是“可連接”的東西,請(qǐng)保留一條線,否則將其摧毀。
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貢獻(xiàn)1784條經(jīng)驗(yàn) 獲得超8個(gè)贊
看來您真正的問題是如何在鼠標(biāo)移動(dòng)或鼠標(biāo)抬起操作期間檢查鼠標(biāo)下方是否有形狀。
Konva 有一種命中檢測(cè)方法,我會(huì)讓@lavarton 解釋一下。如果您處理的是純矩形 - 而不是例如圓形 - 您可以使用形狀位置進(jìn)行自己的命中測(cè)試并運(yùn)行一些簡(jiǎn)單的數(shù)學(xué)檢查。請(qǐng)參閱我對(duì)這個(gè)問題的解決方案“通過在 konva 中的對(duì)象周圍繪制一個(gè)框來選擇”,它涵蓋了相同的命中測(cè)試基礎(chǔ),應(yīng)該會(huì)向您展示一個(gè)簡(jiǎn)單的前進(jìn)方向。
關(guān)于“純矩形”的要點(diǎn)涉及這樣一個(gè)事實(shí),即這種方法很容易用于非旋轉(zhuǎn)的矩形形狀。但是,旋轉(zhuǎn)的矩形或非矩形形狀需要更多工作,如果這是您的用例,那么 Konva 的內(nèi)置命中測(cè)試將為您的代碼學(xué)習(xí)和未來支持提供更低的時(shí)間成本。
關(guān)于@lavrton 的回答缺少將線放置在連接形狀的中心位置的要求,請(qǐng)更改代碼中的 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;
}
});
這是通過獲取目標(biāo)形狀的左上角(getClientRect 值),然后將形狀寬度的一半添加到 x 并將形狀高度的一半添加到 y 值以給出中心點(diǎn)。然后我們獲取當(dāng)前線點(diǎn)數(shù)組,設(shè)置插槽 2 和 3 中的值,即 end.x 和 end.y,將其返回給線并重繪圖層。
@lavrton 應(yīng)該修改他的例子如上并獲得正確答案。
添加回答
舉報(bào)