简体   繁体   English

可调整大小和可旋转的矩形D3?

[英]Resizable and Rotatable Rectangle D3?

I am trying to create a rectangle where I can resize and rotate it using handlers (small circles) located on the top of the rectangle. 我正在尝试创建一个矩形,我可以使用位于矩形顶部的处理程序(小圆圈)调整大小并旋转它。 Similar to the most of the drawing tools that allow us to resize and rotate the shapes. 与大多数允许我们调整大小和旋转形状的绘图工具类似。

I added three circles on the top of my rectangle. 我在矩形的顶部添加了三个圆圈。 One circle is for resizing the width of the rectangle (circle on the right side). 一个圆圈用于调整矩形的宽度(右侧的圆圈)。 Another rectangle is for resizing the height of the bar (circle on the top). 另一个矩形用于调整条形的高度(顶部的圆圈)。 Resizing the rectangle works perfectly. 调整矩形的大小非常有效。

 margin = {top: 40, right: 20, bottom: 30, left: 70},
      width = 600 - margin.left - margin.right,
      height = 400 - margin.top - margin.bottom;

    var svg  = d3.select('#canvas').attr("width",width).attr("height",height);

    gContainer =  svg.append('g')
                     .attr("class", "gContainer")
                     .attr("transform", function(d,i){
                          return "translate("+300+","+200+")"
                     })

    gBars = gContainer.append('g').attr("class", "gBar");


    gBars.append("rect")
         .attr("class", "Bar")
         .attr("fill","black")
         .attr("width", 40)
         .attr("height", function(d) { return height - 200})
         .style("opacity", 0.5);


    var handlerRadius = 3.5;
    handlerPointsPosition=[];


    elementWidth = Number(d3.select(".Bar").attr("width"));
    elementHeight = Number(d3.select(".Bar").attr("height"));

    x0 = 0 + (elementWidth/2) ;
    y0 = 0 ;

    x1 = 0 + (elementWidth);
    y1 = 0 +(elementHeight/2) ;

    x2= 0 + (elementWidth/2) ;
    y2= -20;

    handlerPointsPosition = [[x0,y0],[x1,y1],[x2,y2]];


    var rectangleHandlers = d3.behavior.drag()
              .origin(function(d) { return d; })
              .on("dragstart", dragstarted)
              .on("drag", dragged)




    gHandlerPoints= gContainer.selectAll("g.HandlerPoint")
       .data(handlerPointsPosition)
       .enter().append('g')
       .attr("class", "gHandlerPoint")
       .attr("id", function(d,i){return "gHandlerPoint_id_"+i;})
       .attr("transform", function(d,i){
         //console.log(d);
            return "translate("+d[0]+","+d[1]+")"
       })
       .call(rectangleHandlers);

    gHandlerPoints.append("circle")
              .attr("class", "handlerPoint")
              .style("fill", "white")
              .style("stroke", "blue")
              .attr("stroke","")
              .attr("r",function(d,i){return (i == 2 ? 4: 3.5);})
              .attr("id", function(d,i){return "HandlerPointId_"+i;})

    gContainer.append("line")
              .attr("class","handlerLine")
              .attr("x1", (elementWidth/2) )
              .attr("y1", 0- handlerRadius)
              .attr("x2", (elementWidth/2) )
              .attr("y2", -20 + handlerRadius)
              .attr("stroke-width", 1)
              .attr("stroke", "blue");


    function updateHandlerPosition(id, dX, dY)
    {
      d3.select(id).attr("transform", function(d,i){
             return "translate(" + [ dX, dY] + ")"
      })
    }

    function dragstarted(d,i) {
       dragIconX = d3.transform(d3.select(this).attr("transform")).translate[0];
       dragIconY = d3.transform(d3.select(this).attr("transform")).translate[1];

       barStartWidth = d3.select(".Bar").attr("width");
    }

    function dragged(d,i) {
      barHeight = d3.select(".Bar").attr("height");
      if(i == 0) // circle on the top edge of the bar
      {
        dragIconY = dragIconY + d3.mouse(this)[1];
        updateHandlerPosition("#gHandlerPoint_id_"+i, dragIconX, dragIconY );
        updateHandlerPosition("#gHandlerPoint_id_1", (barStartWidth), (barHeight/2) );

        var x = d3.transform(d3.select(".gContainer").attr("transform")).translate[0];
        var y = d3.transform(d3.select(".gContainer").attr("transform")).translate[1];

        d3.select(".gContainer").attr("transform", function(d,i){
               y = y + dragIconY;
               return "translate(" + [ x , y] + ")"
        })

        console.log(height, barHeight, barHeight - Number(dragIconY));
        d3.select(".Bar").attr("height", barHeight - Number(dragIconY));
      }
      else if (i==1) // circle on the right side of the bar
      {
        oldMouseX = dragIconX;
        dragIconX = d3.mouse(this)[0]+dragIconX;
        barWidth = dragIconX;
        updateHandlerPosition("#gHandlerPoint_id_"+i, dragIconX, dragIconY );
        updateHandlerPosition("#gHandlerPoint_id_0", (barWidth/2), 0 );
        updateHandlerPosition("#gHandlerPoint_id_2", (barWidth/2), -20);
        d3.select(".handlerLine").attr("x1",(barWidth/2)).attr("x2", (barWidth/2));
        d3.select(".Bar").attr("width", Math.abs(dragIconX));
      }
      else if(i==3) //circle on very top
      {

           // code for rotation should come here.

      }
    }

Link to jsFiddle: http://jsfiddle.net/Q5Jag/2103/ 链接到jsFiddle: http//jsfiddle.net/Q5Jag/2103/

I put the third circle for rotation (the circle on the very top). 我把第三个圆圈用于旋转(圆圈在最顶部)。 However, I have no idea how to fix the rotation. 但是,我不知道如何修复旋转。 I want the rectangle to rotate when I drag the circle on the very top. 当我在最顶部拖动圆圈时,我希望矩形旋转。 I also want to be able to resize the circle accordingly when it is rotated. 我还希望能够在旋转时相应地调整圆的大小。

Any idea? 任何想法?

You can calculate the rotation with respect to the center of your rectangle. 您可以计算相对于矩形中心的旋转。 Consider v1 as vector from center of rectangle to the rotation handle before rotation and v2 as a vector from center of rectangle to the rotation handle after rotation . v1视为从旋转的矩形中心到旋转手柄的矢量,将v2视为从旋转的矩形中心到旋转手柄的矢量。 Read here to know the math behind it. 请阅读此处以了解其背后的数学知识。

// old vector
v1 = {};
v1.x = oldMouseX-gCenterX;
v1.y = oldMouseY-gCenterY;

// new vector
v2 = {};
v2.x = dragHandleX-gCenterX;
v2.y = dragHandleY-gCenterY;

angle = Math.atan2(v2.y,v2.x) - Math.atan2(v1.y,v1.x);

where 哪里

  • gCenterX and gCenterY are coordinates of the center of rectangle gCenterXgCenterY是矩形中心的坐标
  • oldMouseX and oldMouseY are coordinates of mouse pointer prior to rotation oldMouseXoldMouseY是旋转前鼠标指针的坐标
  • dragHandleX and dragHandleY are coordinates of mouse pointer after rotation dragHandleXdragHandleY是旋转后鼠标指针的坐标

Here is the complete code: http://jsfiddle.net/Q5Jag/2109/ (But it fails if you mix rotation and resizing) 这是完整的代码: http//jsfiddle.net/Q5Jag/2109/ (但如果你混合旋转和调整大小它会失败)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM