【问题标题】:D3 drag & click in v6 for grouped objectsD3 在 v6 中拖动并单击分组对象
【发布时间】:2020-10-16 23:02:15
【问题描述】:

处理Mike's example 我正在尝试弄清楚如何将概念转移到分组元素。我可以单独创建启动拖动和单击,但在一起我似乎无法单击工作。下面是一个 sn-p - 这只是我使用过的许多方法中的一种。

  const width = 400;
  const height = 300;
  const radius = 5;
  
  const svg = d3.select("#chart").append('svg')
    .attr('width', '400')
    .attr('height', '400')
    .style('border', 'solid 1px');

  const circles = d3.range(20).map(i => ({
    x: Math.random() * (width - radius * 2) + radius,
    y: Math.random() * (height - radius * 2) + radius,
    index: i
  }));

const group =  svg.selectAll("g").data(circles).enter()
      .append("g")
      .attr("cx", d => d.x)
      .attr("cy", d => d.y)            
      .call(d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended))
  
  group.append("circle")
      .attr("cx", d => d.x)
      .attr("cy", d => d.y)            
      .attr("r", radius)
      .attr("fill", d => d3.schemeCategory10[d.index % 10])
      .on("click", clicked);
      
    group.append("text")
      .attr("x", d => d.x)
      .attr("y", d => d.y)            
      .style("fill", 'white')
      .text('a')
    

  function clicked(event, d) {
    if (event.defaultPrevented) return; // dragged

    d3.select(this).transition()
        .attr("fill", "black")
        .attr("r", radius * 2)
      .transition()
        .attr("r", radius)
        .attr("fill", d3.schemeCategory10[d.index % 10]);
  }


  function dragstarted() {
    d3.select(this).attr("stroke", "black");
  }

  function dragged(event, d) {
    d3.select(this).raise().attr("cx", d.x = event.x).attr("cy", d.y = event.y);
  }

  function dragended() {
    d3.select(this).attr("stroke", null);
  }
<script src="https://d3js.org/d3.v6.js"></script>
<div id="chart"></div>

【问题讨论】:

    标签: d3.js click drag


    【解决方案1】:

    关键问题是您使用cxcy 属性定位每个g,并在拖动时更新这些属性。 g 元素不能被 cxcy 定位,因此最初设置这些并在拖动时更新它们不会导致任何变化。

    您需要使用翻译定位 g 元素:

      .attr("transform", d=> "translate("+[d.x,d.y]+")" )   
    

    此外,您现在不需要定位圆圈和文本 - 否则每个 x 和 y 坐标将应用两次 - 一次应用于 g,一次应用于子元素。

    现在您只需要在每次拖动时更新翻译,例如:

    function drag(event,d) {
        d.x = event.x;
        d.y = event.y;
        d3.select(this).raise().attr("transform", d=> "translate("+[d.x,d.y]+")" )
    }
    

    这应该会给你类似的东西:

    const width = 400;
      const height = 300;
      const radius = 5;
      
      const svg = d3.select("#chart").append('svg')
        .attr('width', '400')
        .attr('height', '400')
        .style('border', 'solid 1px');
    
      const circles = d3.range(20).map(i => ({
        x: Math.random() * (width - radius * 2) + radius,
        y: Math.random() * (height - radius * 2) + radius,
        index: i
      }));
    
    const group =  svg.selectAll("g").data(circles).enter()
          .append("g")
          .attr("transform", d=> "translate("+[d.x,d.y]+")" )            
          .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended))
      
      group.append("circle")    
          .attr("r", radius)
          .attr("fill", d => d3.schemeCategory10[d.index % 10])
          .on("click", clicked);
          
        group.append("text")    
          .style("fill", 'white')
          .text('a')
        
    
      function clicked(event, d) {
        if (event.defaultPrevented) return; // dragged
    
        d3.select(this).transition()
            .attr("fill", "black")
            .attr("r", radius * 2)
          .transition()
            .attr("r", radius)
            .attr("fill", d3.schemeCategory10[d.index % 10]);
      }
    
    
      function dragstarted() {
        d3.select(this).attr("stroke", "black");
      }
    
      function dragged(event, d) {
        d.x = event.x;
        d.y = event.y;
        d3.select(this).raise().attr("transform", d=> "translate("+[d.x,d.y]+")" )
      }
    
      function dragended() {
        d3.select(this).attr("stroke", null);
      }
    <script src="https://d3js.org/d3.v6.js"></script>
    <div id="chart"></div>

    【讨论】:

    • 太棒了!感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    • 1970-01-01
    • 1970-01-01
    • 2013-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多