gpt4 book ai didi

javascript - 如何使用带有更新模式的过滤方法?

转载 作者:行者123 更新时间:2023-11-30 11:13:58 25 4
gpt4 key购买 nike

在我下面的代码片段中,我使用以下过滤方法来获取所需的数据:

var data = csv.filter(d => d.date.includes(year))

这里的问题是,每当我更新图表时,每个条形图都会从顶部重新绘制,而不是从以前的数据更新。

这是因为我在我的更新函数中重新声明了 data 变量,因此它没有从以前的数据更新吗?

有没有一种简单的方法可以解决这个问题,或者我是否必须每年在一个新的数据数组中重新映射和分离,并以此作为我的更新模式的基础?

代码如下:

var csvData = `date,value
2018-jan,100
2018-feb,75
2018-mar,45
2018-apr,65
2019-jan,21
2019-feb,43
2019-mar,55
2019-apr,33`;

var csv = d3.csvParse(csvData, d => d)

var margin = {top: 25, bottom: 25, left: 25, right: 25};

var svg = d3.select("#chart"),
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;

var x = d3.scaleBand()
.range([margin.left, width - margin.right])
.padding(0.1)
.paddingOuter(0.2)

var xAxis = g => g
.attr("transform", "translate(0," + (height - margin.bottom) + ")")
.call(d3.axisBottom(x).tickSizeOuter(0))

svg.append("g")
.attr("class", "x-axis")

var y = d3.scaleLinear()
.range([height - margin.bottom, margin.top])

update("2018")

function update(year) {

var data = csv.filter(d => d.date.includes(year))

y.domain([0, d3.max(data, d => Math.max(d.value))])

x.domain(data.map(d => d.date))

svg.selectAll(".x-axis")
.call(xAxis);

var bar = svg.selectAll(".bar")
.data(data, d => d.date)

bar.exit().remove();

bar = bar
.enter()
.append("rect")
.attr("class", "bar")
.attr("fill", "steelblue")
.attr("width", x.bandwidth())
.attr("x", d => x(d.date))
.merge(bar)
.transition().duration(750)
.attr("y", d => y(d.value))
.attr("height", d => y(0) - y(d.value))
}

d3.select("#year").on("change", function() {
update(this.value)
})
body {
padding-top: 25px;
margin: auto;
width: 450px;
font: 11px arial;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
Choose year
<select id="year">
<option value="2018">2018</option>
<option value="2019">2019</option>
</select><br>

<svg id="chart" width="450" height="200"></svg>

最佳答案

这里的问题与过滤数据、重新分配变量、合并选择或问题和评论中提到的任何其他问题无关。

这里的问题只是key function .当您指定键函数时,每个元素的数据根据​​其字符串标识符进行绑定(bind)。而且,由于日期不同,预期的行为是应该删除条形并绘制新的条形。

您想要的是按索引连接的行为。所以,改变你的数据方法......

.data(data, d => d.date)

..至:

.data(data)

这是您的代码,仅进行了更改:

var csvData = `date,value
2018-jan,100
2018-feb,75
2018-mar,45
2018-apr,65
2019-jan,21
2019-feb,43
2019-mar,55
2019-apr,33`;

var csv = d3.csvParse(csvData, d => d)

var margin = {top: 25, bottom: 25, left: 25, right: 25};

var svg = d3.select("#chart"),
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;

var x = d3.scaleBand()
.range([margin.left, width - margin.right])
.padding(0.1)
.paddingOuter(0.2)

var xAxis = g => g
.attr("transform", "translate(0," + (height - margin.bottom) + ")")
.call(d3.axisBottom(x).tickSizeOuter(0))

svg.append("g")
.attr("class", "x-axis")

var y = d3.scaleLinear()
.range([height - margin.bottom, margin.top])

update("2018")

function update(year) {

var data = csv.filter(d => d.date.includes(year))

y.domain([0, d3.max(data, d => Math.max(d.value))])

x.domain(data.map(d => d.date))

svg.selectAll(".x-axis")
.call(xAxis);

var bar = svg.selectAll(".bar")
.data(data)

bar.exit().remove();

bar = bar
.enter()
.append("rect")
.attr("class", "bar")
.attr("fill", "steelblue")
.attr("width", x.bandwidth())
.attr("x", d => x(d.date))
.merge(bar)
.transition().duration(750)
.attr("y", d => y(d.value))
.attr("height", d => y(0) - y(d.value))
}

d3.select("#year").on("change", function() {
update(this.value)
})
body {
padding-top: 25px;
margin: auto;
width: 450px;
font: 11px arial;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
Choose year
<select id="year">
<option value="2018">2018</option>
<option value="2019">2019</option>
</select><br>

<svg id="chart" width="450" height="200"></svg>

关于javascript - 如何使用带有更新模式的过滤方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52413766/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com