簡體   English   中英

D3 多個 SVG 對象跟隨路徑

[英]D3 Multiple SVG Objects Following Path

我對 D3 很陌生,我想用多個均勻間隔的箭頭沿着所述線行進,以指示電路的流動。

這基本上就是我想要的(箭頭在無限循環中沿線動畫)(評論中的鏈接,聲譽不夠高)

我發現了這個很好的例子,一個圖像動畫跟隨正確旋轉的路徑。 http://bl.ocks.org/KoGor/8163268

我的問題是我不知道如何將所有額外的箭頭放在我的路徑上。 我曾考慮將我的路徑分成一組端到端的許多等長路徑,並同時為它們設置動畫,但這似乎比實際需要的要復雜。

知道我應該如何進行嗎?

這是我到目前為止所擁有的: https : //jsfiddle.net/singerbradley/wcfg2mec/16/

代碼

 var points = [ [480, 200], [580, 400], [680, 100], [780, 300], [180, 300], [280, 100], [380, 400] ]; var svg = d3.select("body").append("svg") .attr("width", 960) .attr("height", 500); var path = svg.append("path") .data([points]) .attr("d", d3.svg.line() .tension(1) // Catmull–Rom .interpolate("linear")); //basis-open var arrow = svg.append("polygon") .attr("points", "0,24, 15,12, 0,0") // x,y points .attr("transform", "translate(" + points[3] + ")"); transition(); function transition() { arrow.transition() .duration(10000) .ease("linear") .attrTween("transform", translateAlong(path.node())) .each("end", transition); //infinite loop } // Returns an attrTween for translating along the specified path element. function translateAlong(path) { var l = path.getTotalLength(); var t0 = 0; return function(d, i, a) { return function(t) { var p0 = path.getPointAtLength(t0 * l); //previous point var p = path.getPointAtLength(t * l); //current point var angle = Math.atan2(py - p0.y, px - p0.x) * 180 / Math.PI;//angle for tangent t0 = t; //Shifting center to center of arrow // xoffset and yoffset should be half the original width and height var xoffset = 12, yoffset = 12; var centerX = px - xoffset; var centerY = py - yoffset; return "translate(" + centerX + "," + centerY + ")rotate(" + angle + " " + xoffset + " " + yoffset + ")"; }; }; }
 path { fill: none; stroke: #000; stroke-width: 1px; } polygon { fill: steelblue; stroke: #fff; stroke-width: 1px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

d3.js

有幾種方法可以做到這一點。 這是我的解決方案。

首先,如果您想要 10 個箭頭,讓我們創建具有 10 個元素的數據數組:

var arrowData = d3.range(10);

並相應地附加箭頭:

var arrow = svg.selectAll(".arrow")
    .data(arrowData)
    .enter()
    .append("polygon")
    .attr("points", "0,24, 15,12, 0,0");

然后,每一秒,我們都會為不同的箭頭調用transition() ,使用帶有setTimeout的 IIFE:

(function loop() {
    if (counter++ > 8) return;
    setTimeout(function() {
        var thisPolygon = d3.selectAll("polygon").filter(function(d, i) {
            return i == counter;
        });
        transition(thisPolygon);
        loop()
    }, 1000)
}());

為此,我們稍微修改了transition函數:

function transition(elem) {
    elem.transition()
        .duration(10000)
        .ease("linear")
        .attrTween("transform", translateAlong(path.node()))
        .each("end", function() {
            return transition(elem)
        }); 
}

這是您更新的小提琴: https : //jsfiddle.net/3o7vzvfa/ 這是另一個,有 50 個箭頭: https : //jsfiddle.net/buLjg7d3/

這里是 Stack 片段中的相同代碼:

 var points = [ [480, 200], [580, 400], [680, 100], [780, 300], [180, 300], [280, 100], [380, 400] ]; var arrowData = d3.range(10); var svg = d3.select("body").append("svg") .attr("width", 960) .attr("height", 500); var path = svg.append("path") .data([points]) .attr("d", d3.svg.line() .tension(1) // Catmull–Rom .interpolate("linear")); //basis-open var arrow = svg.selectAll(".arrow") .data(arrowData) .enter() .append("polygon") .attr("points", "0,24, 15,12, 0,0"); var counter = -1; (function loop() { if (counter++ > 8) return; setTimeout(function() { var thisPolygon = d3.selectAll("polygon").filter(function(d, i) { return i == counter; }); transition(thisPolygon); loop() }, 1000) }()) function transition(elem) { elem.transition() .duration(10000) .ease("linear") .attrTween("transform", translateAlong(path.node())) .each("end", function() { return transition(elem) }); //infinite loop } // Returns an attrTween for translating along the specified path element. function translateAlong(path) { var l = path.getTotalLength(); var t0 = 0; return function(d, i, a) { return function(t) { var p0 = path.getPointAtLength(t0 * l); //previous point var p = path.getPointAtLength(t * l); //current point var angle = Math.atan2(py - p0.y, px - p0.x) * 180 / Math.PI; //angle for tangent t0 = t; //Shifting center to center of arrow // xoffset and yoffset should be half the original width and height var xoffset = 12, yoffset = 12; var centerX = px - xoffset; var centerY = py - yoffset; return "translate(" + centerX + "," + centerY + ")rotate(" + angle + " " + xoffset + " " + yoffset + ")"; }; }; }
 path { fill: none; stroke: #000; stroke-width: 1px; } polygon { fill: steelblue; stroke: #fff; stroke-width: 1px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM