如何在d3折线图中的一条线上创建点(散点图)

时间:2017-01-10 20:00:29

标签: javascript json d3.js svg

我的代码工作正常,但该行的第一个点存在问题。第一个点总是得到y = 2和x = 1的位置,但其他点正确放置。请帮我把第一个点放在正确的位置。

图: - enter image description here

图表的JSON数据: -

  var data = [{
            "label": "Execution: 6 - defadmin@gmail.com",
            "x": [1, 2, 3, 4, 5, 6],
            "y": [2, 1, 1, 1, 1, 1],
            "xAxisDisplayData": ["1", "2", "3", "4", "5", "6"]
          }];

这是关于点创建的代码,

  // Set the ranges
  var x = d3.time.scale().range([0, innerwidth]);
  var y = d3.scale.linear().range([innerheight, 0]);

  // Scale the range of the data
  x.domain(d3.extent(datasets[0]['x'], function (d, i) {

     return datasets[0]['x'][i];
  }));
  y.domain([1, d3.max(datasets[0]['y'], function (d, i) {
     return datasets[0]['y'][i];
  })]);

  // Add the scatterplot
  svg.selectAll("dot")
     .data(datasets[0]['x'])
     .enter().append("circle")
     .attr("r", 3.5)
     .attr("cx", function (d, i) {
     return x(datasets[0]['x'][i]);
  })
  .attr("cy", function (d, i) {

     return y(datasets[0]['y'][i]);
  });

