KonvaJS:如何根据鼠标移动画一条线来连接两个形状?

我正在尝试根据鼠标移动画一条线来连接两个形状。我知道如何使用原生画布重新利用它。但是不知道如何使用 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();

                }

            }


猛跑小猪
浏览 386回答 2
2回答

Smart猫小萌

有很多方法可以做到这一点。基本思路:mousedown在源对象上创建一条线mousemove更新事件的行位置在 上检查目标形状mouseup。如果那是“可连接”的东西,请保留一条线,否则将其摧毁。const stage = new Konva.Stage({&nbsp; container: 'container',&nbsp; width: window.innerWidth,&nbsp; 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({&nbsp; x: 20,&nbsp; y: 50,&nbsp; radius: 10,&nbsp; fill: 'green'});layer.add(source);const target1 = new Konva.Circle({&nbsp; x: 20,&nbsp; y: 220,&nbsp; radius: 10,&nbsp; fill: 'red',&nbsp; name: 'target'});layer.add(target1);const target2 = new Konva.Circle({&nbsp; x: 120,&nbsp; y: 220,&nbsp; radius: 10,&nbsp; fill: 'red',&nbsp; name: 'target'});layer.add(target2);let drawingLine = false;let line;source.on('mousedown', () => {&nbsp; drawingLine = true;&nbsp; const pos = stage.getPointerPosition();&nbsp; line = new Konva.Line({&nbsp; &nbsp; stroke: 'black',&nbsp; &nbsp; // remove line from hit graph, so we can check intersections&nbsp; &nbsp; listening: false,&nbsp; &nbsp; points: [source.x(), source.y(), pos.x, pos.y]&nbsp; });&nbsp; layer.add(line);});stage.on('mouseover', (e) => {&nbsp; if (e.target.hasName('target')) {&nbsp; &nbsp; e.target.stroke('black');&nbsp; &nbsp; layer.draw();&nbsp; }});stage.on('mouseout', (e) => {&nbsp; if (e.target.hasName('target')) {&nbsp; &nbsp; e.target.stroke(null);&nbsp; &nbsp; layer.draw();&nbsp; }});stage.on('mousemove', (e) => {&nbsp; if (!line) {&nbsp; &nbsp; return;&nbsp; }&nbsp; const pos = stage.getPointerPosition();&nbsp; const points = line.points().slice();&nbsp; points[2] = pos.x;&nbsp; points[3] = pos.y;&nbsp; line.points(points);&nbsp; layer.batchDraw();});stage.on('mouseup', (e) => {&nbsp; if (!line) {&nbsp; &nbsp; return;&nbsp; }&nbsp; if (!e.target.hasName('target')) {&nbsp; &nbsp; line.destroy();&nbsp; &nbsp; layer.draw();&nbsp; &nbsp; line = null;&nbsp; } else {&nbsp; &nbsp; line = null;&nbsp; }&nbsp;&nbsp;});layer.draw();https://jsbin.com/rumizocise/1/edit?html,js,output

青春有我

看来您真正的问题是如何在鼠标移动或鼠标抬起操作期间检查鼠标下方是否有形状。Konva 有一种命中检测方法,我会让@lavarton 解释一下。如果您处理的是纯矩形 - 而不是例如圆形 - 您可以使用形状位置进行自己的命中测试并运行一些简单的数学检查。请参阅我对这个问题的解决方案“通过在 konva 中的对象周围绘制一个框来选择”,它涵盖了相同的命中测试基础,应该会向您展示一个简单的前进方向。关于“纯矩形”的要点涉及这样一个事实,即这种方法很容易用于非旋转的矩形形状。但是,旋转的矩形或非矩形形状需要更多工作,如果这是您的用例,那么 Konva 的内置命中测试将为您的代码学习和未来支持提供更低的时间成本。关于@lavrton 的回答缺少将线放置在连接形状的中心位置的要求,请更改代码中的 stage.on('mouseup') 侦听器,如下所示。stage.on('mouseup', (e) => {&nbsp; if (!line) {&nbsp; &nbsp; return;&nbsp; }&nbsp;&nbsp;&nbsp; if (!e.target.hasName('target')) {&nbsp; &nbsp; line.destroy();&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; layer.draw();&nbsp; &nbsp; line = null;&nbsp; } else {&nbsp; &nbsp; let pos = e.target.getClientRect();&nbsp; &nbsp; const points = line.points().slice();&nbsp; &nbsp; points[2] = pos.x + (e.target.width()/2);&nbsp; &nbsp; points[3] = pos.y + (e.target.height()/2);;&nbsp; &nbsp; line.points(points);&nbsp; &nbsp; layer.batchDraw();&nbsp; &nbsp;&nbsp; &nbsp; line = null;&nbsp; }&nbsp;&nbsp;});这是通过获取目标形状的左上角(getClientRect 值),然后将形状宽度的一半添加到 x 并将形状高度的一半添加到 y 值以给出中心点。然后我们获取当前线点数组,设置插槽 2 和 3 中的值,即 end.x 和 end.y,将其返回给线并重绘图层。@lavrton 应该修改他的例子如上并获得正确答案。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript