2

Currently I have this sample which creates four points , then connects it.

Basically what I want is to drag the whole connection of the lines(area) when you click on a line but when you selects the circle it should be extended(already implemented)

for(var i=0;i<connectors.length;i++){
    var c=connectors[i];
    var s=anchors[c.start];
    var e=anchors[c.end];
    ctx.beginPath();
    ctx.moveTo(s.x,s.y);
    ctx.lineTo(e.x,e.y);
    ctx.stroke();
}   

// draw circles
for(var i=0;i<anchors.length;i++){
    ctx.beginPath();
    ctx.arc(anchors[i].x,anchors[i].y,radius,0,Math.PI*2);
    ctx.fill(); 
    ctx.fillText(anchors[i].label,anchors[i].x-5,anchors[i].y-15); 
}`
  • Can you explain to us how exactly you want to drag the whole connection? Where should we click or do in order to move the whole thing ? – Marcio Sep 08 '15 at 07:46
  • Once you click inside the are of connected lines, it should be drag as a whole. –  Sep 08 '15 at 07:51
  • 1
    Do you mean something like [this](https://jsfiddle.net/3gejn8j4/4/) ? – Jordumus Sep 08 '15 at 08:19
  • @Jordumus no. What I want is to drag the connected lines with 4 circle(A,B,C,D) as whole when you long click inside the area. –  Sep 08 '15 at 08:25
  • So you want - 1: a function to detect if the mouse is **inside** 4 defined points. 2: when mousedown on a location like that, the possibility to 'drag' the 4 points. Correct? – Jordumus Sep 08 '15 at 09:07
  • You are aware that your 4 points don't form a convex poly, right? Is this on purpose? – Jordumus Sep 08 '15 at 09:25
  • It is on purpose. One thing I want to correct is that it can only be drag when clicking on the lines not inside the lines. –  Sep 08 '15 at 09:27
  • 1
    Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/89047/discussion-between-jordumus-and-jt-25). – Jordumus Sep 08 '15 at 09:33

1 Answers1

0

You got 2 important steps you have to tackle for this problem:

1 - Detect if the mouse is on a line when holding down LMB.

2 - Move all dots connected to the line in question when moving mouse.

Detect if a point is on a line

Theory: Mathematically you can detect if a point is on a (enclosed) line if the distance between said point to the 2 ends of the line is EQUAL to the distance between the 2 ends of the line.

More information: here

I wrote a little function to check this:

function mouseOnLine(mousePos) {

    for (var i = 0 ; i < connectors.length; i++){
        var pA = anchors[connectors[i].start];
        var pB = anchors[connectors[i].end];

        var first = distanceBetween(pA,mousePos) + distanceBetween(pB,mousePos);
        var second = distanceBetween(pA,pB);
        if (Math.abs(first - second) < 0.3) //Threshold of 0.3
            return connectors[i];

    }

    return null;
}

Important to note: I don't check if it's equal to 0, but rather if the difference is smaller than 0.3, so the mouse doesn't have to be exactly on the line, as that would be quite hard to achieve.

Distance between is a simple pythagoras calculation:

var distanceBetween = function (point1, point2) {

    var distX = Math.abs( point1.x - point2.x);
    var distY = Math.abs(point1.y - point2.y);
    return Math.sqrt((distX * distX) + (distY * distY));
}

Move all points connected to this one

Theory: As soon as we detected that the mousebutton is held down on top of a line, we have to find the first point of that form. We know that each polygon contains 4 points, so we can just loop over the next 4 points.

We can find the first point of the polygon (assuming they're always in order), with a little calculation:

var startPoints = Math.floor(fullDrag.start / 4) * 4;
//Example: We clicked on the line starting with point 3. this will return:
//Math.floor(3 / 4) * 4  ==> Math.floor(0.75) * 4 ==> 0 * 4 ==> 0

Now just loop and move it all:

var startPoints = Math.floor(fullDrag.start / 4) * 4;
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);

for (var i = 0; i < 4; i++) {
    anchors[startPoints+i].x +=(mouseX-startX);
    anchors[startPoints+i].y +=(mouseY-startY);
}

startX=mouseX;
startY=mouseY; 

Other people reading this: The code shown above are only snippets from the entire solution. You can find a working fiddle right here

Community
  • 1
  • 1
Jordumus
  • 2,763
  • 2
  • 21
  • 38