Json D3数组内容不工作



附加的代码应该产生一些彩色圆圈,当使用[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的回答中也提到了这一点,但有一个更好的方法来处理它:使用音阶。

所以,如果你想让你的圆在x轴上的位置从200到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>

最新更新