【问题标题】:D3js drag() returns strange results on chromeD3js drag() 在 chrome 上返回奇怪的结果
【发布时间】:2020-11-18 21:17:38
【问题描述】:

在 pc chrome 上它工作正常,在 chrome 移动模拟器(或 android chroem)上,箭头跳过圆圈。 d3.pointers(event)[0] 返回的 x 和 y 对于 y 轴不是线性的 => 156、100、157、101、158、102。

drawCompass({
  radius: 120
})

function drawCompass(data) {

  const compasColor = '#ccc'
  // const { x, y } = map.latLngToLayerPoint([data.lat, data.long])
  const x = y = 190;
  const r = data.radius

  svg = d3.select("svg")
  svg
    .append("circle")
    .attr("cx", x)
    .attr("cy", y)
    .attr("r", r)
    .style("fill", "red")
    .attr("stroke", compasColor)
    .attr("stroke-width", 3)
    .attr("fill-opacity", .0)

  drawArrow("steelblue", 0, "0", "");

  function drawArrow(color, angle, text_inner, text_outer) {

    const outer_id = "outer_" + color + Date.now(); //id for line text 
    const inner_id = "inner"
    const arrowGroup = svg.append("g").attr("class", "arrowGroup");
    const offset = 30;

    //line radius
    arrowGroup
      .append("path")
      .attr("id", inner_id) //normall
      .attr("class", "compassLines")
      .attr("d", d3.line()([
        [x, y - r],
        [x, y],
      ]))
      .attr("stroke", compasColor)
      .attr("stroke-width", 1)
      .attr("fill", "none");


    // line and background for text outside the compass circle 
    const dragger = arrowGroup
      .append("path")
      .attr("id", outer_id) //normall
      .style("stroke", "black")
      .attr("stroke-width", 20)
      .attr("stroke-opacity", 0.5)
      .attr("fill-opacity", 0.7)
      .style("stroke-linecap", "round")
      .attr("d", d3.line()([
        [x, y - r],
        [x, y - r - 30]
      ]))
      .call(
        d3.drag().on("drag", dragged)
      )

    function dragged(event) {
      const arrow_position = d3.pointers(event)[0];
      console.log('arrow_position', arrow_position);
      var angle123 = geometric.lineAngle([
        [x, y], arrow_position
      ]);
      const tempAngle = Math.ceil(angle123 + 90)
      const displayAngel = tempAngle < 0 ? 360 + tempAngle : tempAngle
      const arrow = this.parentNode;
      d3.select(arrow)
        .attr('transform', `rotate(${angle123 + 90} ${x} ${y})`);
    }
    return arrowGroup
  }
}
<!DOCTYPE html>
<html>

<head>
  <style>
    .compassText {
      text-align: center;
      font-size: 30px;
      text-anchor: middle;
    }
  </style>
  <script src="https://d3js.org/d3.v6.min.js"></script>
  <script src="https://unpkg.com/geometric@1.0.0/build/geometric.min.js"></script>
</head>

<body>

  <svg width="380" height="380"></svg>

【问题讨论】:

    标签: javascript android google-chrome d3.js


    【解决方案1】:

    其实我在这个方面太深入了,所以请耐心等待。

    解决方案的第一部分实际上与我回答 here 的类似。拖动计算当前拖动元素和容器之间的距离。通常,该容器是父节点。但是,如果您移动拖动手柄的父节点(就像您所做的那样),那么容器会相对于自身偏移,从而中断。如果您将祖父母改为容器,使用this.parentNode.parentNode,变化的输出就会消失。

    所有这些实际上都发生在d3.selection 中的d3.pointer 中,其中函数通过Touch event 和.container node 调用。 node 是这里的问题,因为它等于您要移动的节点。


    现在,解决了这个问题,一切看起来都很好。然而,在我的移动模拟器上,即使输出稳定,摆动仍然存在。下图是console.log(event.x, event.y, angle123) 的结果。如您所见,前两个保持稳定,但最后一个摆动。

    这种摆动的原因是您正在使用d3.pointers(),它会自动再次调用d3.pointer()。但这一次,它使用了错误的node。所以不是祖父母,而是父母。所以不用d3.pointer,你可以自己获取等价的值。

    var angle123 = geometric.lineAngle([
        [x, y], [event.x, event.y]
    ]);
    

    这确实解决了问题。

    drawCompass({
      radius: 120
    })
    
    function drawCompass(data) {
    
      const compasColor = '#ccc'
      // const { x, y } = map.latLngToLayerPoint([data.lat, data.long])
      const x = y = 190;
      const r = data.radius
    
      svg = d3.select("svg")
      svg
        .append("circle")
        .attr("cx", x)
        .attr("cy", y)
        .attr("r", r)
        .style("fill", "red")
        .attr("stroke", compasColor)
        .attr("stroke-width", 3)
        .attr("fill-opacity", .0)
    
      drawArrow("steelblue", 0, "0", "");
    
      function drawArrow(color, angle, text_inner, text_outer) {
    
        const outer_id = "outer_" + color + Date.now(); //id for line text 
        const inner_id = "inner"
        const arrowGroup = svg.append("g").attr("class", "arrowGroup");
        const offset = 30;
    
        //line radius
        arrowGroup
          .append("path")
          .attr("id", inner_id) //normall
          .attr("class", "compassLines")
          .attr("d", d3.line()([
            [x, y - r],
            [x, y],
          ]))
          .attr("stroke", compasColor)
          .attr("stroke-width", 1)
          .attr("fill", "none");
    
    
        // line and background for text outside the compass circle 
        const dragger = arrowGroup
          .append("path")
          .attr("id", outer_id) //normall
          .style("stroke", "black")
          .attr("stroke-width", 20)
          .attr("stroke-opacity", 0.5)
          .attr("fill-opacity", 0.7)
          .style("stroke-linecap", "round")
          .attr("d", d3.line()([
            [x, y - r],
            [x, y - r - 30]
          ]))
          .call(
            d3.drag()
              .container(function() { return this.parentNode.parentNode; })
              .on("drag", dragged)
          )
    
        function dragged(event) {
          var angle123 = geometric.lineAngle([
            [x, y], [event.x, event.y]
          ]);
          const tempAngle = Math.ceil(angle123 + 90)
          const displayAngel = tempAngle < 0 ? 360 + tempAngle : tempAngle
          const arrow = this.parentNode;
          d3.select(arrow)
            .attr('transform', `rotate(${angle123 + 90} ${x} ${y})`);
        }
        return arrowGroup
      }
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <style>
        .compassText {
          text-align: center;
          font-size: 30px;
          text-anchor: middle;
        }
      </style>
      <script src="https://d3js.org/d3.v6.min.js"></script>
      <script src="https://unpkg.com/geometric@1.0.0/build/geometric.min.js"></script>
    </head>
    
    <body>
    
      <svg width="380" height="380"></svg>

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-08
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多