2015-09-01 5 views
5

Ziel: Verschieben Sie das rote Rechteck innerhalb der Gruppe der schwarzen Rechtecke. Schwarze Rechtecke bilden eine Figur, die darauf beschränkt ist, das rote Rechteck zu verschieben.Beschränken Sie die Bewegung des Elements, wenn wir es ziehen

window.onload=function(){ 

var inter = false; 

//Make an SVG Container 
var svgContainer = d3.select("body").append("svg") 
    .attr("width", 800) 
    .attr("height", 600); 

//draw some rects 
var r1 = svgContainer.append("rect") 
    .attr("class", "interactive") 
    .attr("x", 10) 
    .attr("y", 223) 
    .attr("width", 50) 
    .attr("height", 150); 

var r2 = svgContainer.append("rect") 
    .attr("class", "interactive") 
    .attr("x", 223) 
    .attr("y", 10) 
    .attr("width", 50) 
    .attr("height", 300) 
    .attr("transform", "rotate(45 220,10)"); 

//group of elements for limit red rect drag 
var interactive = d3.selectAll(".interactive") 
    .on("mouseover", function(d){ 
     inter = true; 
    }) 
    .on("mouseleave", function(d){ 
     inter = false; 
    }); 

// dragging function 
var drag = d3.behavior.drag() 
    .on("drag", function(d,i) { 
     if(inter){ 
      d.x += d3.event.dx; 
      d.y += d3.event.dy; 
      d3.select(this).attr("transform", function(d,i){ 
       return "translate(" + [ d.x,d.y ] + ")" 
      }); 
     } 
    }) 
    .on("dragstart", function() { 
     d3.select(this).style("pointer-events", "none") 
    }) 
    .on("dragend", function() { 
     d3.select(this).style("pointer-events", "auto") 
    }); 

// red rectangle for draging 
var r = svgContainer.append("rect") 
    .attr("x", 150) 
    .attr("y", 100) 
    .attr("width", 20) 
    .attr("height", 20) 
    .attr("fill", "red") 
    .data([ {"x":0, "y":0} ]) 
    .call(drag); 

} 

http://codepen.io/anon/pen/pjorBb

Hier ist mein Beispiel für ein Thema. Aber es funktioniert nicht richtig. Vielleicht hat jemand ein ähnliches Beispiel für eine korrekte oder geben Sie einen Hinweis, wie es richtig geht.

Antwort

1

Dies ist keine perfekte Lösung. Aber Sie können die Idee, wie Sie die Funktionalität von dieser Demo implementieren.

//Make an SVG Container 
 
var svgContainer = d3.select("body").append("svg") 
 
\t .attr("width", 800) 
 
\t .attr("height", 600); 
 

 
//draw some rects 
 
var r1 = svgContainer.append("rect") 
 
\t .attr("class", "interactive") 
 
\t .attr("x", 10) 
 
\t .attr("y", 223) 
 
\t .attr("width", 50) 
 
\t .attr("height", 150); 
 

 
var r2 = svgContainer.append("rect") 
 
\t .attr("class", "interactive") 
 
\t .attr("x",223) 
 
\t .attr("y", 10) 
 
\t .attr("width", 50) 
 
\t .attr("height", 300) 
 
\t .attr("transform", "rotate(45 220,10)"); 
 

 
function pointRectangleIntersection(p, r) { 
 
    return p.x >= r.x1 && p.x <= r.x2 && p.y >= r.y1 && p.y <= r.y2; 
 
} 
 
// dragging function 
 
var drag = d3.behavior.drag()   
 
\t .on("drag", function(d,i) {   
 
      var pt1 = d3.mouse(r1.node()); 
 
      var point1 = {x: pt1[0], y: pt1[1]}; 
 
      var bbox1 = r1.node().getBBox(); 
 
      var rect1 = { x1: bbox1.x, x2: bbox1.x+bbox1.width, y1: bbox1.y, y2: bbox1.y+bbox1.height }; 
 
      var pt2 = d3.mouse(r2.node()); 
 
      var point2 = {x: pt2[0], y: pt2[1]}; 
 
      var bbox2 = r2.node().getBBox(); 
 
      var rect2 = { x1: bbox2.x, x2: bbox2.x+bbox2.width, y1: bbox2.y, y2: bbox2.y+bbox2.height }; 
 
      
 
      if(pointRectangleIntersection(point1, rect1) || pointRectangleIntersection(point2, rect2)){ 
 
       if(pointRectangleIntersection(point1, rect1)){ 
 
        d.x = Math.max(0, Math.min(rect1.x2 - 20, d3.event.x)); 
 
        d.y = Math.max(0, Math.min(rect1.y2 - 20, d3.event.y)); 
 
       } else{ 
 
        d.x = Math.max(0, Math.min(rect2.x2 - 20, d3.event.x)); 
 
        d.y = Math.max(0, Math.min(rect2.y2 - 20, d3.event.y)); 
 
       }    
 
       d3.select(this).attr("x", d.x); 
 
       d3.select(this).attr("y", d.y); 
 
       d3.event.sourceEvent.stopPropagation();    
 
      } 
 
\t \t 
 
\t }); \t 
 
\t 
 
// red rectangle for draging 
 
var r = svgContainer.append("rect") 
 
\t .attr("x", 150) 
 
\t .attr("y", 100) 
 
\t .attr("width", 20) 
 
\t .attr("height", 20) 
 
\t .attr("fill", "red") 
 
\t .datum({"x":0, "y":0}) 
 
\t .call(drag);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

+0