更新1:完整代码

                        function createLineChart(data, number) {

                //            var data = [ { label: "Execution 1 - buddhika@gmail.com",
                //                x: [1,2,3,4,5,6],
                //                y: [2,1,1,1,1,1] }] ;


                            var widthForSVG;
                            var widthForChart;

                            if ((data[0]['x']).length < 13) {

                                widthForSVG = 1220;
                                widthForChart = 960;

                            } else {


                                widthForSVG = (((data[0]['x']).length - 12) * 80) + 1220;
                                widthForChart = (((data[0]['x']).length - 12) * 80) + 960;

                            }


                            var xy_chart = d3_xy_chart()
                                    .width(widthForChart)
                                    .height(500)
                                    .xlabel("TCS")
                                    .ylabel("STATUS");


                            // creating main svg
                            var svg = d3.select(".lineChartDiv" + number).append("svg")
                                    .datum(data)
                                    .call(xy_chart)
                                    .attr("class", "lineChart" + number)
                                    .attr('width', widthForSVG);


                            function d3_xy_chart() {
                                //1220px  for 12 steps in svg
                                var width = widthForChart,
                                        height = 480,
                                        xlabel = "X Axis Label",
                                        ylabel = "Y Axis Label";


                                function chart(selection, svg) {

                                    var numberNUmber = 0;
                                    selection.each(function (datasets) {
                                        //
                                        // Create the plot.
                                        //


                                        var margin = {top: 20, right: 80, bottom: 30, left: 50},
                                                innerwidth = width - margin.left - margin.right,
                                                innerheight = height - margin.top - margin.bottom;


                                        // Set the ranges



                                        var x_scale = d3.scale.linear()
                                                .range([0, innerwidth])
                                                .domain([d3.min(datasets, function (d) {


                                                    return d3.min(d.x);
                                                }),
                                                    d3.max(datasets, function (d) {

                                                        return d3.max(d.x);
                                                    })]);


                                        var y_scale = d3.scale.linear()
                                                .range([innerheight, 0])
                                                .domain([d3.min(datasets, function (d) {

                                                    return 1;
                                                }),
                                                    d3.max(datasets, function (d) {
                                                        // d3.max(d.y)
                                                        return 3;
                                                    })]);

                                        var color_scale = d3.scale.category10()
                                                .domain(d3.range(datasets.length));

                                        var x_axis = d3.svg.axis()
                                                .scale(x_scale)
                                                .orient("bottom")
                                                .tickFormat(function (d, i) {


                                                    if (d % 1 == 0) {

                                                        return parseInt(datasets[0]['xAxisDisplayData'][i])

                                                    } else {

                                                        return "  "

                                                    }

                                                })
                                                .ticks(d3.max(datasets, function (d) {

                                                    return d3.max(d.x);
                                                }));



                                        var y_axis = d3.svg.axis()
                                                .scale(y_scale)
                                                .orient("left")
                                                .ticks(d3.max(datasets, function (d) {

                                                    return d3.max(d.y);
                                                }))
                                                .tickFormat(function (d, i) {


                                                    if (d == "1") {

                                                        return "NOT EXECUTED"

                                                    } else if (d == "2") {

                                                        return "FAILED"

                                                    } else if (d == "3") {

                                                        return "PASSED"

                                                    } else {

                                                        return "  "

                                                    }

                                                });

                                        var x_grid = d3.svg.axis()
                                                .scale(x_scale)
                                                .orient("bottom")
                                                .tickSize(-innerheight)
                                                .ticks(d3.max(datasets, function (d) {
                                                    // d3.max(d.y)
                                                    return d3.max(d.x);
                                                }))
                                                .tickFormat("");

                                        var y_grid = d3.svg.axis()
                                                .scale(y_scale)
                                                .orient("left")
                                                .tickSize(-innerwidth)
                                                .tickFormat("")
                                                .ticks(d3.max(datasets, function (d) {

                                                    return d3.max(d.y);
                                                }));

                                        var draw_line = d3.svg.line()
                                                .interpolate("linear")
                                                .x(function (d) {

                                                    return x_scale(d[0]);
                                                })
                                                .y(function (d) {

                                                    return y_scale(d[1]);
                                                });

                                        var svg = d3.select(this)
                                                .attr("width", width)
                                                .attr("height", height)
                                                .append("g")
                                                .attr("transform", "translate(" + 90 + "," + margin.top + ")");

                                        svg.append("g")
                                                .attr("class", "x grid")
                                                .attr("transform", "translate(0," + innerheight + ")")
                                                .call(x_grid);

                                        svg.append("g")
                                                .attr("class", "y grid")
                                                .call(y_grid);

                                        svg.append("g")
                                                .attr("class", "x axis")
                                                .attr("transform", "translate(0," + innerheight + ")")
                                                .call(x_axis)
                                                .append("text")
                                                .attr("dy", "-.71em")
                                                .attr("x", innerwidth)
                                                .style("text-anchor", "end")
                                                .text(xlabel);

                                        svg.append("g")
                                                .attr("class", "y axis")
                                                .call(y_axis)
                                                .append("text")
                                                .attr("transform", "rotate(-90)")
                                                .attr("y", 6)
                                                .attr("dy", "0.71em")
                                                .style("text-anchor", "end")
                                                .text(ylabel);


                                        var data_lines = svg.selectAll(".d3_xy_chart_line")
                                                .data(datasets.map(function (d) {

                                                    return d3.zip(d.x, d.y);
                                                }))
                                                .enter().append("g")
                                                .attr("class", "d3_xy_chart_line");


                                        data_lines.append("path")
                                                .attr("class", "line")
                                                .attr("d", function (d) {

                                                    return draw_line(d);
                                                })
                                                .attr("stroke", function (_, i) {
                                                    return color_scale(i);
                                                });

                                        data_lines.append("text")
                                                .datum(function (d, i) {
                                                    return {name: datasets[i].label, final: d[d.length - 1]};
                                                })
                                                .attr("transform", function (d) {
                                                    return ( "translate(" + x_scale(d.final[0]) + "," +
                                                    y_scale(d.final[1]) + ")" );
                                                })
                                                .attr("x", 3)
                                                .attr("dy", ".35em")
                                                .attr("fill", function (_, i) {
                                                    return color_scale(i);
                                                })
                                                .text(function (d) {
                                                    return d.name;
                                                });


                                        // Set the ranges
                                        var x = d3.time.scale().range([0, innerwidth]);
                                        var y = d3.scale.linear().range([innerheight, 0]);


                                        // Scale the range of the data
                                        x.domain(d3.extent(datasets[0]['x']));
                                        y.domain([1, d3.max(datasets[0]['y'])]);

                                        svg.selectAll("dot")
                                                .data(d3.zip(datasets[0].x, datasets[0].y))
                                                .enter().append("circle")
                                                .attr("r", 3.5)
                                                .attr("cx", function (d) {
                                                    return x(d[0]);
                                                })
                                                .attr("cy", function (d) {
                                                    return y(d[1]);
                                                });



                                    });
                                }

                                chart.width = function (value) {
                                    if (!arguments.length) return width;
                                    width = value;
                                    return chart;
                                };

                                chart.height = function (value) {
                                    if (!arguments.length) return height;
                                    height = value;
                                    return chart;
                                };

                                chart.xlabel = function (value) {
                                    if (!arguments.length) return xlabel;
                                    xlabel = value;
                                    return chart;
                                };

                                chart.ylabel = function (value) {
                                    if (!arguments.length) return ylabel;
                                    ylabel = value;
                                    return chart;
                                };

                                return chart;
                            }


                        }

