簡體   English   中英

KonvaJS:如何根據鼠標移動畫一條線來連接兩個形狀?

[英]KonvaJS : How to draw a line to connect two shape based on mouse move?

我正在嘗試根據鼠標移動畫一條線來連接兩個形狀。 我知道如何使用原生 canvas 來實現它。 但是不知道如何通過使用 KonvaJS 來實現它。 請幫助我。

此圖像顯示什么結果:在此處輸入圖像描述

這是我試圖實現我想要的代碼。 但它不起作用。

            stage.on('mousedown', function(e) {
                const a = e.target instanceof Konva.Rect;
                if (!a) {
                    return;
                } else {
                    
                    group.draggable(false);
                    group2.draggable(false);
                    
                    clickdot1 = e.target;
                    drawingLine = true;
                    }
            });

            stage.on('mousemove', function(e) {
                if (!drawingLine) {
                    return;
                }else{
                    if(clickdot1!=null&&drawingLine){
                        let lastLine = new Konva.Line({
                            stroke: '#df4b26',
                            strokeWidth: 5,
                            lineCap: 'round',
                            lineJoin: 'round',
                            points: [e.target.x(), e.target.y()],
                        });
                        connections.push(lastLine);
                        drawthings();
                    }
                }   
            });
            
            function drawthings(){
                for(let i = 0;i<connections.length;i++){
                    animLayer.add(connections[i]);
                    animLayer.batchDraw();
                }
            }

有很多方法可以做到這一點。 基本思想:

  1. 在源代碼 object 上的mousedown上創建一行
  2. mousemove事件上更新行 position
  3. 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

看來您真正的問題是如何在鼠標移動或鼠標向上操作期間檢查鼠標下方是否有形狀。

Konva 有一個命中檢測方法,我會讓@lavarton 解釋。 如果您正在處理純矩形 - 而不是例如圓形 - 您可以使用形狀 position 進行自己的命中測試並運行一些簡單的數學檢查。 請參閱我對這個問題的解決方案,即“通過在 konva 中的對象周圍繪制一個框來選擇” ,它涵蓋了命中測試的相同基礎,並且應該向您展示一個簡單的前進方式。

關於“純矩形”的觀點涉及這樣一個事實,即這種方法很容易適用於非旋轉的矩形形狀。 但是,旋轉的矩形或非矩形形狀需要更多的工作,如果這是您的用例,那么 Konva 的內置命中測試將為您的代碼的學習和未來支持提供更低的時間成本。

關於@lavrton 的回答缺少將線放置在連接形狀上的中心 position 的要求,請在他的代碼中更改 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 應該如上修改他的示例並獲得正確答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM