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

时间:2016-11-26 17:31:10

标签: javascript d3.js

我正在尝试创建一个矩形,我可以使用位于矩形顶部的处理程序(小圆圈)调整大小并旋转它。与大多数允许我们调整大小和旋转形状的绘图工具类似。

我在矩形的顶部添加了三个圆圈。一个圆圈用于调整矩形的宽度(右侧的圆圈)。另一个矩形用于调整条形的高度(顶部的圆圈)。调整矩形的大小非常有效。

 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.

      }
    }

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

我把第三个圆圈用于旋转(圆圈位于最顶部)。但是,我不知道如何修复旋转。当我在最顶部拖动圆圈时,我希望矩形旋转。我还希望能够在旋转时相应地调整圆的大小。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您可以计算相对于矩形中心的旋转。将v1视为从矩形中心到旋转手柄旋转前的矢量v2作为从矩形中心到旋转手柄旋转后的矢量。阅读here以了解其背后的数学知识。

// 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);

,其中

  • gCenterXgCenterY是矩形中心的坐标
  • oldMouseXoldMouseY是旋转前鼠标指针的坐标
  • dragHandleXdragHandleY是旋转后鼠标指针的坐标

这是完整的代码: http://jsfiddle.net/Q5Jag/2109/ (但是如果你混合旋转和调整大小就会失败)