Json D3阵列内容不起作用

时间:2016-10-28 18:01:57

标签: json d3.js

附加的代码应该生成一些彩色圆圈,实际上它使用的是[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>

2 个答案:

答案 0 :(得分:3)

这与异步代码有关。

将处理代码移到回调中,当前只有:

console.log(d);

您将放在那里的代码比您拥有的任何非回调代码执行得晚,因为脚本首先执行完成,只有然后(异步)将触发回调 - 因此,只有然后 ddataset)才能拥有所需的值:

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>