【问题标题】:D3 JS - Making a Polygon Draggable using hard coded Bounding Box Attributes Does Not WorkD3 JS - 使用硬编码的边界框属性使多边形可拖动不起作用
【发布时间】:2017-06-26 05:52:49
【问题描述】:

我使用 D3 鼠标事件绘制了一个多边形,如 fiddle 所示。

下面是获取多边形边界框并设置多边形边界框属性的方法。

function completePolygon() {
  d3.select('g.outline').remove();

  gPoly = svgCanvas.append('g')
    .classed("polygon", true);

  polyPoints.splice(polyPoints.length - 1);

  polyEl = gPoly.append("polygon")
    .attr("points", polyPoints);

  for (var i = 0; i < polyPoints.length; i++) {
    gPoly.append('circle')
      .attr("cx", polyPoints[i][0])
      .attr("cy", polyPoints[i][1])
      .attr("r", 4)
      .call(dragBehavior);
  }

  isDrawing = false;
  isDragging = true;

  bbox = polyEl._groups[0][0].getBBox();
  var bbox2 = gPoly._groups[0][0].getBBox();

  //Altering the bounding box's attribute of polygon
  bbox.x = 0;
  bbox.y = 0;
  bbox.width = 50;
  bbox.height = 50;

  gPoly.attr("transform", "translate(" + 0 + "," + 0 + ")");
  // polyEL.attr("transform", "translate(" + 0 + "," + 0 + ")");
  //
  // gPoly.call(d3.drag().on("drag", movePolygon(bbox)));
}

我想让整个多边形可拖动。我尝试获取绘制多边形的边界框并将 X 和 Y 坐标设置为 0,然后像我在此 fiddle 中对圆形和矩形元素所做的那样在拖动时将其翻译,但更改任何多边形的边界框属性不会似乎对多边形元素有影响。然而,多边形的翻译工作。

除了循环遍历多边形的二维坐标数组并更新所有坐标点以实现可拖动多边形之外,还有其他方法吗?

