繁体   English   中英

沿d3中的路径拖动

[英]Drag along path in d3

使用d3和React我画了一条路。 在此路径上,我有多个只能沿该路径拖动的圆。 但是,当该路径上有一个圆圈时,我当前的实现(仅适用于这种情况)有效。

(在dragStart上,无论位置如何,它都将移动到路径上的长度0,并且每当我拖动第二个圆时,它就会从上一个圆的位置开始)。

我的问题是:如何沿着d3中的路径拖动多个圆(或我们)? 有没有一种方法可以根据当前圆的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> } } 

与此类似,只有可拖动的圈子和多个圈子: http : //bl.ocks.org/mbostock/1705868

这是此示例的快速修改,使圆可拖动:

 <!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