简体   繁体   English

沿d3中的路径拖动

[英]Drag along path in d3

Using d3 and React I have drawn a path. 使用d3和React我画了一条路。 On this path I have multiple circles which are draggable only along that path. 在此路径上,我有多个只能沿该路径拖动的圆。 However, my current implementation only (sort of) works when there is one circle on that path. 但是,当该路径上有一个圆圈时,我当前的实现(仅适用于这种情况)有效。

(On dragStart it moves to length 0 on the path regardless of position, and whenever I'm dragging a second circle it starts of the the previous circle's position). (在dragStart上,无论位置如何,它都将移动到路径上的长度0,并且每当我拖动第二个圆时,它就会从上一个圆的位置开始)。

My question is: How can I drag multiple circles (or we) along a path in d3? 我的问题是:如何沿着d3中的路径拖动多个圆(或我们)? Is there a way to get the currentLength position on the path based on cx and cy of the current circle? 有没有一种方法可以根据当前圆的cx和cy获取路径上的currentLength位置?

 var currentLength = 0; class MyComponent extends Component { constructor(props) { super(props) currentLength = 0; } componentDidMount() { var drag = d3.behavior.drag() .on('drag', this.move); var g = d3.select(this._base); var circle = g.selectAll('circle').data(this.props.data); var onEnter = circle.enter(); onEnter.append('circle') .attr({ r: 10, cx: (d) => dx, cy: (d) => dy }) .style('fill', 'blue') .call(drag); } move(d) { currentLength += d3.event.dx + d3.event.dy if (currentLength < 0) { currentLength = 0 } var pointAtCurrentLength = d3.select('#path').node().getPointAtLength(currentLength) this.cx.baseVal.value = pointAtCurrentLength.x; this.cy.baseVal.value = pointAtCurrentLength.y; } render() { return <g ref={(c)=>this._base=c}></g> } } 

Something similar to this, only draggable and multiple circles: http://bl.ocks.org/mbostock/1705868 与此类似,只有可拖动的圈子和多个圈子: http : //bl.ocks.org/mbostock/1705868

Here's a quick modification to this example , which makes the circles draggable: 这是此示例的快速修改,使圆可拖动:

 <!DOCTYPE html> <meta charset="utf-8"> <style> path { fill: none; stroke: #000; stroke-width: 1.5px; } line { fill: none; stroke: red; stroke-width: 1.5px; } circle { fill: red; } </style> <body> <script src="//d3js.org/d3.v3.min.js"></script> <script> var points = [[600,276],[586,393],[378,388],[589,148],[346,227],[365,108]]; var width = 960, height = 500; var line = d3.svg.line() .interpolate("cardinal"); var drag = d3.behavior.drag() .on("drag", dragged); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); var path = svg.append("path") .datum(points) .attr("d", line); var line = svg.append("line"); var circle = svg.append("circle") .attr("transform", "translate(" + points[0] + ")") .attr("r", 7) .call(drag); svg.append("circle") .attr("transform", "translate(" + points[5] + ")") .attr("r", 7) .call(drag); function dragged(d) { var m = d3.mouse(svg.node()), p = closestPoint(path.node(), m); d3.select(this) .attr("transform", "translate(" + p[0] + "," + p[1] + ")") } function closestPoint(pathNode, point) { var pathLength = pathNode.getTotalLength(), precision = 8, best, bestLength, bestDistance = Infinity; // linear scan for coarse approximation for (var scan, scanLength = 0, scanDistance; scanLength <= pathLength; scanLength += precision) { if ((scanDistance = distance2(scan = pathNode.getPointAtLength(scanLength))) < bestDistance) { best = scan, bestLength = scanLength, bestDistance = scanDistance; } } // binary search for precise estimate precision /= 2; while (precision > 0.5) { var before, after, beforeLength, afterLength, beforeDistance, afterDistance; if ((beforeLength = bestLength - precision) >= 0 && (beforeDistance = distance2(before = pathNode.getPointAtLength(beforeLength))) < bestDistance) { best = before, bestLength = beforeLength, bestDistance = beforeDistance; } else if ((afterLength = bestLength + precision) <= pathLength && (afterDistance = distance2(after = pathNode.getPointAtLength(afterLength))) < bestDistance) { best = after, bestLength = afterLength, bestDistance = afterDistance; } else { precision /= 2; } } best = [best.x, best.y]; best.distance = Math.sqrt(bestDistance); return best; function distance2(p) { var dx = px - point[0], dy = py - point[1]; return dx * dx + dy * dy; } } </script> 

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

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