简体   繁体   English

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

[英]how to create dots(scatterplot) on a line in a d3 line chart

my code is working fine, but there is a issue with the first dot on the line. 我的代码工作正常,但该行的第一个点有问题。 first dot always get the y=2 and x=1 position, but other dots are placed correctly. 第一个点始终位于y = 2和x = 1的位置,但其他点的放置正确。 please help me to place the first dot in correct place. 请帮助我将第一个点放置在正确的位置。

graph:- 图形:- 在此处输入图片说明

JSON data for the graph:- 图的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"]
          }];

here is my code regarding the dot creation, 这是我关于点创建的代码,

  // 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]);
  });

UPDATE 1: full code 更新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;
                            }


                        }

UPDATE 2: 更新2:

html view of created circles-(check the first circle, it always has cx=0 and cy=0 cordinates.other circles are fine) 创建的圆的html视图(检查第一个圆,它始终具有cx = 0和cy = 0坐标,其他圆都可以)

在此处输入图片说明

UPDATE 3: feddle 更新3:联邦

feddle 联邦

Your use of d3.extent() as well as d3.max() is flawed. 您对d3.extent()d3.max()的使用存在缺陷。 The functions provided to these methods are just accessors; 这些方法提供的功能仅仅是访问器; there is no parameter i for an actual iteration. 实际迭代没有参数i They are meant as a means to actually access the relevant data of the array, which was passed in as the first parameter. 它们是实际访问数组的相关数据的一种手段,该数据作为第一个参数传入。 Because you are already passing in the flat data arrays, both accessor function can be reduced to function (d) { return d; } 因为您已经在传递平面数据数组,所以两个访问器函数都可以简化为function (d) { return d; } function (d) { return d; } . function (d) { return d; } These might further be omitted because this is the default behavior. 这些可能会进一步省略,因为这是默认行为。 Your domain setup thus becomes: 这样,您的域设置将变为:

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

Personally, I would also rewrite your data binding logic to improve readability: 就个人而言,我还将重写您的数据绑定逻辑以提高可读性:

// 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]);
    });

Instead of doing the cumbersome deep access into the datasets array each time you need those values, this uses d3.zip() to build a new array of arrays containing the points' coordinates, which is then bound to the selection. 不需要每次都需要这些值时对datasets数组进行繁琐的深度访问,而是使用d3.zip()构建包含点坐标的新数组数组,然后将其绑定到选择。 As you can see, this leaves you with clean code for setting your cx and cy attribute values. 如您所见,这将为您提供用于设置cxcy属性值的简洁代码。

Besides these technical shortcomings there is a logical glitch in setting up your y scale's domain—as indicated by Andrew's comment —, where you are doing 除了这些技术缺陷存在设置你的逻辑故障y规模的领域,如由安德鲁表示意见 - ,你在哪里做

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

In the dataset you provided the maximum value for y is 2, though. 但是,在数据集中,您提供的y的最大值为2。 This way your domain will be set to [1, 2] leaving out the 3 . 这样,您的域将被设置为[1, 2]而不包含3 With this domain the point will consequently be drawn at the origin. 因此,使用该域将在原点绘制点。 Because your y values are categories, this is obviously not what you want. 因为您的y值是类别,所以显然这不是您想要的。 To always draw the full range of categories, you could use static values to set up your scale's domain: 要始终绘制所有类别的类别,可以使用静态值来设置比例尺的域:

y.domain([1, 3]);

You are already doing it this way—in a rather awkward way, though—for your other scale y_scale , which is why the line is drawn correctly. 对于其他比例尺y_scale ,您已经以这种方式(但是相当尴尬)进行了此y_scale ,这就是正确绘制线条的原因。

Of course, you could also decide to only draw the categories contained in the dataset, in which case you would keep the d3.max() in the domain, but you will then have to also do the same for your y_scale 's domain. 当然,您也可以决定只绘制数据集中包含的类别,在这种情况下,您应将d3.max()保留在域中,但随后还必须对y_scale的域进行相同的操作。

Have a look at the following snippet for a working example. 请看下面的示例片段。 It contains the code from your JSFiddle having just the one line changed, where the y scale's domain is set up. 它包含来自JSFiddle的代码,只更改了一行,并在其中设置了y标度的域。

 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(dx); }), d3.max(datasets, function(d) { return d3.max(dx); }) ]); var y_scale = d3.scale.linear() .range([innerheight, 0]) .domain([d3.min(datasets, function(d) { return 1; }), d3.max(datasets, function(d) { // d3.max(dy) 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(dx); })); var y_axis = d3.svg.axis() .scale(y_scale) .orient("left") .ticks(d3.max(datasets, function(d) { return d3.max(dy); })) .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(dy) return d3.max(dx); })) .tickFormat(""); var y_grid = d3.svg.axis() .scale(y_scale) .orient("left") .tickSize(-innerwidth) .tickFormat("") .ticks(d3.max(datasets, function(d) { return d3.max(dy); })); 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(dx, dy); })) .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; } 
 .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; } 
 <script src="https://d3js.org/d3.v3.js"></script> <div class="row"> <div class="col-sm-12"> <div class="lineChartDiv1" style=" overflow-x: scroll"> </div> </div> </div> 

Try this, 尝试这个,

           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');


            }

Hey I (Buddhika) improved your code below way, other wise it is useless : 嘿我(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');


                                }

                            }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM