簡體   English   中英

d3 v4折線圖過渡不起作用

[英]d3 v4 line chart transition not working

我希望我的線條像這樣的例子:

https://bl.ocks.org/shimizu/f7ef798894427a99efe5e173e003260d

下面的代碼沒有進行任何轉換,只顯示圖表。

我知道瀏覽器緩存,這不是問題。 我也試過改變持續時間,這也無濟於事。 我覺得我可能沒有明確表示我希望d3如何轉換,但我不確定如何給d3它想要的東西。 非常感謝您的幫助。

編輯:x軸域:[0,1]。 y軸域:[ - 18600,-3300]。

// Here's just a few rows of the data
data = [{"threshold": 0.0, "loss": -18600},
        {"threshold": 0.008571428571428572, "loss": -18600},
        {"threshold": 0.017142857142857144, "loss": -18600}]

var svg = d3.select("svg"),
    margin = {top: 20, right: 20, bottom: 30, left: 20},
    width = +svg.attr("width") - 400 - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom;


var x = d3.scaleLinear()
    .range([0, width]);

var y = d3.scaleLinear()
    .range([0, height]);

var line = d3.line()
    .x(d => x(d.threshold))
    .y(d => y(d.loss));

var g = svg.append("g")
    .attr("transform", "translate(" + (margin.left + 50) + "," + margin.top + ")");

d3.json("static/data/thresh_losses.json", function(thisData) {
 draw(thisData);
});

let draw = function(data) {
    $("svg").empty()
    var x = d3.scaleLinear()
        .range([0, width]);

    var y = d3.scaleLinear()
        .range([0, height]);

    var line = d3.line()
        .x(d => x(d.threshold))
        .y(d => y(d.loss));

    var g = svg.append("g")
        .attr("transform", "translate(" + (margin.left + 50) + "," + margin.top + ")");

    d3.selectAll("g").transition().duration(3000).ease(d3.easeLinear);

    x.domain([0, d3.max(data, d => d.threshold)]);
    y.domain([d3.max(data, d => d.loss), d3.min(data, d => d.loss)]);

    g.append("g")
        .attr("class", "axis axis--x")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x))
        .append("text")
        .attr("class", "axis-title")
        .attr("y", 18)
        .attr("dy", "1em")
        .attr("x", (height/2) - 40)
        .attr("dx", "1em")
        .style("text-anchor", "start")
        .attr("fill", "#5D6971")
        .text("Threshold");

    g.append("g")
        .attr("class", "axis axis--y")
        .call(d3.axisLeft(y))
        .append("text")
       .attr("class", "axis-title")
       .attr("transform", "rotate(-90)")
       .attr("y", -40)
       .attr("dy", ".71em")
       .attr("x", -height/2 + 40)
       .attr("dx", ".71em")
       .style("text-anchor", "end")
       .attr("fill", "#5D6971")
       .text("Profit ($)");

    var line_stuff = g.selectAll(".line")
        .data([data]);

    line_stuff.enter().append("path").classed("line", true)
           .merge(line_stuff);

    g.selectAll(".line")
      .transition()
      .duration(10000)
      .ease(d3.easeLinear)
      .attr("d", line);
};

D3文檔

要應用轉換,請選擇元素,調用選擇 .transition ,然后進行所需的更改。

我在代碼中發現了這個:

d3.selectAll("g").transition().duration(3000).ease(d3.easeLinear);

這不會動畫任何東西,因為最后沒有.attr().style() - 沒有“期望的變化”。 這是一個沒有變化的過渡。

現在,讓我們來看看:

g.selectAll(".line")
  .transition()
  .duration(10000)
  .ease(d3.easeLinear)
  .attr("d", line);

這幾乎滿足了要求。 它選擇.line ,創建轉換(並自定義),並設置d屬性。 如果您d設置在其他地方,那么這將要被空其所有的數據轉換的路徑,只...

D3不會以這種方式轉換字符串。 在首先檢查屬性是數字還是顏色之后 ,D3開始使用名為interpolateString東西。 您認為interpolateString會將字符從a更改為ababc ,但實際上,它所做的只是查找字符串中的數字,然后插入這些數字,使字符串的其余部分保持不變 結果是,除非你自己動手,否則你無法動畫像d一樣的字符串從空到動畫。

以下是使用attrTween (注意:不是一個好主意)

.attrTween("d", function() {
  return function(t) {
    const l = line(data);
    return l.substring(0, Math.ceil(l.length * t));
  };
})

這實際上將在沒有文本到d屬性的整個文本之間轉換。 但是,由於SVG路徑的工作方式,這看起來不太好。

還有另一種方式,如您鏈接的示例( Ryan Morton評論中也提到)中所示: 轉換stroke-dashoffset 這是你如何做到這一點:

line_stuff.enter().append("path").classed("line", true)
  .merge(line_stuff)
  .attr('d', line)
  .attr("fill", "none")
  .attr("stroke", "black")
  .attr("stroke-dasharray", function(d) {
    return this.getTotalLength()
  })
  .attr("stroke-dashoffset", function(d) {
    return this.getTotalLength()
  });

g.selectAll(".line")
  .transition()
  .duration(10000)
  .ease(d3.easeLinear)
  .attr("stroke-dashoffset", 0);

基本上,第一部分告訴D3:

  • 創建線,使填充不可見(所以你可以看到線)
  • 使筆划破折號等於該行的總長度
  • 偏移破折號,以便在開始時完全隱藏該行

下一部分設置轉換並告訴它將偏移轉換為0(此時該線將完全可見,因為每個破折號與線本身的長度相同)。

如果要轉換填充,可以將.attr("fill", "none")更改為.attr("fill", "#fff") ,然后執行以下操作:

g.selectAll(".line")
  .transition()
  .delay(10000)
  .duration(2000)
  .ease(d3.easeLinear)
  .attr('fill', '#000');

這將使用.delay()等待第一次轉換完成,然后將背景從白色更改為黑色。 請注意, 不透明度可能更適合為性能設置動畫

暫無
暫無

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

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