【发布时间】:2021-02-23 18:40:50
【问题描述】:
我对 D3 和 JavaScript 比较陌生。我正在尝试在同一页面上插入两个 d3 条形图(d3 版本 6)。这两个条形图的功能基本相同。它们每个都有一个下拉选择器,允许用户过滤可视化数据,以及一个复选框,允许用户对可视化数据进行排序。
目前,两个条形图都将加载,下拉选择器对两者都适用,但切换仅适用于其中一个。我怀疑这与加载两个脚本有关。据我所知,无论哪个脚本最后写在 html 页面上,都会覆盖另一个。此外,如果您选择它然后使用下拉菜单进行排序,但当您取消选中该框时,条形会消失。
代码没有抛出任何错误,但是当您选择切换复选框时,这些条就会消失。我已经运行了 console.logs 来确认正在访问哪些数据,果然,当您选择切换复选框时,您会得到一个空数组。我尝试重命名变量,加载 csv 的副本,以便每个图表引用不同的数据源并尝试放置脚本,但我似乎找不到导致冲突的原因。
我附上我的代码。任何指导将不胜感激。我真的很想弄清楚这一点,我怀疑这会教给我一些重要的东西。提前谢谢你。
我将包含 3 个 sn-ps。
- HTML
- prcpTrends.js
- precipitation.js
下面是一段可以使用的 csv 数据。这是我在这里的第一篇文章,所以我不确定显示这些数据的最佳方法是什么,所以我只是将它粘贴在这里。我想我们会看看这是否有效。
CSV 数据 ...
站、名称、纬度、经度、日期、EMXP、PRCP
USC00381997,"CONWAY, SC US",33.8313,-79.0558,2010,,42.05
USC00381997,"CONWAY, SC US",33.8313,-79.0558,2011,2.65,37.96
USC00381997,"CONWAY, SC US",33.8313,-79.0558,2012,5.95,53.92
USC00381997,"CONWAY, SC US",33.8313,-79.0558,2013,2.65,51.65
US1SCHR0061,"CONWAY 6.2 E, SC US",33.82948,-78.95277,2012,3.53,53.76
US1SCHR0061,"CONWAY 6.2 E, SC US",33.82948,-78.95277,2013,3.21,58.24
US1SCHR0061,"CONWAY 6.2 E, SC US",33.82948,-78.95277,2014,3.69,52.84
US1SCHR0061,"CONWAY 6.2 E, SC US",33.82948,-78.95277,2015,10.82,77.65
US1SCHR0061,"CONWAY 6.2 E, SC US",33.82948,-78.95277,2016,7.49,73.1
US1SCHR0061,"CONWAY 6.2 E, SC US",33.82948,-78.95277,2017,3.01,52.29
US1SCHR0061,"CONWAY 6.2 E, SC US",33.82948,-78.95277,2018,6.4,67.57
US1SCHR0061,"CONWAY 6.2 E, SC US",33.82948,-78.95277,2019,4.31,48.8
US1SCHR0061,"CONWAY 6.2 E, SC US",33.82948,-78.95277,2020,4.57,72.44
US1SCHR0010,"MYRTLE BEACH 8.6 SW, SC US",33.6192,-79.0145,2012,3.21,47.08
US1SCHR0010,"MYRTLE BEACH 8.6 SW, SC US",33.6192,-79.0145,2014,3.71,66.72
US1SCHR0010,"MYRTLE BEACH 8.6 SW, SC US",33.6192,-79.0145,2015,7.05,72.65
US1SCHR0076,"美特尔海滩 9.1 WSW, SC US",33.646118,-79.036631,2015,8.04,71.29
US1SCHR0076,"美特尔海滩 9.1 WSW, SC US",33.646118,-79.036631,2016,8.41,69.54
US1SCHR0033,"LORIS 2.9 WSW, SC US",34.037885,-78.935069,2012,3.39,54.93
US1SCHR0033,"LORIS 2.9 WSW, SC US",34.037885,-78.935069,2013,3.4,63.96
US1SCHR0033,"LORIS 2.9 WSW, SC US",34.037885,-78.935069,2015,3.73,60.56
US1SCHR0033,"LORIS 2.9 WSW, SC US",34.037885,-78.935069,2016,6.97,61.37
US1SCHR0033,"LORIS 2.9 WSW, SC US",34.037885,-78.935069,2017,3.09,56.54
US1SCHR0066,"美特尔海滩 9.2 WSW, SC US",33.623648,-79.025797,2014,3.08,64.24
US1SCHR0066,"美特尔海滩 9.2 WSW, SC US",33.623648,-79.025797,2020,3.95,66.58
US1SCHR0063,"MURRELLS INLET 1.7 N, SC US",33.578576,-79.045388,2013,4.19,50.72
US1SCHR0063,"MURRELLS INLET 1.7 N, SC US",33.578576,-79.045388,2014,3.46,62.16
US1SCHR0063,"MURRELLS INLET 1.7 N, SC US",33.578576,-79.045388,2018,3.63,54.76
US1SCHR0063,"MURRELLS INLET 1.7 N, SC US",33.578576,-79.045388,2020,4,70.33
US1SCHR0064,"MYRTLE BEACH 2.4 ENE, SC US",33.715721,-78.855623,2015,9.35,69.26
US1SCHR0064,"MYRTLE BEACH 2.4 ENE, SC US",33.715721,-78.855623,2017,2.76,45.67
US1SCHR0075,"美特尔海滩 7.4 NNW, SC US",33.790506,-78.957247,2014,3.14,51.79
US1SCHR0075,"美特尔海滩 7.4 NNW, SC US",33.790506,-78.957247,2015,8.42,87.71
US1SCHR0075,"MYRTLE BEACH 7.4 NNW, SC US",33.790506,-78.957247,2019,4.51,54.74
US1SCHR0075,"美特尔海滩 7.4 NNW, SC US",33.790506,-78.957247,2020,3.62,74.55
US1SCHR0014,"MURRELLS INLET 4.0 NE, SC US",33.5994932,-79.0065316,2013,3.79,48.06
US1SCHR0014,"MURRELLS INLET 4.0 NE, SC US",33.5994932,-79.0065316,2014,3.32,59.28
US1SCHR0014,"MURRELLS INLET 4.0 NE, SC US",33.5994932,-79.0065316,2016,10,60.14
US1SCHR0014,"MURRELLS INLET 4.0 NE, SC US",33.5994932,-79.0065316,2017,4.04,47.89
US1SCHR0014,"MURRELLS INLET 4.0 NE, SC US",33.5994932,-79.0065316,2019,6.15,51.88
US1SCHR0014,"MURRELLS INLET 4.0 NE, SC US",33.5994932,-79.0065316,2020,4.49,65.3
US1SCHR0046,"MYRTLE BEACH 5.0 WNW, SC US",33.72668,-78.9728839,2012,2.85,39.44
US1SCHR0046,"MYRTLE BEACH 5.0 WNW, SC US",33.72668,-78.9728839,2013,4.48,52.29
US1SCHR0046,"MYRTLE BEACH 5.0 WNW, SC US",33.72668,-78.9728839,2014,3.51,53.09
US1SCHR0046,"MYRTLE BEACH 5.0 WNW, SC US",33.72668,-78.9728839,2015,9.55,72.26
US1SCHR0046,"MYRTLE BEACH 5.0 WNW, SC US",33.72668,-78.9728839,2016,6.78,68.54
US1SCHR0046,"MYRTLE BEACH 5.0 WNW, SC US",33.72668,-78.9728839,2017,3.25,47.37
US1SCHR0046,"MYRTLE BEACH 5.0 WNW, SC US",33.72668,-78.9728839,2019,5.63,57.22
US1SCHR0106,"MYRTLE BEACH 4.8 NNW, SC US",33.76386,-78.91961,2019,4.94,53.29
US1SCHR0106,"MYRTLE BEACH 4.8 NNW, SC US",33.76386,-78.91961,2020,4.95,76.84
US1SCHR0019,"LORIS 1.4 ENE, SC US",34.067521,-78.868929,2016,5.08,59.64
US1SCHR0019,"LORIS 1.4 ENE, SC US",34.067521,-78.868929,2018,11,73.78
USW00093718,"北默特尔比奇, SC US",33.81619,-78.72048,2010,2.72,41.91
USW00093718,"北默特尔比奇, SC US",33.81619,-78.72048,2011,2.04,33.5
USW00093718,"北默特尔比奇, SC US",33.81619,-78.72048,2012,1.96,39.27
USW00093718,"北默特尔比奇, SC US",33.81619,-78.72048,2013,3.25,48.59
USW00093718,"北默特尔比奇, SC US",33.81619,-78.72048,2014,2.25,41.01
USW00093718,"北默特尔比奇, SC US",33.81619,-78.72048,2015,7.88,64.87
USW00093718,"北默特尔比奇, SC US",33.81619,-78.72048,2016,8.9,56.26
USW00093718,"北默特尔比奇, SC US",33.81619,-78.72048,2017,3.73,49.13
USW00093718,"北默特尔比奇, SC US",33.81619,-78.72048,2018,5.71,68.53
USW00093718,"北默特尔比奇, SC US",33.81619,-78.72048,2019,10.39,56.02
USW00093718,"北默特尔比奇, SC US",33.81619,-78.72048,2020,4.12,55.72
/* ../static/precipitation.js */
d3.csv("/static/Horry_County_Precipitation.csv").then(d => chartTrend(d));
function chartTrend(csv) {
csv.forEach(function(d) {
d.DATE = d.DATE;
d.PRCP = +d.PRCP;
return d;
})
const weatherStation = csv
.map((a) => a.NAME)
.filter((value, index, self) => self.indexOf(value) === index);
weatherStation.sort(function(a, b) {
return b - a;
});
console.log(weatherStation)
d3
.select("#weatherStation")
.selectAll("option")
.data(weatherStation)
.enter()
.append("option")
.text((d) => d);
var svg = d3.select("#prcpTrends"),
margin = {
top: 70,
right: -35,
bottom: 50,
left: 110
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
// Setting x Scale
const x = d3
.scaleBand()
.range([margin.left, width - margin.right])
.padding(0.1)
.paddingOuter(0.2);
var y = d3.scaleLinear().range([height - margin.bottom, margin.top]);
var colorScale = d3.scaleOrdinal()
.range(["#ed5151", "#149ece", "#3caf99", "#004c73", "#fc921f", "#a8a800", "#f789d8", "#732600", "#ff00c5", "#9e559c", "#a7c636", "#7f7f7f", "#6b6bd6", "#a87000"]);
var xAxis = (g) =>
g
.attr("transform", "translate(0," + (height - margin.bottom) + ")")
.call(d3.axisBottom(x).tickSizeOuter(0))
.selectAll('text')
.attr("y", 10)
.attr("x", 0)
// .attr("dy", ".35em")
// .attr("transform", "rotate(60)")
// .style("text-anchor", "start");
var yAxis = (g) =>
g
.attr("transform", "translate(" + margin.left + ",0)")
.call(d3.axisLeft(y)
.ticks(5)
.tickSize(-width));
svg.append("g").attr("class", "x-axis");
svg
.append("g")
.attr("class", "y-axis")
.append("text")
.attr("class", "yAxisPRCP")
.attr("y", -30)
.attr("x", -85)
.attr("transform", `rotate(-90)`)
// .attr("fill", "#635f5d")
// .style("font-size", "2.5em")
.text("Precipitation (in)");
svg
.append("text")
.attr("y", 40)
.attr("x", 185)
.attr("class", "title")
.text("Weather Station Precipitation Totals");
update(d3.select("#weatherStation").property("value"), 0);
function update(name, speed) {
var data = csv.filter(d => d.NAME == name);
console.log(data)
y.domain([0, d3.max(data, (d) => d.PRCP)]).nice();
svg.selectAll(".y-axis").transition().duration(speed).call(yAxis);
data.sort(
d3.select("#sortPRCP").property("checked") ?
(a, b) => b.PRCP - a.PRCP :
(a, b) => a.NAME - b.NAME
);
x.domain(data.map((d) => d.DATE));
svg.selectAll(".x-axis").transition().duration(speed).call(xAxis);
var bar = svg.selectAll(".bar").data(data, (d) => d.DATE);
bar.exit().remove();
var bar1 = bar
.enter()
.append("rect")
.attr("class", "bar")
.style("fill", "#149ece")
.attr("opacity", ".5")
.attr("width", x.bandwidth())
.attr("height", (d) => y(0) - y(d.PRCP));
bar1
.merge(bar)
.transition()
.duration(speed)
.attr("x", (d) => x(d.DATE))
.attr("y", (d) => y(d.PRCP))
.attr("width", x.bandwidth())
.attr("height", (d) => y(0) - y(d.PRCP));
// Adding Tooltip Behavior
bar1
.on("mouseover", function(event, d) {
d3.select(this).style("fill", "#ebe028");
d3.select("#stationName").text(" " + d.NAME)
d3.select("#annualPrecipitationTrends").text(" " + d.PRCP + " inches");
//Position the tooltip <div> and set its content
let x = event.pageX - 500;
let y = event.pageY - 1000;
//Position tooltip and make it visible
d3.select("#tooltipTrends")
.style("left", x + "px")
.style("top", y + "px")
.style("opacity", 1);
})
.on("mouseout", function() {
d3.select(this).style("fill", "#149ece");
//Hide the tooltip
d3.select("#tooltipTrends").style("opacity", "0");
});
}
chartTrend.update = update;
}
var select = d3
.select("#weatherStation")
.style("border-radius", "5px")
.on("change", function() {
chartTrend.update(this.value, 750);
});
var checkbox = d3
.select("#sortPRCP")
.style("margin-left", "1%")
.on("click", function() {
chartTrend.update(select.property("value"), 750);
});
/* ../static/prcpTrends.js */
d3.csv("/static/Horry_County_Precipitation.csv").then(d => chart(d));
function chart(csv) {
csv.forEach(function(d) {
d.DATE = d.DATE;
d.PRCP = +d.PRCP;
return d;
})
const years = csv
.map((a) => a.DATE)
.filter((value, index, self) => self.indexOf(value) === index);
years.sort(function(a, b) {
return b - a;
});
// console.log(years)
d3
.select("#year")
.selectAll("option")
.data(years)
.enter()
.append("option")
.text((d) => d);
var svg = d3.select("#precipitation_barchart"),
margin = {
top: 70,
right: -35,
bottom: 50,
left: 110
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
// Setting x Scale
const x = d3
.scaleBand()
.range([margin.left, width - margin.right])
.padding(0.1)
.paddingOuter(0.2);
var y = d3.scaleLinear().range([height - margin.bottom, margin.top]);
var colorScale = d3.scaleOrdinal()
.range(["#ed5151", "#149ece", "#3caf99", "#004c73", "#fc921f", "#a8a800", "#f789d8", "#732600", "#ff00c5", "#9e559c", "#a7c636", "#7f7f7f", "#6b6bd6", "#a87000"]);
var xAxis = (g) =>
g
.attr("transform", "translate(0," + (height - margin.bottom) + ")")
.call(d3.axisBottom(x).tickSizeOuter(0))
.selectAll('text')
.attr("y", 0)
.attr("x", 9)
.attr("dy", ".35em")
.attr("transform", "rotate(60)")
.style("text-anchor", "start");
var yAxis = (g) =>
g
.attr("transform", "translate(" + margin.left + ",0)")
.call(d3.axisLeft(y)
.ticks(5)
.tickSize(-width));
svg.append("g").attr("class", "x-axis");
svg
.append("g")
.attr("class", "y-axis")
.append("text")
.attr("class", "yAxisPRCP")
.attr("y", -30)
.attr("x", -85)
.attr("transform", `rotate(-90)`)
// .attr("fill", "#635f5d")
// .style("font-size", "2.5em")
.text("Precipitation (in)");
svg
.append("text")
.attr("y", 35)
.attr("x", 270)
.attr("class", "title")
.text("Annual Precipitation Totals");
update(d3.select("#year").property("value"), 0);
function update(year, speed) {
var data = csv.filter(d => d.DATE == year);
// console.log(data)
y.domain([0, d3.max(data, (d) => d.PRCP)]).nice();
svg.selectAll(".y-axis").transition().duration(speed).call(yAxis);
data.sort(
d3.select("#sort").property("checked") ?
(a, b) => b.PRCP - a.PRCP :
(a, b) => a.NAME - b.NAME
);
x.domain(data.map((d) => d.NAME));
svg.selectAll(".x-axis").transition().duration(speed).call(xAxis);
var bar = svg.selectAll(".bar").data(data, (d) => d.NAME);
bar.exit().remove();
var bar1 = bar
.enter()
.append("rect")
.attr("class", "bar")
.style("fill", function(d) {
return colorScale(d.NAME);
})
.attr("opacity", ".5")
.attr("width", x.bandwidth())
.attr("height", (d) => y(0) - y(d.PRCP));
bar1
.merge(bar)
.transition()
.duration(speed)
.attr("x", (d) => x(d.NAME))
.attr("y", (d) => y(d.PRCP))
.attr("width", x.bandwidth())
.attr("height", (d) => y(0) - y(d.PRCP));
// Adding Tooltip Behavior
bar1
.on("mouseover", function(event, d) {
d3.select(this).style("fill", "#ebe028");
d3.select("#stationName").text(" " + d.NAME)
d3.select("#annualPrecipitation").text(" " + d.PRCP + " inches");
//Position the tooltip <div> and set its content
let x = event.pageX - 1100;
let y = event.pageY - 1000;
//Position tooltip and make it visible
d3.select("#tooltip")
.style("left", x + "px")
.style("top", y + "px")
.style("opacity", 1);
})
.on("mouseout", function() {
d3.select(this).style("fill", function(d) {
return colorScale(d.NAME);
});
//Hide the tooltip
d3.select("#tooltip").style("opacity", "0");
});
}
chart.update = update;
}
var select = d3
.select("#year")
.style("border-radius", "5px")
.on("change", function() {
chart.update(this.value, 750);
});
var checkbox = d3
.select("#sort")
.style("margin-left", "30%")
.on("click", function() {
chart.update(select.property("value"), 750);
});
<!--HTML code for bar charts in question. -->
<!-- Start precipitation by weather station bar chart -->
<div class="row">
<div id="precipitationVisualization" class="col-md-6 col-sm-6 mb-4">
Choose Weather Station:
<select id="weatherStation"></select>
<input type="checkbox" id="sortPRCP"> Toggle sort by Precipitation Volume
<div class="row">
<svg id="prcpTrends" width="768" height="400"></svg>
<div id="tooltipTrends">
<!-- Station Name:<span id="stationName" class="info"></span><br> -->
Annual Precipitation:<span id="annualPrecipitationTrends" class="info"></span><br>
</div>
</div>
</div>
<!-- Start precipitation by year bar chart -->
<div id="precipitationVisualization" class="col-md-6 col-sm-6 mb-4">
Choose year:
<select id="year"></select>
<input type="checkbox" id="sort"> Toggle sort by Precipitation Volume
<div class="row">
<svg id="precipitation_barchart" width="768" height="400"></svg>
<div id="tooltip">
<!-- Station Name:<span id="stationName" class="info"></span><br> -->
Annual Precipitation:<span id="annualPrecipitation" class="info"></span><br>
</div>
</div>
</div>
</div>
<script src="../static/d3.js"></script>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="https://d3js.org/d3-scale.v3.min.js" defer></script>
<script src="https://d3js.org/d3-axis.v1.min.js" defer></script>
<!--
<script src="../static/precipitation.js"></script>
<script src="../static/prcpTrends.js"></script>
-->
【问题讨论】:
-
所以,我已将您的三个 sn-ps 合并为一个,但您的 d3 脚本引用了 Stack Overflow 服务器上显然不存在的 CSV 文件。如果您可以将数据(可能更少)作为内联数据包含到 d3 中(对不起,我无论如何都不是 d3 专家),这将有助于使脚本运行得更干净。
-
谢谢邪猴。这是我第一次在这里发布问题,所以我不是 100% 确定它是如何工作的,但我将一段 CSV 数据复制并粘贴到我的邮件正文中。我不确定这是否正确。让我知道是否需要以另一种方式执行此操作。再次感谢。
标签: javascript html d3.js