javascript - 如何使用 d3.js 沿 GeoJSON 路径为对象设置动画?

标签 javascript d3.js

我正在使用 D3.js 从 GeoJSON 文件生成和呈现路径。这工作正常,但现在我想沿着那条路径为一个对象设置动画。我知道如何使用 D3 和标准 SVG 来做到这一点:

  1. 创建一个过渡并设置其持续时间
  2. 对于转换的每一帧,使用 % complete 找到沿路径的坐标
  3. 将对象移动到第2步中找到的坐标

这很简单。但我遇到的问题是 d3.geo.path() 似乎不像标准 D3 路径对象(例如有用的 getPointAtLength() 方法)那样返回任何长度或位置数据。所以我无法找到某个点的 x、y 坐标,比如说,沿着路径的 25%。

有没有办法获取这些数据? (或者是否有更好的方法,例如将 d3.geo.path() 转换为常规 D3 路径?)

下面是我的代码的 chop 版本;一个活生生的例子在这里:http://jsfiddle.net/5m35J/4/

json = {
    ... // snipped for brevity
};

// Draw a GeoJSON line on the map:

map = $('#map');
xy = d3.geo.mercator().scale(480000).translate([630700, 401100]);
path = d3.geo.path().projection(xy);

vis = d3.select("#map")
    .append("svg:svg")
    .attr("width", 960)
    .attr("height", 600);

vis.append("svg:g")
    .attr("class", "route")
    .selectAll("path")
    .data(json.features)
    .enter()
    .append("svg:path")
    .attr("d", path)
    .attr("fill-opacity", 0.5)
    .attr("fill", "#fff")
    .attr("stroke", "#333");

// Draw a red circle on the map:

//len = 100; // how do I find the length of the path?
origin_x = 100;
origin_y = 100;

group = vis.append("svg:g");

circle = group.append("circle")
    .attr({
    r: 10,
    fill: '#f33',
    transform: function () {
        //var p = path.getPointAtLength(0)
        //return "translate(" + [p.x, p.y] + ")";
        return "translate("+ origin_x +","+ origin_y +")";
    }
});

// Animate the circle:

duration = 5000;
circle.transition()
    .duration(duration)
    .ease("linear")
    .attrTween("transform", function (d, i) {
    return function (t) {
        //var p = path.node().getPointAtLength(len*t) // d3.geo.path() doesn't provide a getPointAtLength() method!
        //return "translate("+[p.x,p.y]+")"
        var current_x = origin_x + origin_x * t;
        var current_y = origin_y + origin_y * t;            
        return "translate("+ current_x +","+ current_y +")";
    }
});

最佳答案

嗯,我想出来了,但我不完全确定我的解决方案是否是“正确”的方法。基本上,我使用 D3 选择由 d3.geo.path() 对象创建的原始 SVG 元素。

注意 targetPathpathNodepathLength 变量以及 transform() 的变化> 和 attrTween() 函数:

// Draw a red circle on the map:

group = vis.append("svg:g");

var targetPath = d3.selectAll('.route')[0][0],
    pathNode = d3.select(targetPath).selectAll('path').node(),
    pathLength = pathNode.getTotalLength();

circle = group.append("circle")
    .attr({
    r: 10,
    fill: '#f33',
    transform: function () {
        var p = pathNode.getPointAtLength(0)
        return "translate(" + [p.x, p.y] + ")";
    }
});

// Animate the circle:

duration = 10000;
circle.transition()
    .duration(duration)
    .ease("linear")
    .attrTween("transform", function (d, i) {
    return function (t) {
        var p = pathNode.getPointAtLength(pathLength*t);
        return "translate(" + [p.x, p.y] + ")";
    }
});

实例在这里:http://jsfiddle.net/5m35J/6/

关于javascript - 如何使用 d3.js 沿 GeoJSON 路径为对象设置动画?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17794501/

相关文章:

javascript - 可缩放冰柱 d3 从右到左

javascript - 如何在 d3 中绘制多边形内的图像

d3.js - 当两个条的值为 0 时,相对 barmode 标签中的 Plotly.js 会重叠

javascript - Rails 的 RJS 替代方案

javascript - nodejs不停

javascript - 检查倒计时是否结束

javascript - 提交后不要清除输入

javascript - 加载后将媒体变量添加到数组时如何不改变媒体变量。倒闭?

javascript - 使用 setInterval() 自动移动时间 slider

javascript - 使用 dc.js 的日期堆积面积图