【问题标题】:How to update text in area chart when I change csv file on click in d3?当我在 d3 中单击更改 csv 文件时如何更新面积图中的文本?
【发布时间】:2014-07-17 17:30:14
【问题描述】:

我是 D3 的初学者。我制作了通过单击更改 csv 文件时更新的面积图。问题只是文本。新文本出现时旧文本不会删除。

这是带有更新功能的代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" >
<title>Otroška imena</title>
<script src="D3/d3.js"></script>
<script src="D3/d3.layout.cloud.js"></script>

<!-- Style -->
<link rel="stylesheet" type="text/css" href="mystyle.css">

</head>
<body>
<div id="option">
    <input type="button"value="Adam"onclick="zamenjaj(value)" />
    <input type="button"value="Aljaž"onclick="zamenjaj(value)" />
    <input type="button"value="Sara"onclick="zamenjaj(value)" />
</div>

<!-- JavaScript -->
<script>
window.funkcija1 = function(x){zamenjaj(x.value);}

//Dimensions of canvas
    var margin = {top: 20, right: 30, bottom: 30, left: 40},
width = 700 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;

// Set the ranges
var x = d3.scale.linear().range([0, width]);
var y = d3.scale.linear().range([height, 0]);

// Define the axes
var xAxis = d3.svg.axis().scale(x).orient("bottom").tickFormat(d3.format("d"));
var yAxis = d3.svg.axis().scale(y).orient("left").ticks(5);

//Area
var area = d3.svg.area()
    .interpolate("monotone")
    .x(function(d) { return x(d.leto); })
    .y0(height)
    .y1(function(d) { return y(d.st); });

// Line
var valueline = d3.svg.line()
.interpolate("monotone")
.x(function(d) { return x(d.leto); })
.y(function(d) { return y(d.st); });


//SVG canvas
var svg = d3.select("body")
    .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
    .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// y grid lines
function make_y_axis() {return d3.svg.axis().scale(y).orient("left").ticks(5)}      

//**DATA**
d3.csv("Imena/Adam.csv",function(error, podatki) {
podatki.forEach(function(d) {d.st = +d.st;  });

// Compute the minimum and maximum
x.domain(d3.extent(podatki,function(d) { return d.leto; }));
y.domain([0, d3.max(podatki, function(d) { return d.st; })]);

// Add the filled area
svg.append("path")
    .attr("class", "area")
    .attr("d", area(podatki));

// Add the valueline path.
svg.append("path")      // Add the valueline path.
    .attr("class", "line")
    .attr("d", valueline(podatki));

// Draw the Y Grid lines
svg.append("g")         
    .attr("class", "grid")
    .call(make_y_axis().tickSize(-width, 0, 0).tickFormat(""))

// Add the X Axis
svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

// Add the Y Axis
svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Stevilo");

    podatki.splice(1,20);   

    var napis = svg.selectAll().data(podatki).enter().append("text")
    napis
        .text(function(d){return d["ime"]})
        .attr("class","graftext")
        .attr("y",50).attr("x",50);
});

// ** Update podatki section (Called from the onclick)
function zamenjaj(ime_s) {

    // Get the podatki again
    d3.csv("Imena/" + ime_s + ".csv",function(error, podatki) {
    podatki.forEach(function(d) {
        d.st = +d.st;});

    // Select the section we want to apply our changes to
    var svgUpdate = d3.select("body").transition();

    // Scale the range of the data again 
    y.domain([0, d3.max(podatki, function(d) { return d.st; })]);

    // Make the changes
    svgUpdate.select(".area")
        .duration(750)
        .attr("d", area(podatki));
    svgUpdate.select(".line")   // change the line
        .duration(750)
        .attr("d", valueline(podatki));
    svgUpdate.select(".y.axis") // change the y axis
        .duration(750)
        .call(yAxis);  

    podatki.splice(1,20);   

    var napisUpdate = svg.selectAll(".text").data(podatki);
    napisUpdate.exit().remove();
    napisUpdate.enter().append("text")
        .text(function(d){return d["ime"]})
        .attr("class","graftext")
        .attr("y",80).attr("x",50).duration(750);
    });
}
</script>
</body>
</html>

这些页面帮助了我:thisthis 但不幸的是它对我不起作用。感谢您的帮助。

【问题讨论】:

  • 看起来应该可以了。您能否提供一个完整的示例来演示该问题?
  • 为什么要在更新文本之前从数据中拼接出 20 项?
  • Lars,我添加了其余代码。
  • jshanley,我使用了 splice,因为我制作了这样的 csv 文件,每行中用于写入 21 次的文本的元素在哪里。但我需要它只写一次。是的,这很愚蠢,但我没有找到更好的解决方案。我不知道是否可以在csv文件的一行中写入元素。
  • 我相信您需要在添加新文本之前清理 d3 数据对象。类似 d3.select(element).selectAll(chldElements).data(newDataset)

标签: csv text d3.js charts area


【解决方案1】:

您正在使用.text 类选择文本元素,但是当您在.enter() 选择中创建文本元素时,您将给它们一个.graftext 类。您需要为新元素使用与选择时相同的类,否则在计算数据连接时,它会认为您需要所有新元素,因为选择是空的。

试试这样:

// selects all elements with class of `graftext` and joins the data
var napisUpdate = svg.selectAll(".graftext").data(podatki);
  // remove excess elements for which there is no data 
  napisUpdate.exit().remove();
  // create new elements for each excess datapoint
  napisUpdate.enter().append("text")
    .attr("class","graftext")
    .attr("y",80).attr("x",50).duration(750);
  });
  // update existing elements with the new information
  napisUpdate.text(function(d){return d["ime"]});

【讨论】:

  • 谢谢,但不起作用。新文本未显示,旧文本仍在此处。
  • 也摆脱了无关的.duration() 调用。在选择之前调用 .duration 而不直接在其前面加上 .transition() 是没有意义的,并且它可能会因为调用 undefined 作为函数而引发各种错误。
  • 我解决了这个问题。你的回答也很有用。谢谢!我想给你点有用的解决方案,但我还没有足够的声誉。
【解决方案2】:

几个小时后,我解决了这个问题。我改变了一些东西,它的工作原理:

svg.append('text')
    .data(podatki)
    .attr('x', 30)
    .attr('y', 50)
    .attr("class","graftext")
    .text(function(d) { return d.ime })

在更新功能中:

podatki.splice(1,20);   
var svgUpdate = d3.select(".graftext").data(podatki);   
svgUpdate.exit().remove();
svgUpdate.enter().append("text");
svgUpdate.text(function(d) { return d.ime });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-07
    • 2021-04-18
    • 1970-01-01
    • 2022-12-15
    • 2021-07-31
    • 1970-01-01
    • 2018-08-08
    • 2023-02-17
    相关资源
    最近更新 更多