在2个元素之间绘制线 [英] Drawing lines between 2 elements onclick

查看:222
本文介绍了在2个元素之间绘制线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有办法(我猜它的总是)在2个元素之间画一条线吗?一个div和一个img标签具有不同的id。 Heres是一些HTML

is there a way (i guess its always) to draw a line between 2 elements? A div and an img tags wwith different ids. Heres is some html

<div id="textHolder">
                      <div class="text" id="text0"><p>masă</p></div>
</div>
<div id="objectHolder">
                          <img class="obiecte" id="obj0" src="images/Macara.svg">
</div> 

好吧,所以我需要在div之间绘制一行div的另一个div与id =textHolder 和一个div里面的图像,id =objectHolder。首先点击textHolder里的div,然后在用户点击objectHolder里面的图像时绘制它们之间的线。

Ok,so i need to draw a line between the div inside of another div with id="textHolder" and an image inside a div with id="objectHolder".First clicking on the div inside of textHolder then drawing the line between them when user click on the image inside of objectHolder.

我知道我必须添加一些代码,但我没有找到任何好的显示。

I know i must add some code but i didnt found anything good to show.

这里是一个小提琴: http://jsfiddle.net/4DURB/

推荐答案

我在这一点上做了一点工作,因为它刺激了我的兴趣。有一个jsbin(首选由于控制台jsfiddle)在这里 http://jsbin.com/guken/3/

I've done a little bit of work on this one, because it piqued my interest. There is a jsbin (preferred to jsfiddle just because of the console) here http://jsbin.com/guken/3/

方法是创建一个浮动canvas元素(阴影粉红色),并放置在DOM的其余部分(使用z-index)下面。然后,我计算与盒中心之间的线对应的两个框的边界上的点。红色和蓝色正方形实际上是与行末端一起移动的div,可以用于源,目标等注释。

The method is to create a floating canvas element (shaded pink), and lay that underneath the rest of the DOM (using z-index). I then calculate the points on the borders of the two boxes that correspond with a line between the box centres. The red and blue squares are actually divs that move with the line ends, which could be used for annotation like source, target etc.

在jsbin中,您可以点击一个元素,然后得到一个行准备点击下一个。

In that jsbin, you can click on one element, and then get a line ready to click on the next. It detects hover for the chosen elements and snaps to a target if you hover over one.

我不会在这里粘贴所有的代码,但是我们绘制的位在客户机DOM坐标中从一个x,y位置到另一个位置的行是:

I won't paste all the code here, but the bit where we draw a line from one x,y position to another in client DOM coordinates is this:

var lineElem;
function drawLineXY(fromXY, toXY) {
    if(!lineElem) {
        lineElem = document.createElement('canvas');
        lineElem.style.position = "absolute";
        lineElem.style.zIndex = -100;
        document.body.appendChild(lineElem);
    }
    var leftpoint, rightpoint;
    if(fromXY.x < toXY.x) {
      leftpoint = fromXY;
      rightpoint = toXY;
    } else {
      leftpoint = toXY;
      rightpoint = fromXY;
    }

    var lineWidthPix = 4;
    var gutterPix = 10;
    var origin = {x:leftpoint.x-gutterPix, 
                  y:Math.min(fromXY.y, toXY.y)-gutterPix};
    lineElem.width = Math.max(rightpoint.x - leftpoint.x, lineWidthPix) + 
      2.0*gutterPix;
    lineElem.height = Math.abs(fromXY.y - toXY.y) + 2.0*gutterPix;
    lineElem.style.left = origin.x;
    lineElem.style.top = origin.y;
    var ctx = lineElem.getContext('2d');
    // Use the identity matrix while clearing the canvas
    ctx.save();
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.clearRect(0, 0, lineElem.width, lineElem.height);
    ctx.restore();
    ctx.lineWidth = 4;
    ctx.strokeStyle = '#09f';
    ctx.beginPath();
    ctx.moveTo(fromXY.x - origin.x, fromXY.y - origin.y);
    ctx.lineTo(toXY.x - origin.x, toXY.y - origin.y);
    ctx.stroke();
}

