附加的代码应该生成一些彩色圆圈,实际上它使用的是[1,4,2,3,5]
的硬编码数据集。
但是,我不明白为什么下面的代码无法使用我的JSON数据数组。
浏览器中的控制台显示JSON查询已成功运行并将数据拉入页面 - 似乎没有任何事情发生。
JSON查询如下:
[{"Id":1,"UserID":"JNP","HCRef":"ProjSetup","AnswerString":"","Answerlist":1},
{"Id":2,"UserID":"JNP","HCRef":"ProjSetup","AnswerString":null,"Answerlist":2},
{"Id":3,"UserID":"JNP","HCRef":"ProjSetup","AnswerString":null,"Answerlist":5},
{"Id":4,"UserID":"JNP","HCRef":"ProjSetup","AnswerString":null,"Answerlist":6},
{"Id":5,"UserID":"JNP","HCRef":"ProjSetup","AnswerString":null,"Answerlist":3},
{"Id":6,"UserID":"JNP","HCRef":null,"AnswerString":null,"Answerlist":4}]
我想要发生的是,使用Answerlist
变量在代码的returncolour
部分中返回并驱动圆圈的颜色。否则,数据仅用于触发正在绘制的圆(使用'i'参数)。
正如我所说,使用硬编码数据集,代码可以正常工作。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Test</title>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style type="text/css">
</style>
</head>
<body>
<script type="text/javascript">
var dataset = d3.json('/api/answers/', function (d) {
console.log(d);
});
var w = 1000;
var h = 1000;
// var dataset = [1,4,2,3,5];
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var circles = svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle");
circles.attr("cx", function (d, i)
{
var Xaxis;
if (i === 0) { Xaxis = "500"; }
else if (i === 1) { Xaxis = "400"; }
else if (i === 2) { Xaxis = "420"; }
else if (i === 3) { Xaxis = "452.5"; }
else if (i === 4) { Xaxis = "485"; }
else if (i === 5) { Xaxis = "515"; }
else if (i === 6) { Xaxis = "547.5"; }
else if (i === 7) { Xaxis = "580"; }
else if (i === 8) { Xaxis = "600"; }
else if (i === 9) { Xaxis = "600"; }
else if (i === 10) { Xaxis = "650"; }
else if (i === 11) { Xaxis = "700"; }
else if (i === 12) { Xaxis = "750"; }
else if (i === 13) { Xaxis = "750"; }
else if (i === 14) { Xaxis = "750"; }
else if (i === 15) { Xaxis = "750"; }
else if (i === 16) { Xaxis = "750"; }
return Xaxis;
})
circles.attr("cy", function (d, i) {
var Yaxis;
if (i === 0) { Yaxis = "500"; }
else if (i === 1) { Yaxis = "500"; }
else if (i === 2) { Yaxis = "535"; }
else if (i === 3) { Yaxis = "560"; }
else if (i === 4) { Yaxis = "585"; }
else if (i === 5) { Yaxis = "585"; }
else if (i === 6) { Yaxis = "560"; }
else if (i === 7) { Yaxis = "535"; }
else if (i === 8) { Yaxis = "500"; }
else if (i === 9) { Yaxis = "600"; }
else if (i === 10) { Yaxis = "550"; }
else if (i === 11) { Yaxis = "500"; }
else if (i === 12) { Yaxis = "450"; }
else if (i === 13) { Yaxis = "600"; }
else if (i === 14) { Yaxis = "550"; }
else if (i === 15) { Yaxis = "500"; }
else if (i === 16) { Yaxis = "450"; }
return Yaxis;
})
.attr("r", function (d, i) {
var size;
if (i === 0) { size = "30"; }
else if (i > 0) { size = "20"; }
return size;
})
.attr("fill", function (d) {
return d.Answerlist;
var returnColor;
if (d.Answerlist === 1) { returnColor = "green"; }
else if (d.Answerlist === 2) { returnColor = "lightgreen"; }
else if (d.Answerlist === 3) { returnColor = "gold"; }
else if (d.Answerlist === 4) { returnColor = "darkorange"; }
else if (d.Answerlist === 5) { returnColor = "red"; }
else if (d.Answerlist === 6) { returnColor = "lightgrey"; }
return returnColor;
});
</script>
</body>
</html>
答案 0 :(得分:3)
这与异步代码有关。
将处理代码移到回调中,当前只有:
console.log(d);
您将放在那里的代码比您拥有的任何非回调代码执行得晚,因为脚本首先执行完成,只有然后(异步)将触发回调 - 因此,只有然后 d
(dataset
)才能拥有所需的值:
d3.json('/api/answers/', function (dataset) {
var w = 1000;
var h = 1000;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var circles = svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle");
// etc....
// ...
});
注意:如果您使用数组作为可能的值,那么您的巨大if
语句可以减少到代码的5%。
例如,这个:
var Xaxis;
if (i === 0) { Xaxis = "500"; }
else if (i === 1) { Xaxis = "400"; }
else if (i === 2) { Xaxis = "420"; }
else if (i === 3) { Xaxis = "452.5"; }
else if (i === 4) { Xaxis = "485"; }
else if (i === 5) { Xaxis = "515"; }
else if (i === 6) { Xaxis = "547.5"; }
else if (i === 7) { Xaxis = "580"; }
else if (i === 8) { Xaxis = "600"; }
else if (i === 9) { Xaxis = "600"; }
else if (i === 10) { Xaxis = "650"; }
else if (i === 11) { Xaxis = "700"; }
else if (i === 12) { Xaxis = "750"; }
else if (i === 13) { Xaxis = "750"; }
else if (i === 14) { Xaxis = "750"; }
else if (i === 15) { Xaxis = "750"; }
else if (i === 16) { Xaxis = "750"; }
return Xaxis;
...可以写成:
var Xaxis = [500, 400, 420, 452.5, 485, 515, 547.5, 580, 600, 600,
650, 700, 750, 750, 750, 750, 750][i];
看起来你想要在较大的圆圈周围很好地定位较小的圆圈。在这种情况下,您可以根据 i 的值使用三角函数(正弦和余弦)计算坐标。对于较小的圆圈(i > 0
),它可能看起来像这样 - 较大的圆圈位于[x,y] = [500,500]
:
x = 500-Math.cos((i-1)/2)*100
y = 500+Math.sin((i-1)/2)*100
另请注意,您的attr
回调中包含死代码。在确定颜色并返回颜色之前,return
语句将退出该函数。所以你应该删除return
语句。
最后,颜色缺失,因为您的样本数据的AnswerList
值最多为6,而您只指定了最多为5的颜色。
以下是代码在这些更改中的外观。请注意,我使用了ES6箭头功能。如果您没有ES6支持,只需将它们更改为标准功能:
var dataset = [
{"Id":1,"UserID":"JNP","HCRef":"ProjSetup","AnswerString":"","Answerlist":1},
{"Id":2,"UserID":"JNP","HCRef":"ProjSetup","AnswerString":null,"Answerlist":2},
{"Id":3,"UserID":"JNP","HCRef":"ProjSetup","AnswerString":null,"Answerlist":5},
{"Id":4,"UserID":"JNP","HCRef":"ProjSetup","AnswerString":null,"Answerlist":6},
{"Id":5,"UserID":"JNP","HCRef":"ProjSetup","AnswerString":null,"Answerlist":3},
{"Id":6,"UserID":"JNP","HCRef":null,"AnswerString":null,"Answerlist":4}];
var svg = d3.select("body")
.append("svg")
.attr("width", 1000)
.attr("height", 1000)
.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", (d, i) => i ? 500-Math.cos((i-1)/2)*100 : 500)
.attr("cy", (d, i) => i ? 500+Math.sin((i-1)/2)*100 : 500)
.attr("r", (d, i) => i === 0 ? 30 : 20)
.attr("fill", (d) => ['', 'green', 'gold', 'darkorange', 'red', 'lightgrey', 'purple']
[d.Answerlist]);
<script src="https://d3js.org/d3.v4.min.js"></script>
Scroll down to see the colored circles.
答案 1 :(得分:1)
我迟到了,异步代码的问题已经通过trincot解决了。但我想谈谈你的大量和不必要的if else
陈述。它也在trincot的答案中得到了解决,但有一个更好的 D3方式处理它:使用scales。
因此,如果您想将圆圈从位置200均匀地定位到x轴的位置400,这是一个简单的解决方案:
var xScale = d3.scalePoint()
.range([200, 400])//the start and end position
然后,您使用比例设置圈子'cx
位置:
.attr("cx", function(d,i){
return xScale(i)
});
请参阅?你不需要在一个庞大的数组([400, 420, 450...]
)中手动设置x位置,在繁琐的if
语句中更少,d3会为你做。
使用10个圆圈检查此演示:
var svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 100);
var dataset = d3.range(10);
var xScale = d3.scalePoint()
.range([200, 400])
.domain(dataset);
var circles = svg.selectAll(".circle")
.data(dataset)
.enter()
.append("circle");
circles.attr("cy", 50)
.attr("r", 5)
.attr("fill", "teal")
.attr("cx", function(d,i){return xScale(i)});
<script src="https://d3js.org/d3.v4.min.js"></script>