我正在尝试让一些 html 元素沿着 SVG 路径相互跟随。我希望他们在绕行路径时保持相同的距离。我还希望 SVG 图像能够缩放到容纳它的容器。
我已经创建了一个 codepen 来展示我目前所拥有的: http://codepen.io/mikes000/pen/GIJab
我遇到的问题是,当元素沿 X 轴移动时,它们似乎比在 Y 轴上移动得更远。
有没有办法让他们在沿线行进时保持相同的距离?
谢谢!
更新**
经过一些进一步的摆弄后,我发现距离变化似乎是由 SVG viewbox 的纵横比增加 X 大于 Y 引起的。当它沿 X 轴向下拉伸(stretch) 1px 时,线可能在屏幕上变成 3px。
红色方 block 的位置是通过前后移动黑框宽度的一半来设置的。沿线行进时,如果更改视框纵横比,则线上每个点之间的距离会根据此增加或减少。
我已经尝试创建一个类似的 SVG,其视框的大小与容器 div 的大小完全相同,红点正好位于黑框的末端,一直向下。这并不能解决问题,因为我希望带有线条的 SVG 可以缩放到它放置在其中的任何大小的容器。
我认为,如果有一种方法可以计算黑框大小的像素数与它覆盖的直线下方的像素数之间的关系,那么红点就会完全对齐。
关于如何完成此任务的任何想法或关于解决此问题的更好方法的任何想法?
最佳答案
var svg = d3.select("#line").append("svg:svg").attr("width", "100%").attr("height", "100%");
var data = d3.range(50).map(function(){return Math.random()*10})
var x = d3.scale.linear().domain([0, 10]).range([0, 700]);
var y = d3.scale.linear().domain([0, 10]).range([10, 290]);
var line = d3.svg.line()
.interpolate("cardinal")
.x(function(d,i) {return x(i);})
.y(function(d) {return y(d);})
var path = svg.append("svg:path").attr("d", line(data));
var circle =
svg.append("circle")
.attr("cx", 100)
.attr("cy", 350)
.attr("r", 3)
.attr("fill", "red");
var circleBehind =
svg.append("circle")
.attr("cx", 50)
.attr("cy", 300)
.attr("r", 3)
.attr("fill", "blue");
var circleAhead =
svg.append("circle")
.attr("cx", 125)
.attr("cy", 375)
.attr("r", 3)
.attr("fill", "green");
var pathEl = path.node();
var pathLength = pathEl.getTotalLength();
var BBox = pathEl.getBBox();
var scale = pathLength/BBox.width;
var offsetLeft = document.getElementById("line").offsetLeft;
var randomizeButton = d3.select("button");
svg.on("mousemove", function() {
var x = d3.event.pageX - offsetLeft;
var beginning = x, end = pathLength, target;
while (true) {
target = Math.floor((beginning + end) / 2);
pos = pathEl.getPointAtLength(target);
if ((target === end || target === beginning) && pos.x !== x) {
break;
}
if (pos.x > x) end = target;
else if (pos.x < x) beginning = target;
else break; //position found
}
circle
.attr("opacity", 1)
.attr("cx", x)
.attr("cy", pos.y);
posBehind = pathEl.getPointAtLength(target-10);
circleBehind
.attr("opacity", 1)
.attr("cx", posBehind.x)
.attr("cy", posBehind.y);
posAhead = pathEl.getPointAtLength(target+10);
circleAhead
.attr("opacity", 1)
.attr("cx", posAhead.x)
.attr("cy", posAhead.y);
});
randomizeButton.on("click", function(){
data = d3.range(50).map(function(){return Math.random()*10});
circle.attr("opacity", 0)
path
.transition()
.duration(300)
.attr("d", line(data));
});
与其自行计算前后圆圈的位置,不如使用相对于必须位于中间的对象中心的 getPointAtLength
。
关于javascript - HTML 元素沿 SVG 路径与 javascript 相互跟随,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24210090/