Dies ist eine gute Wahl! Aber es funktioniert nicht korrekt mit einem Objekt, das sich dreht. –

1

Ich habe eine ähnliche Situation in der Vergangenheit, So habe ich das Problem überwunden.

Wenn ich das kleine Element ziehe, benutze ich eine Funktion, um das x, y des Elements zu bestimmen, das gezogen wird.

werden die Mauskoordinaten (d3.mouse(this)) und x, y , width, height der inneren & äußeren Objekte nehmen. Dann wird es herausfinden, ob die Mauskoordinaten zurückgegeben werden sollen oder nicht (in diesem Fall Grenzkoordinaten des äußeren Objekts).

Ich hoffe, Sie werden die Idee bekommen. Ich denke, du kannst es benutzen, um dein Problem zu lösen.

Dies ist mein ursprünglicher Beitrag. d3js transforming nested group images

0

Zum Beispiel. Ich änderte die Aufgabe für meine eigenen Bedürfnisse. Und schrieb eine Entscheidung, die für jemanden nützlich sein könnte. Weiter ist der Code, in dem ein Rechteck nur entlang der Linie bewegt werden kann. Die Linien können mit einer transparenten Farbe (.attr ("fill", "rgba (0, 0, 0, 0)")) versteckt werden und Sie können alles andere für den Benutzer zeichnen.

http://codepen.io/anon/pen/pjoGOr

var deltaMax = 15; // max distance to line 
var svgx = 0; 
var svgy = 0; 
var limiters = []; //array of lines for align 

var svgContainer = d3.select("body").append("svg") 
    .attr("width", 700) 
    .attr("height", 700); 

var line1 = svgContainer.append("line") 
    .style("stroke", "black") 
    .attr("x1", 100) 
    .attr("y1", 50) 
    .attr("x2", 100) 
    .attr("y2", 200); 

var line2 = svgContainer.append("line") 
    .style("stroke", "blue") 
    .attr("x1", 100) 
    .attr("y1", 50) 
    .attr("x2", 300) 
    .attr("y2", 50); 

var line3 = svgContainer.append("line") 
    .style("stroke", "green") 
    .attr("x1", 100) 
    .attr("y1", 50) 
    .attr("x2", 300) 
    .attr("y2", 200); 

limiters.push(line1); 
limiters.push(line2); 
limiters.push(line3); 

function distance2points(x1,y1,x2,y2){ //distance between 2 points 
    return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); 
} 

//find nearest intersection point 
function stick(x1,y1,x2,y2,x3,y3) { 

    //intersection point 
    var ipoint = { x:0, y:0 }; 
    var onSegment = false; 

    if((x2 - x1) == 0){ 
     ipoint.x = x1; 
     ipoint.y = y3; 
    }else if((y2-y1) == 0){ 
     ipoint.x = x3; 
     ipoint.y = y1; 
    }else{ 
     var k = (y2-y1)/(x2-x1); 
     var b = y2-k*x2; 

     var kp = -1/k; 
     var bp = y3-kp*x3; 

     ipoint.x = (bp-b)/(k-kp); 
     ipoint.y = ipoint.x*k+b; 

    } 
    //xxx helper 
    point.attr("cx",ipoint.x); 
    point.attr("cy",ipoint.y); 

    if(distance2points(x3,y3,ipoint.x,ipoint.y) > deltaMax){ 
     return false; 
    } 
    //intersectionn point on segment? 
    if(((x1 >= ipoint.x) && (x2 <= ipoint.x) || (x1 <= ipoint.x) && (x2 >= ipoint.x)) && 
     ((y1 >= ipoint.y) && (y2 <= ipoint.y) || (y1 <= ipoint.y) && (y2 >= ipoint.y))){ 
     onSegment = true; 
    }else if(distance2points(x1,y1,ipoint.x,ipoint.y) < deltaMax){ 
     ipoint.x = x1; 
     ipoint.y = y1; 
     onSegment = true; 
    }else if(distance2points(x2,y2,ipoint.x,ipoint.y) < deltaMax){ 
     ipoint.x = x2; 
     ipoint.y = y2; 
     onSegment = true; 
    }else{ 
     onSegment = false; 
    } 

    if(onSegment){ 
     point.attr("fill","blue"); 
     return ipoint; 
    }else{ 
     point.attr("fill","red"); 
     return false; 
    } 
} 

//mouse position 
svgContainer.on('mousemove', function() { 
    svgx = d3.mouse(this)[0]; 
    svgy = d3.mouse(this)[1]; 
}); 

// dragging function 
var drag = d3.behavior.drag() 
    .on("drag", function(d,i) { 
     for (i = 0; i < limiters.length; i++) { 
      var obj = limiters[i]; 
      var p = stick(
       obj.attr("x1"), 
       obj.attr("y1"), 
       obj.attr("x2"), 
       obj.attr("y2"), 
       svgx,//mouse position 
       svgy 
      ); 
      if(p !== false){ 
       d3.select(this).attr("transform", function(d,i){ 
        return "translate(" + [ p.x,p.y ] + ")" 
       }); 
       break; 
      } 
     } 

    }); 

var r = svgContainer.append("rect") 
    .attr("x", 0) 
    .attr("y", 0) 
    .attr("width", 20) 
    .attr("height", 20) 
    .attr("fill", "red") 
    .data([ {"x":0, "y":0} ]) 
    .call(drag); 

//xxx helper - nearest intersection point 
var point = svgContainer.append("circle") 
    .attr("cx", 10) 
    .attr("cy", 30) 
    .attr("r", 5) 
    .attr("fill", "green"); 
Verwandte Themen