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

标签 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/

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

有什么想法吗?

最佳答案

您可以计算相对于矩形中心的旋转。将 v1 视为从矩形中心到旋转 handle 的向量旋转前,将 v2 视为从矩形中心到旋转 handle 的向量>旋转后。阅读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/ (但如果你混合旋转和调整大小,它会失败)

关于javascript - 可调整大小和可旋转的矩形 D3?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40821071/

相关文章:

javascript - 跨子域设置 Cookies javascript 陷阱

javascript - 升级到 KendoUI 2013.1.319 后,Treeview 抛出异常

javascript - 当找到两个对象时,forEach 内部的过滤器无法正常工作

d3.js - 将元素添加到组元素的顶部

javascript - 使用 d3js 遍历 SVGElement 路径?

javascript - 当 div 改变大小时,如何修复 div 内图像的布局?

javascript - 如何播放/暂停声音以及声音从头开始播放?

html - d3.js 设置属性为百分比而不是像素

javascript - 向数据添加变量数

javascript - 在 jsf 中使用 d3 图表有技巧吗?