javascript - HTML 元素沿 SVG 路径与 javascript 相互跟随

标签 javascript html svg

我正在尝试让一些 html 元素沿着 SVG 路径相互跟随。我希望他们在绕行路径时保持相同的距离。我还希望 SVG 图像能够缩放到容纳它的容器。

我已经创建了一个 codepen 来展示我目前所拥有的: http://codepen.io/mikes000/pen/GIJab

我遇到的问题是,当元素沿 X 轴移动时,它们似乎比在 Y 轴上移动得更远。

有没有办法让他们在沿线行进时保持相同的距离?

谢谢!

更新**

经过一些进一步的摆弄后,我发现距离变化似乎是由 SVG viewbox 的纵横比增加 X 大于 Y 引起的。当它沿 X 轴向下拉伸(stretch) 1px 时,线可能在屏幕上变成 3px。

红色方 block 的位置是通过前后移动黑框宽度的一半来设置的。沿线行进时,如果更改视框纵横比,则线上每个点之间的距离会根据此增加或减少。

我已经尝试创建一个类似的 SVG,其视框的大小与容器 div 的大小完全相同,红点正好位于黑框的末端,一直向下。这并不能解决问题,因为我希望带有线条的 SVG 可以缩放到它放置在其中的任何大小的容器。

我认为,如果有一种方法可以计算黑框大小的像素数与它覆盖的直线下方的像素数之间的关系,那么红点就会完全对齐。

关于如何完成此任务的任何想法或关于解决此问题的更好方法的任何想法?

最佳答案

看看http://jsfiddle.net/4LzK4/

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

灵感来自:http://bl.ocks.org/duopixel/3824661

关于javascript - HTML 元素沿 SVG 路径与 javascript 相互跟随,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24210090/

相关文章:

html - GIF 作为 css 背景图片

Android:使用很长的 SVG 文件运行我的应用程序?

javascript - 使用 jQuery 将同一个 div 中的两个不同元素包装到所有类中?

javascript - 使用对象作为事件处理程序

javascript - 错误 : Target container is not a DOM element. - 使用开箱即用的应用程序

javascript - 向 svg g 元素添加填充

JQuery 将列表项移动到无序列表的末尾

html - 悬停时更改 SVG 中的填充颜色

javascript - 将 Svg 绘制到 Canvas ,包括嵌入在 svg 中的图像

javascript - HTML5 视频帧捕获到位图