由于示例只是一行,已经完成准备好创建更多,它使用一个全局变量 lineElem 。第一次尝试绘制线时,它创建一个canvas元素,将其插入DOM并将其分配给lineElem。在这个构造之后,它随后重新使用canvas元素,改变大小并重新绘制新的坐标对。

As the example is just one line, and we can always store lines that have been 'finished' ready to create more, it uses a global variable lineElem. On the first attempt to draw a line, it creates a canvas element, inserts it into the DOM and assigns it to lineElem. After this construction, it subsequently reuses the canvas element, changing the size and redrawing for new coordinate pairs.

为了防止线被画布的边缘切掉,有一个填充画布宽度和高度的填充设置。其余的只是在客户端DOM坐标和在画布上绘制的坐标之间进行坐标平移。

To prevent the line being cut off by the edge of the canvas, there is a gutter setting which pads the canvas width and height. The rest is just getting the coordinate translation right between client DOM coordinates and the coordinates for drawing on the canvas itself.

唯一的另一个不直接的位是计算点的坐标在一个盒子的边界沿线。这不是完美的,但这是一个合理的开始。关键是从源()的角度计算目标()的角度,并且看到如何与盒角的已知角度比较:

The only other unstraightforward bit is calculating the coordinates of a point on the border of a box along a line. It's not perfect, but it's a reasonable start. The crux is to calculate the angle of the target (to) point from the perspective of the source (from) point, and see how that compares to the known angles of the box corners:

function getNearestPointOutside(from, to, boxSize) {
    // which side does it hit? 
    // get the angle of to from from.
    var theta = Math.atan2(boxSize.y, boxSize.x);
    var phi = Math.atan2(to.y - from.y, to.x - from.x);
    var nearestPoint = {};
    if(Math.abs(phi) < theta) { // crosses +x
        nearestPoint.x = from.x + boxSize.x/2.0;
        nearestPoint.y = from.y + ((to.x === from.x) ? from.y : 
        ((to.y - from.y)/(to.x - from.x) * boxSize.x/2.0));
    } else if(Math.PI-Math.abs(phi) < theta) { // crosses -x
        nearestPoint.x = from.x - boxSize.x/2.0;
        nearestPoint.y = from.y + ((to.x === from.x) ? from.y : 
        (-(to.y - from.y)/(to.x - from.x) * boxSize.x/2.0));
    } else if(to.y > from.y) { // crosses +y
        nearestPoint.y = from.y + boxSize.y/2.0;
        nearestPoint.x = from.x + ((to.y === from.y) ? 0 : 
        ((to.x - from.x)/(to.y - from.y) * boxSize.y/2.0));
    } else { // crosses -y
        nearestPoint.y = from.y - boxSize.y/2.0;
        nearestPoint.x = from.x - ((to.y === from.y) ? 0 :
        ((to.x - from.x)/(to.y - from.y) * boxSize.y/2.0));
    }
    return nearestPoint;
}

Theta是第一个方块角的角度,phi是实际线角度。

Theta is the angle to the first box corner, and phi is the actual line angle.

要获取客户端坐标中框的位置,您需要使用 elem.getBoundingClientRect()生成左,上,宽,高等,我使用找到一个框的中心:

To get the positions of the boxes in client coordinates, you need to use elem.getBoundingClientRect(), which yields left, top, width, height among other things, and I use to find the centre of a box:

function getCentreOfElement(el) {
    var bounds = el.getBoundingClientRect();
    return {x:bounds.left + bounds.width/2.0,
            y:bounds.top + bounds.height/2.0};
}

将所有这些组合在一起,可以从一个元素到另一个元素绘制一条线。

Putting all that together, you can draw a line from one element to another.

这篇关于在2个元素之间绘制线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