更新2:

创建圈子的html视图 - (查看第一个圈子,它总是有cx = 0和cy = 0 cordinates.other圈子很好)

enter image description here

更新3:feddle

feddle

2 个答案:

答案 0 :(得分:3)

您对d3.extent()以及d3.max()的使用存在缺陷。提供给这些方法的功能只是访问者;实际迭代没有参数i。它们是实际访问数组相关数据的一种方法,它作为第一个参数传入。因为您已经传入平面数据数组,所以两个访问器函数都可以减少到function (d) { return d; }。这些可能会被省略,因为这是默认行为。您的域名设置因此变为:

// Scale the range of the data
x.domain(d3.extent(datasets[0]['x']));
y.domain([1, d3.max(datasets[0]['y'])]);

就个人而言,我还会重写您的数据绑定逻辑以提高可读性:

// Add the scatterplot
svg.selectAll("dot")
  .data(d3.zip(datasets[0].x, datasets[0].y))
  .enter().append("circle")
    .attr("r", 3.5)
    .attr("cx", function (d) {
      return x(d[0]);
    })
    .attr("cy", function (d) {
      return y(d[1]);
    });

每次需要这些值时,不要对datasets数组进行繁琐的深度访问,而是使用d3.zip()构建一个包含点&#39;的新数组。坐标,然后绑定到选择。如您所见,这为您提供了用于设置cxcy属性值的简洁代码。

除了这些技术缺陷之外,设置您的y比例域名存在逻辑故障 - 正如Andrew comment所示 - 你正在做什么

y.domain([1, d3.max(datasets[0]['y'])]);

在您提供的数据集中,y的最大值为2。这样,您的域名将设置为[1, 2],而忽略3。有了这个域,因此将在原点绘制点。因为你的y值是类别,所以这显然不是你想要的。要始终绘制所有类别,您可以使用静态值来设置比例域:

y.domain([1, 3]);

你已经这样做了 - 虽然相当尴尬 - 对于你的其他比例y_scale,这就是正确绘制线的原因。

