简体   繁体   English

D3-跨组拖动多个元素

[英]D3 - dragging multiple elements across groups

I'm trying to achieve a D3 drag behavior, for which I'm not finding an example. 我正在尝试实现D3拖动行为,但没有找到示例。

The below code creates a couple of rows with a rectangle, circle and ellipse each, and the drag feature is enabled for the circle. 下面的代码创建了几行,每行分别具有矩形,圆形和椭圆形,并且为圆形启用了拖动功能。

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Drag many</title> <style media="screen"> .active { stroke: #000; stroke-width: 2px; } </style> </head> <body> <svg width=1000 height=500></svg> <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script> <script type="text/javascript"> var svg=d3.select("svg"), mainGroup = svg.append("g"); var squareData = [ {x:25, y:23, width:15, height:15}, {x:25, y:63, width:15, height:15} ]; var circleData = [ {cx:60, cy:30, r:10}, {cx:60, cy:70, r:10} ]; var ellipseData = [ {cx:90, cy:30, rx:10, ry:15}, {cx:90, cy:70, rx:10, ry:15} ]; var squareGroup = mainGroup.append("g"); squareGroup.selectAll(null) .data(squareData) .enter().append("rect") .attr("class", (d,i)=>`rectGroup row_${i+1}`) .attr("x", d=>dx) .attr("y", d=>dy) .attr("width", d=>d.width) .attr("height", d=>d.height) .attr("fill", "blue"); circleGroup = mainGroup.append("g"); circleGroup.selectAll(null) .data(circleData) .enter().append("circle") .attr("class", (d,i)=>`circleGroup row_${i+1}`) .attr("cx", d=>d.cx) .attr("cy", d=>d.cy) .attr("r", d=>dr) .attr("fill", "red") .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); ellipseGroup = mainGroup.append("g"); ellipseGroup.selectAll(null) .data(ellipseData) .enter().append("ellipse") .attr("class", (d,i)=>`ellipseGroup row_${i+1}`) .attr("cx", d=>d.cx) .attr("cy", d=>d.cy) .attr("rx", d=>d.rx) .attr("ry", d=>d.ry) .attr("fill", "green"); function dragstarted(d){ d3.select(this).classed("active", true); } function dragended(d){ d3.select(this).classed("active", false); } function dragged(d){ //var dx = d3.event.x - d3.select(this).attr("cx") d3.select(this).attr("cx", dx = d3.event.x); // I really need to move all the elements in this row here, // with the circle being the pivot... } </script> </body> </html> 

I would like to modify the drag behavior of the circle to pull the entire row with it rather than move alone. 我想修改圆的拖动行为,以拉动整行而不是单独移动。

How can I achieve this? 我该如何实现?

It looks like you give each row a class so instead of: 好像您给每一行一个类,而不是:

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

get the class of that row (from the looks of your code it should be the second class) with: var thisRow = d3.select(this).attr("class").split()[1]; 通过以下方法获取该行的类(从代码的外观上应该是第二类): var thisRow = d3.select(this).attr("class").split()[1];

.split() will split on spaces which is how getting the class list will spit out its result. .split()将在空格上分割,这就是获取类列表将其结果吐出来的方式。

After getting the class move all of that class: 上完课后,移动所有该课:

d3.selectAll("." + thisRow).attr("cx", dx = d3.event.x);

I'm not really sure if there's a better way of finding the row , but here's how I solved it using the concept from @pmkroeker 我不确定是否有找到row的更好方法,但是这是我使用@pmkroeker中的概念解决的方法

  function dragged(d){
    var deltaX = d3.event.x - d3.select(this).attr("cx");
    d3.select(this).attr("cx", d.x = d3.event.x); // move the circle

    // find the row
    var row = d3.select(this).attr("class").split(/\s+/).filter(s=>s.startsWith("row_"))[0];

    // grab other elements of the row and move them as well
    d3.selectAll("."+row).filter(".rectGroup").attr("x", d=>d.x = d.x+deltaX);
    d3.selectAll("."+row).filter(".ellipseGroup").attr("cx", d=>d.cx = d.cx+deltaX);
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM