我有两个函数,每个函数应该从同一个数据集中绘制两个ID分别为 one 和 two 的SVG的图表。
我创建了不同的变量以将图表附加到其相应的SVG:
var svg1 = d3.select("#one")
var svg2 = d3.select("#two")
问题在于为第二个SVG绘制图表的功能会覆盖两个图表。
如果分别运行每个功能,则可以看到图表正确返回。 (注释每个函数调用,以查看另一个图表中被覆盖的数据)
<html>
<body>
<svg id="one"></svg>
<svg id="two"></svg>
<script>
// variables we'll be filtering by
var quantile;
var amount;
var type;
var risk;
w = window.innerWidth;
h = window.innerHeight;
// <-- Make Selection -->
// Possible values --
// quantile: [1 2 3 4]
// variable: ['Income' 'Payments' 'Consumption' 'Utility']
// amount: [ 5000 30000 70000]
// type: ['Loan' 'ISA']
// risk: [1 2 3 4]
quantile = 1;
amount=5000;
type = 'Loan';
risk = 2;
getFirst();
getSecond();
function getFirst() {
variable= 'Income';
// chart stuff
margin = {top: h/4, right: w/4, bottom: h/4, left: w/4},
width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight - margin.top - margin.bottom;
x = d3.scaleLinear()
.rangeRound([0, width]);
y = d3.scaleLinear()
.rangeRound([height,0]);
valueline = d3.line()
.x(function(d) { return x(d.key); })
.y(function(d) { return y(d.value); });
var svg1 = d3.select("#one")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// data
d3.csv("https://raw.githubusercontent.com/JainFamilyInstitute/isa-app/master/data/data_vis.csv?token=AXiiVXcAwXZjLK4-3tiyxKwj8yaVMVDmks5b6b8NwA%3D%3D", function(error, data) {
if (error) throw error;
// filter by selection
data = data.filter(function(d) {
return (d.quantile == quantile) &
(d.variable == variable) &
(d.amount == amount) &
(d.type == type) &
(d.risk == risk) });
// create visualizable array with only ages and amounts for selected series
data_filtered = data.map(({ quantile,amount,risk,type,variable, ...item }) => item);
data_vis = data_filtered[0];
console.log(data_vis);
result = [];
for(i=22;i<101;i++){
key = i;
value =parseFloat(data_vis[i]);
result.push({
key: key,
value: value
});
}
// console.log(data_vis);
console.log(result);
// Scale the range of the data
x.domain([d3.min(result, function(d) { return d.key; }), d3.max(result, function(d) { return d.key; })]);
y.domain([0, d3.max(result, function(d) { return d.value; })]);
// Add the valueline path.
svg1.append("path")
.data([result])
.attr("class", "line")
.attr("d", valueline);
// Add the X Axis
svg1.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add the Y Axis
function y_grid_lines() {
return d3.axisLeft(y)
}
svg1.append("g")
.attr("class", "grid")
.call(y_grid_lines()
.tickSize(-width)
);
});
}
function getSecond() {
variable= 'Payments';
// chart stuff
margin = {top: h/4, right: w/4, bottom: h/4, left: w/4},
width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight - margin.top - margin.bottom;
x = d3.scaleLinear()
.rangeRound([0, width]);
y = d3.scaleLinear()
.rangeRound([height,0]);
valueline = d3.line()
.x(function(d) { return x(d.key); })
.y(function(d) { return y(d.value); });
var svg2 = d3.select("#two")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// data
d3.csv("https://raw.githubusercontent.com/JainFamilyInstitute/isa-app/master/data/data_vis.csv?token=AXiiVXcAwXZjLK4-3tiyxKwj8yaVMVDmks5b6b8NwA%3D%3D", function(error, data) {
if (error) throw error;
// filter by selection
data = data.filter(function(d) {
return (d.quantile == quantile) &
(d.variable == variable) &
(d.amount == amount) &
(d.type == type) &
(d.risk == risk) });
// create visualizable array with only ages and amounts for selected series
data_filtered = data.map(({ quantile,amount,risk,type,variable, ...item }) => item);
data_vis = data_filtered[0];
console.log(data_vis);
result = [];
for(i=22;i<101;i++){
key = i;
value =parseFloat(data_vis[i]);
result.push({
key: key,
value: value
});
}
// console.log(data_vis);
console.log(result);
// Scale the range of the data
x.domain([d3.min(result, function(d) { return d.key; }), d3.max(result, function(d) { return d.key; })]);
y.domain([0, d3.max(result, function(d) { return d.value; })]);
// Add the valueline path.
svg2.append("path")
.data([result])
.attr("class", "line")
.attr("d", valueline);
// Add the X Axis
svg2.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add the Y Axis
svg2.append("g")
.call(d3.axisLeft(y));
});
}
</script>
</html>
答案 0 :(得分:0)
一种可能的解决方法是,一次获取您的数据,两次获取过滤器。
这是我使用 d3v5 创建的fiddle,它使用了 fetch API ,可以更轻松地避免此类问题。通常,在编写Javascript代码时要警惕回调。
此代码的主要变化如下:
d3.csv("<remote csv>").then(function(data) {
getIncome(data);
getPayments(data);
});
其余部分与您的代码非常相似。
编辑:Gerardo Furtado的回答还解决了有关问题原因的重要问题。您还应该遵循该答案中的建议。我的解决方案未解决该答案中解决的问题。相反,我的答案集中在确保执行的预期顺序上。
答案 1 :(得分:0)
关于Java语言的警告:当您这样做时...
variable = 'Income';
...而不是:
var variable = 'Income';
...甚至使用const
或let
,您的variable
是全局变量,也就是说,它不在getIncome()
或getPayments()
内部
结合d3.csv
的回调不会立即运行的事实,会发生以下情况:
您一次调用两个函数:
getIncome();
getPayments();
在getIncome()
内,您拥有:
function getIncome() {
variable= 'Income';
//etc...
这使variable
成为具有"Income"
值的全局变量。
然后,当涉及到getPayments()
时,您将拥有:
function getPayments() {
variable= 'Payments';
//etc...
现在variable
的值为"Payments"
,但是第一个函数(getIncome()
)的回调尚未执行!
因此,当第一个函数运行时,variable
的值为"Payments"
,并且两个图表都具有相同的路径。
解决方案:请勿创建全局变量,请勿将值分配给未声明的变量。
这里是您的小提琴,只是在每个变量前添加var
:https://jsfiddle.net/qrj803za/3/
另外,还要照顾您在此处创建的其他全局变量(例如result
,data_vis
等)