当然,您也可以决定只绘制数据集中包含的类别,在这种情况下,您将d3.max()保留在域中,但您必须同时为{{{{{{ 1}}&#39; s。域。

请查看以下代码段以获取工作示例。它包含来自JSFiddle的代码,只更改了一行,其中y_scale比例域已设置。

&#13;
&#13;
y
&#13;
var data = [{
  "label": "Execution: 6 - defadmin@gmail.com",
  "x": [1, 2, 3, 4, 5, 6],
  "y": [2, 1, 1, 1, 1, 1],
  "xAxisDisplayData": ["1", "2", "3", "4", "5", "6"]
}];

var number = 1;

var widthForSVG;
var widthForChart;

if ((data[0]['x']).length < 13) {

  widthForSVG = 1220;
  widthForChart = 960;

} else {


  widthForSVG = (((data[0]['x']).length - 12) * 80) + 1220;
  widthForChart = (((data[0]['x']).length - 12) * 80) + 960;

}


var xy_chart = d3_xy_chart()
.width(widthForChart)
.height(500)
.xlabel("TCS")
.ylabel("STATUS");


// creating main svg
var svg = d3.select(".lineChartDiv1").append("svg")
.datum(data)
.call(xy_chart)
.attr("class", "lineChartDiv1")
.attr('width', widthForSVG);





function d3_xy_chart() {

  var width = widthForChart,
      height = 480,
      xlabel = "X Axis Label",
      ylabel = "Y Axis Label";


  function chart(selection, svg) {

    var numberNUmber = 0;
    selection.each(function(datasets) {
      //
      // Create the plot.
      //


      var margin = {
        top: 20,
        right: 80,
        bottom: 30,
        left: 50
      },
          innerwidth = width - margin.left - margin.right,
          innerheight = height - margin.top - margin.bottom;


      // Set the ranges



      var x_scale = d3.scale.linear()
      .range([0, innerwidth])
      .domain([d3.min(datasets, function(d) {


        return d3.min(d.x);
      }),
               d3.max(datasets, function(d) {

                 return d3.max(d.x);
               })
              ]);


      var y_scale = d3.scale.linear()
      .range([innerheight, 0])
      .domain([d3.min(datasets, function(d) {

        return 1;
      }),
               d3.max(datasets, function(d) {
                 // d3.max(d.y)
                 return 3;
               })
              ]);

      var color_scale = d3.scale.category10()
      .domain(d3.range(datasets.length));

      var x_axis = d3.svg.axis()
      .scale(x_scale)
      .orient("bottom")
      .tickFormat(function(d, i) {


        if (d % 1 == 0) {

          return parseInt(datasets[0]['xAxisDisplayData'][i])

        } else {

          return "  "

        }

      })
      .ticks(d3.max(datasets, function(d) {

        return d3.max(d.x);
      }));



      var y_axis = d3.svg.axis()
      .scale(y_scale)
      .orient("left")
      .ticks(d3.max(datasets, function(d) {

        return d3.max(d.y);
      }))
      .tickFormat(function(d, i) {


        if (d == "1") {

          return "NOT EXECUTED"

        } else if (d == "2") {

          return "FAILED"

        } else if (d == "3") {

          return "PASSED"

        } else {

          return "  "

        }

      });

      var x_grid = d3.svg.axis()
      .scale(x_scale)
      .orient("bottom")
      .tickSize(-innerheight)
      .ticks(d3.max(datasets, function(d) {
        // d3.max(d.y)
        return d3.max(d.x);
      }))
      .tickFormat("");

      var y_grid = d3.svg.axis()
      .scale(y_scale)
      .orient("left")
      .tickSize(-innerwidth)
      .tickFormat("")
      .ticks(d3.max(datasets, function(d) {

        return d3.max(d.y);
      }));

      var draw_line = d3.svg.line()
      .interpolate("linear")
      .x(function(d) {

        return x_scale(d[0]);
      })
      .y(function(d) {

        return y_scale(d[1]);
      });

      var svg = d3.select(this)
      .attr("width", width)
      .attr("height", height)
      .append("g")
      .attr("transform", "translate(" + 90 + "," + margin.top + ")");

      svg.append("g")
      .attr("class", "x grid")
      .attr("transform", "translate(0," + innerheight + ")")
      .call(x_grid);

      svg.append("g")
      .attr("class", "y grid")
      .call(y_grid);

      svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + innerheight + ")")
      .call(x_axis)
      .append("text")
      .attr("dy", "-.71em")
      .attr("x", innerwidth)
      .style("text-anchor", "end")
      .text(xlabel);

      svg.append("g")
      .attr("class", "y axis")
      .call(y_axis)
      .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", "0.71em")
      .style("text-anchor", "end")
      .text(ylabel);


      var data_lines = svg.selectAll(".d3_xy_chart_line")
      .data(datasets.map(function(d) {

        return d3.zip(d.x, d.y);
      }))
      .enter().append("g")
      .attr("class", "d3_xy_chart_line");


      data_lines.append("path")
      .attr("class", "line")
      .attr("d", function(d) {

        return draw_line(d);
      })
      .attr("stroke", function(_, i) {
        return color_scale(i);
      });

      data_lines.append("text")
      .datum(function(d, i) {
        return {
          name: datasets[i].label,
          final: d[d.length - 1]
        };
      })
      .attr("transform", function(d) {
        return ("translate(" + x_scale(d.final[0]) + "," +
                y_scale(d.final[1]) + ")");
      })
      .attr("x", 3)
      .attr("dy", ".35em")
      .attr("fill", function(_, i) {
        return color_scale(i);
      })
      .text(function(d) {
        return d.name;
      });


      // Set the ranges
      var x = d3.time.scale().range([0, innerwidth]);
      var y = d3.scale.linear().range([innerheight, 0]);


      // Scale the range of the data
      x.domain(d3.extent(datasets[0]['x']));
      y.domain([1, 3]);

      // console.log(JSON.stringify(d3.extent(datasets[0]['x'])))
      // console.log(JSON.stringify(d3.max(datasets[0]['y'])))

      // Add the scatterplot

      svg.selectAll("dot")
      .data(d3.zip(datasets[0].x, datasets[0].y))
      .enter().append("circle")
      .attr("class", datasets[0]['label'])
      .attr("r", 3.5)
      .attr("cx", function(d) {

        // console.log(JSON.stringify(d[0])+" XXXXXXXXXXx ")

        return x(d[0]);


      })
      .attr("cy", function(d) {
        //console.log(JSON.stringify(d[1])+" YYYYYYYyy ")
        return y(d[1]);
      });



    });
  }

  chart.width = function(value) {
    if (!arguments.length) return width;
    width = value;
    return chart;
  };

  chart.height = function(value) {
    if (!arguments.length) return height;
    height = value;
    return chart;
  };

  chart.xlabel = function(value) {
    if (!arguments.length) return xlabel;
    xlabel = value;
    return chart;
  };

  chart.ylabel = function(value) {
    if (!arguments.length) return ylabel;
    ylabel = value;
    return chart;
  };

  return chart;
}
&#13;
.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}
.grid path,
.grid line {
  fill: none;
  stroke: rgba(0, 0, 0, 0.25);
  shape-rendering: crispEdges;
}
.x.axis path {
  display: none;
}
.line {
  fill: none;
  stroke-width: 2.5px;
}
svg {
  font: 10px sans-serif;
}
.area {
  fill: lightgray;
  clip-path: url(#clip);
}
.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}
.brush .extent {
  stroke: #fff;
  fill-opacity: .125;
  shape-rendering: crispEdges;
  clip-path: url(#clip);
}
rect.pane {
  cursor: move;
  fill: none;
  pointer-events: all;
}
&#13;
&#13;
&#13;

答案 1 :(得分:-1)

试试这个,

           if(data[0]['y'][1]==1){

                document.getElementsByClassName(data[0]['label'])[0].setAttribute('cx','0');
                document.getElementsByClassName(data[0]['label'])[0].setAttribute('cy','225');


            }else if(data[0]['y'][1]==2){

                document.getElementsByClassName(data[0]['label'])[0].setAttribute('cx','0');
                document.getElementsByClassName(data[0]['label'])[0].setAttribute('cy','450');

            }else{

                document.getElementsByClassName(data[0]['label'])[0].setAttribute('cx','0');
                document.getElementsByClassName(data[0]['label'])[0].setAttribute('cy','0');


            }

嘿我(Buddhika)改进了你的代码,其他方面也没用:

  var element = document.getElementsByClassName(data[0]['label']);

                            for (var i =0; i<element.length; i++){



                                if(data[0]['y'][0]==1 & data[0]['x'][i]==0){

                                    document.getElementsByClassName(data[0]['label'])[i].setAttribute('cy','450');


                                }else if(data[0]['y'][0]==2  & data[0]['x'][i]==0){


                                    document.getElementsByClassName(data[0]['label'])[i].setAttribute('cy','225');

                                }else if(data[0]['y'][0]==3 & data[0]['x'][i]==0){


                                    document.getElementsByClassName(data[0]['label'])[i].setAttribute('cy','0');


                                }else if(data[0]['y'][i]==1){


                                    document.getElementsByClassName(data[0]['label'])[i].setAttribute('cy','450');


                                }else if(data[0]['y'][i]==2){


                                    document.getElementsByClassName(data[0]['label'])[i].setAttribute('cy','225');

                                }else if(data[0]['y'][i]==3){


                                    document.getElementsByClassName(data[0]['label'])[i].setAttribute('cy','0');


                                }

                            }