【问题讨论】:

    标签: javascript d3.js polygon bounding-box


    【解决方案1】:

    我真的没有关注所有这些getBBox() 的东西。为什么不用传统的方式拖动元素呢?

    gPoly.call(d3.drag().on("drag", function(d) {
        d3.select(this).attr("transform", "translate(" +
            (d.x = d3.event.x) + "," + (d.y = d3.event.y) + ")")
    }));
    

    这是您的更改代码:

      d3.select('#poly').on('click', function() {
        new Polygon();
      });
    
      var w = 600,
        h = 500;
      var svgCanvas = d3.select('body').append('svg').attr("width", w).attr("height", h);
    
      function Polygon() {
    
        var polyPoints = [];
        var gContainer = svgCanvas.append('g').classed("outline", true);
        var isDrawing = false;
        var isDragging = false;
        var linePoint1, linePoint2;
        var startPoint;
        var bbox;
        var boundingRect;
        var shape;
        var gPoly;
    
        var polyDraw = svgCanvas.on("mousedown", setPoints)
          .on("mousemove", drawline)
          .on("mouseup", decidePoly);
    
        var dragBehavior = d3.drag().on("drag", alterPolygon);
        //        var dragPolygon = d3.drag().on("drag", movePolygon(bbox));
    
        //On mousedown - setting points for the polygon
        function setPoints() {
    
          if (isDragging) return;
    
    
          isDrawing = true;
    
          var plod = d3.mouse(this);
          linePoint1 = {
            x: plod[0],
            y: plod[1]
          };
    
          polyPoints.push(plod);
    
          var circlePoint = gContainer.append("circle")
            .attr("cx", linePoint1.x)
            .attr("cy", linePoint1.y)
            .attr("r", 4)
            .attr("start-point", true)
            .classed("handle", true)
            .style("cursor", "pointer");
    
    
          // on setting points if mousedown on a handle
          if (d3.event.target.hasAttribute("handle")) {
            completePolygon()
          }
    
        }
    
        //on mousemove - appending SVG line elements to the points
        function drawline() {
    
          if (isDrawing) {
            linePoint2 = d3.mouse(this);
            gContainer.select('line').remove();
            gContainer.append('line')
              .attr("x1", linePoint1.x)
              .attr("y1", linePoint1.y)
              .attr("x2", linePoint2[0] - 2) //arbitary value must be substracted due to circle cursor hover not working
              .attr("y2", linePoint2[1] - 2); // arbitary values must be tested
    
          }
        }
    
        //On mouseup - Removing the placeholder SVG lines and adding polyline
        function decidePoly() {
    
          gContainer.select('line').remove();
          gContainer.select('polyline').remove();
    
          var polyline = gContainer.append('polyline').attr('points', polyPoints);
    
          gContainer.selectAll('circle').remove();
    
          for (var i = 0; i < polyPoints.length; i++) {
            var circlePoint = gContainer.append('circle')
              .attr('cx', polyPoints[i][0])
              .attr('cy', polyPoints[i][1])
              .attr('r', 4)
              .attr("handle", true)
              .classed("handle", true);
    
          }
    
        }
    
        //Called on mousedown if mousedown point if a polygon handle
        function completePolygon() {
          d3.select('g.outline').remove();
    
          gPoly = svgCanvas.append('g')
            .classed("polygon", true);
    
          polyPoints.splice(polyPoints.length - 1);
          //console.log(polyPoints);
    
          polyEl = gPoly.append("polygon")
            .attr("points", polyPoints);
    
          for (var i = 0; i < polyPoints.length; i++) {
            gPoly.append('circle')
              .attr("cx", polyPoints[i][0])
              .attr("cy", polyPoints[i][1])
              .attr("r", 4)
              .call(dragBehavior);
          }
    
          isDrawing = false;
          isDragging = true;
    
          bbox = polyEl._groups[0][0].getBBox();
          var bbox2 = gPoly._groups[0][0].getBBox();
    
    
          bbox.x = 0;
          bbox.y = 0;
          bbox.width = 50;
          bbox.height = 50;
    
    
          //            debugger;
    
          gPoly.datum({
            x: 0,
            y: 0
          })
    
          //console.log(bbox);
          gPoly.attr("transform", function(d) {
            return "translate(" + d.x + "," + d.y + ")"
          });
          //          polyEL.attr("transform", "translate(" + 0 + "," + 0 + ")");
          //
          gPoly.call(d3.drag().on("drag", function(d) {
            d3.select(this).attr("transform", "translate(" + (d.x = d3.event.x) + "," + (d.y = d3.event.y) + ")")
          }));
    
        }
    
        //Altering polygon coordinates based on handle drag
        function alterPolygon() {
    
          if (isDrawing === true) return;
    
          var alteredPoints = [];
          var selectedP = d3.select(this);
          var parentNode = d3.select(this.parentNode);
    
          //select only the elements belonging to the parent <g> of the selected circle
          var circles = d3.select(this.parentNode).selectAll('circle');
          var polygon = d3.select(this.parentNode).select('polygon');
    
    
          var pointCX = d3.event.x;
          var pointCY = d3.event.y;
    
          //rendering selected circle on drag
          selectedP.attr("cx", pointCX).attr("cy", pointCY);
    
          //loop through the group of circle handles attatched to the polygon and push to new array
          for (var i = 0; i < polyPoints.length; i++) {
    
            var circleCoord = d3.select(circles._groups[0][i]);
            var pointCoord = [circleCoord.attr("cx"), circleCoord.attr("cy")];
            alteredPoints[i] = pointCoord;
    
          }
    
          //re-rendering polygon attributes to fit the handles
          polygon.attr("points", alteredPoints);
    
          bbox = parentNode._groups[0][0].getBBox();
          console.log(bbox);
        }
    
        function movePolygon() {
    
        }
    
        function prepareTransform(bboxVal) {
    
          var originalPosition = {
            x: bboxVal.x,
            y: bboxVal.y
          };
    
          console.log(bboxVal);
          console.log(bbox);
    
          bbox.x = 0;
          bbox.y = 0;
    
    
    
    
          //            //render a bounding box
          //            shape.rectEl.attr("x", bbox.x).attr("y", bbox.y).attr("height", bbox.height).attr("width", bbox.width);
          //
          //            //drag points
          //            shape.pointEl1.attr("cx", bbox.x).attr("cy", bbox.y).attr("r", 4);
          //            shape.pointEl2.attr("cx", (bbox.x + bbox.width)).attr("cy", (bbox.y + bbox.height)).attr("r", 4);
          //            shape.pointEl3.attr("cx", bbox.x + bbox.width).attr("cy", bbox.y).attr("r", 4);
          //            shape.pointEl4.attr("cx", bbox.x).attr("cy", bbox.y + bbox.height).attr("r", 4);
    
          return originalPosition;
        }
      }
    h1 {
      text-align: center;
    }
    
    .svg-container {
      display: inline-block;
      position: relative;
      width: 100%;
      padding-bottom: 60%;
      /* depends on svg ratio, for my zebra height/width = 1.2 so padding-bottom = 50% * 1.2 = 60% */
      vertical-align: middle;
      /* top | middle | bottom ... do what you want */
    }
    
    .my-svg {
      /* svg into : object, img or inline */
      display: block;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      /* only required for <img /> */
      z-index: 0;
    }
    
    svg {
      border: solid 1px rgba(221, 61, 16, 0.71);
    }
    
    .rectangle {
      fill: lightblue;
      stroke: blue;
      stroke-width: 2px;
      fill-opacity: 0.5;
    }
    
    .rectangle-bind {
      fill: none;
      stroke: #081c4e;
      stroke-width: 1px;
      stroke-dasharray: 5;
    }
    
    circle {
      fill: lightgreen;
      stroke: green;
      stroke-width: 2px;
      fill-opacity: 0.5;
    }
    
    .rect-active {
      fill: #1578db;
    }
    
    .pointC-active {
      fill: #FF8F00;
    }
    
    .circle-active {
      fill: #4CAF50;
    }
    
    path {
      fill: #ffb7b3;
      stroke: #ff4736;
      stroke-width: 5px;
    }
    
    polygon {
      fill: #b6eeff;
      fill-opacity: 0.5;
      stroke: #0067ff;
      stroke-width: 2px;
    }
    
    line {
      fill: none;
      stroke: #cd08ff;
      stroke-width: 2px;
    }
    
    polyline {
      fill: none;
      stroke: #563aff;
      stroke-width: 2px;
    }
    
    circle.handle {
      fill: yellow;
      stroke: #cb9c0f;
      stroke-width: 2px;
      cursor: pointer;
    }
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <button id='poly'>Poly</button>

    PS:不要使用_groups[0][0]。请改用node()

    【讨论】:

    • 看起来我已经很努力了。你的方式也缩短了我的代码。
    猜你喜欢
    • 2012-08-25
    • 2012-11-09
    • 2011-07-20
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多