附加的代码应该产生一些彩色圆圈,当使用[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>
这与异步代码有关。
将处理代码移到回调中,当前只有:
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.
我迟到了,异步代码的问题已经被trincot解决了。但我想谈谈你的庞大和不必要的if else
声明。trincot的回答中也提到了这一点,但有一个更好的方法来处理它:使用音阶。
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>