我对d3.js(和javascript一般来说)是新手,我不知道为什么我的图表在做了一个下拉选择之后没有改变。我相信在下拉选择中选择的值没有达到更新功能。感谢您的帮助。提前谢谢。。。
html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 chart bar with drop down menu</title>
<script type="text/javascript" src="https://d3js.org/d3.v5.min.js"></script>
<style type="text/css">
</style>
</head>
<body>
<div id = "container">
<div id = "dropdown"></div>
<div id = "graph"></div>
<script src ="bar.js"></script>
</div>
</body>
</html>
如前所述,我最好的猜测是有东西没有注册在
unitMenu
对象(应该将新的选择值输入到图形中)。原因是如果我这么做
return console.log("hello, world");
内部
unitMenu.on('change', ...)
控制台上没有显示任何功能。感谢您的帮助:
// margins
var margin = {bottom: 30};
// padding
var padding = 20;
//Width and height
var w = 600;
var h = 250 - margin.bottom;
// create svg
var svg = d3.select("#graph")
.append("svg")
.attr("width", w)
.attr("height", h + margin.bottom);
/* section 2: import csv data and draw elements*/
// import csv data
d3.csv("data.csv").then((data, error) => {
if (error) throw error;
// create objects that "live" outside the function that will create the initial graph...
// formatting the loaded data can live outisde the graph funciton...
//format data
data.forEach((d) => {
d.group = d.group;
d.year = +d.year;
d.value = +d.value;
});
// make an array with the unitoptions for dropdown menu
unitOptions = data.map((a) => a.group).filter((item, i, ar) => {
return ar.indexOf(item) == i;
})
// create dropwdown and populate menu
var unitMenu = d3.select("#dropdown")
.append("select")
.selectAll("option")
.data(unitOptions)
.enter()
.append("option")
.attr("value", (d) => {return d;})
.text((d) => {return d;});
// function for the initial graph
var initialGraph = function(unitSelected) {
var selections = [unitSelected, "BASELINE"];
barData = data.filter(d => {return selections.includes(d.group);})
// bar chart horizontal scale
var xScale = d3.scaleBand()
.domain(d3.range(barData.filter(d => {return d.group == unitSelected;}).length))
.rangeRound([0, w])
.paddingInner(0.05); // padding inner sets the outer padding to the specified value
// bar chart vertical scale
var yScale = d3.scaleLinear()
.domain([0, d3.max(barData, d => {return d.value;})])
.range([padding, h - padding]);
// there is only a bottom axis with the tick labels for the years displayed
var xAxis = d3.axisBottom(xScale)
.tickFormat(function(d,i){return i;})// very important function, tickFormat allow us to relabel ticks...
.tickSize([0,0]); // approximate labels and bars...
// draw bottom axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0, " + (h + margin.bottom * 1/10) + ")")
.style("font-size", "12px")
.call(xAxis)
.selectAll("path, line").remove();
//Create bars
svg.selectAll("rect")
.data(barData.filter(d => {return d.group == unitSelected;}))
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {
return yScale(d.value);
})
.attr("fill", "hotpink");
// add labels to bars
svg.selectAll(".textBar")
.data(barData.filter(d => {return d.group == unitSelected;}))
.enter()
.append("text")
.text(d => {
x = d.value * 100;
x = +x.toFixed(1);
return x + "%";
})
.attr("text-anchor", "middle")
.attr("x", (d, i) => {
return xScale(i) + xScale.bandwidth() / 2;
})
.attr("y", (d) => {
if(h - yScale(d.value) + 0.05*h > h - 0.08*h + 0.05*h){
return h - yScale(d.value) - 0.02*h;
} else {
return h - yScale(d.value) + 0.05*h;
};
})
.attr("font-size", "11px")
.attr("fill", function(d){
if(h - yScale(d.value) + 0.05*h > h - 0.08*h + 0.05*h){
return "black";
} else {
return "white";
};
})
.attr("font-weight", "bold");
// draw comparator
svg.selectAll(".point")
.data(barData.filter(d => {return d.group == "BASELINE";}))
.enter()
.append("path")
.attr("class", "point")
.attr("fill", "steelblue")
.attr("stroke", "black")
.attr("stroke-width", "0.5")
.attr("d", d3.symbol().type(d3.symbolCross))
.attr("transform", function(d, i) {return "translate(" +
(xScale(d.year - 1) + (xScale.bandwidth() / 2)) + "," + (h - yScale(d.value)) + ")";});
};
initialGraph("A");
// function that updates data and graph
var updateGraph = function(unitSelected) {
// filter the data to include only the unit of interest
// selection of baseline and comparator
var selections = [unitSelected, "BASELINE"]; // notice that hte baseline is fixed (for now!!)
// dataset for bars
barData = data.filter(d => {return selections.includes(d.group);})
// update rect
svg.selectAll("rect")
.data(barData.filter(d => {return d.group == unitSelected;}))
.transition()
.duration(1000)
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {
return yScale(d.value);
})
.exit().remove();
// update labels
svg.selectAll(".textBar")
.data(barData.filter(d => {return d.group == unitSelected;}))
.transition()
.duration(1000)
.text(function(d) {
x = d.value * 100;
x = +x.toFixed(1);
return x + "%";
})
.attr("x", function(d, i) {
return xScale(i) + xScale.bandwidth() / 2;
})
.attr("y", function(d) {
if(h - yScale(d.value) + 0.05*h > h - 0.08*h + 0.05*h){
return h - yScale(d.value) - 0.02*h;
} else {
return h - yScale(d.value) + 0.05*h;
};
})
.attr("fill", function(d){
if(h - yScale(d.value) + 0.05*h > h - 0.08*h + 0.05*h){
return "black";
} else {
return "white";
};
});
};
unitMenu.on('change', function() {
// find which unit was selected from the dropdown
var selectedUnit = d3.select(this)
.select("select")
.property("value");
// run update with selected unit
updateGraph(selectedUnit);
});
});
数据:
group,year,value
A,1,0.830798527
A,2,0.14806798
B,1,0.248585574
B,2,0.902224423
C,1,0.386217747
C,2,0.526020182
D,1,0.951627372
D,2,0.936993723
BASELINE,1,0.564061688
BASELINE,2,0.337876435
***更新:已解决***
好吧,我坚持了下来,发现了错误。。。
这个街区。。。
var unitMenu = d3.select("#dropdown")
.append("select")
.selectAll("option")
.data(unitOptions)
.enter()
.append("option")
.attr("value", (d) => {return d;})
.text((d) => {return d;});
应该是。。。
var unitMenu = d3.select("#dropdown")
unitMenu.append("select")
.selectAll("option")
.data(unitOptions)
.enter()
.append("option")
.attr("value", (d) => {return d;})
.text((d) => {return d;});
尽管如此,我还是会投票并检查解释为什么会这样的答案。。。谢谢!!!