D3JS Plotting Line Graph From Array Data (Data is undefined error)

自作多情 提交于 2021-02-17 01:22:12

问题


I am trying to plot out a graph from the following array, however the console is telling me that the array is not passed to the line function

I am receiving the following error: "0: Unable to get property 'x' of undefined or null reference" from the console log

Code is as follows :

const svgHeight = 400;
const svgWidth = 400;
const margin = {left:50, right:20, top:20, bottom:30};
const h = svgHeight - margin.top - margin.bottom;
const w = svgWidth - margin.right - margin.left;

document.addEventListener("DOMContentLoaded", function(event){
          drawChart();
});

function drawChart(){
        const svg = d3.select("body")
                      .append("svg")
                      .attr("height",svgHeight)
                      .attr("width",svgWidth);

        const xscale = d3.scaleLinear()
              .range([0,w])
              .domain([0,50]);

        const yscale = d3.scaleLinear()
                  .range([h,0])
                  .domain([0,30]);

        const xaxis = d3.axisBottom().scale(xscale);
        const yaxis = d3.axisRight().scale(yscale);

        var rh100line = d3.line()
                      .x(function(d,i){
                        console.log(d[i]);
                        return xscale(d[i].x);
                      })
                      .y(function(d,i){
                        return yscale((622*1*d[i].y)/(101.325-1*d[i].y));
                      })
                      .curve(d3.curveMonotoneX);

        svg.append("g")
          .attr("class","axis")
          .attr("transform","translate(0," + h + ")")
          .call(xaxis);

        svg.append("g")
          .attr("class","axis")      
          .call(yaxis);

        svg.append("path")
            .data(tp1)
            .attr("class","line")
            .attr("d", rh100line);

}

Array is stored in tp1:

var tp1 = [{x:0.01, y:0.61165},
    {x:1, y:0.65709},
    {x:2, y:0.70599},
    {x:3, y:0.75808},
    {x:4, y:0.81355},
    {x:5, y:0.87258},
    {x:6, y:0.93536},
    {x:7, y:1.00210},
    {x:8, y:1.07300},
    {x:9, y:1.14830},
    {x:10, y:1.22820},
    {x:11, y:1.31300},
    {x:12, y:1.40280},
    {x:13, y:1.49810},
    {x:14, y:1.59900},
    {x:15, y:1.70580},
    {x:16, y:1.81880},
    {x:17, y:1.93840},
    {x:18, y:2.06470},
    {x:19, y:2.19830},
    {x:20, y:2.33930},
    {x:21, y:2.48820},
    {x:22, y:2.64530},
    {x:23, y:2.81110},
    {x:24, y:2.98580},
    {x:25, y:3.16990},
    {x:26, y:3.36390},
    {x:27, y:3.56810},
    {x:28, y:3.78310},
    {x:29, y:4.00920},
    {x:30, y:4.24700},
    {x:31, y:4.49690},
    {x:32, y:4.75960},
    {x:33, y:5.03540},
    {x:34, y:5.32510},
    {x:35, y:5.62900},
    {x:36, y:5.94790},
    {x:37, y:6.28230},
    {x:38, y:6.63280},
    {x:39, y:7.00020},
    {x:40, y:7.38490},
    {x:41, y:7.78780},
    {x:42, y:8.20960},
    {x:43, y:8.65080},
    {x:44, y:9.11240},
    {x:45, y:9.59500},
    {x:46, y:10.09900},
    {x:47, y:10.62700},
    {x:48, y:11.17700},
    {x:49, y:11.75200},
    {x:50, y:12.35200}]

回答1:


There are two issues here, let's start with binding data to the line.

You have a data array that contains points of a path, a singular path. You don't want each item in the data array to correspond to an element in the DOM. So we need to restructure your use of .data(). .data() would be great if you wanted to create one point for every item in the data array, but you only have one line. One way to fix this is to use:

.data([pointsOnPathArray]) // here we pass an array containing one item (the path data) 
                           // as opposed to an array containing many items

Or, we can set the bound datum for the appended path with:

.datum(pointsOnPathArray) // here we bind the path data directly to the appended path.

The use of .datum() would probably be more idiomatic in this case as you aren't using selectAll() or enter() statements.

Now the accessor function for x and y for the line generator. For each point in the path data array, what do we want to use to plot x and y?

    var rh100line = d3.line()
                  .x(function(d){
                     return xscale(d.x);
                  })
                  .y(function(d){
                    return yscale((622*1*d.y)/(101.325-1*d.y));
                  })
                  .curve(d3.curveMonotoneX);

There is no need to use an index, d refers to the point already, not the array containing all the points.

Here's those changes at work:

var tp1 = [{x:0.01, y:0.61165},
    {x:1, y:0.65709},
    {x:2, y:0.70599},
    {x:3, y:0.75808},
    {x:4, y:0.81355},
    {x:5, y:0.87258},
    {x:6, y:0.93536},
    {x:7, y:1.00210},
    {x:8, y:1.07300},
    {x:9, y:1.14830},
    {x:10, y:1.22820},
    {x:11, y:1.31300},
    {x:12, y:1.40280},
    {x:13, y:1.49810},
    {x:14, y:1.59900},
    {x:15, y:1.70580},
    {x:16, y:1.81880},
    {x:17, y:1.93840},
    {x:18, y:2.06470},
    {x:19, y:2.19830},
    {x:20, y:2.33930},
    {x:21, y:2.48820},
    {x:22, y:2.64530},
    {x:23, y:2.81110},
    {x:24, y:2.98580},
    {x:25, y:3.16990},
    {x:26, y:3.36390},
    {x:27, y:3.56810},
    {x:28, y:3.78310},
    {x:29, y:4.00920},
    {x:30, y:4.24700},
    {x:31, y:4.49690},
    {x:32, y:4.75960},
    {x:33, y:5.03540},
    {x:34, y:5.32510},
    {x:35, y:5.62900},
    {x:36, y:5.94790},
    {x:37, y:6.28230},
    {x:38, y:6.63280},
    {x:39, y:7.00020},
    {x:40, y:7.38490},
    {x:41, y:7.78780},
    {x:42, y:8.20960},
    {x:43, y:8.65080},
    {x:44, y:9.11240},
    {x:45, y:9.59500},
    {x:46, y:10.09900},
    {x:47, y:10.62700},
    {x:48, y:11.17700},
    {x:49, y:11.75200},
    {x:50, y:12.35200}]

const svgHeight = 400;
const svgWidth = 400;
const margin = {left:50, right:20, top:20, bottom:30};
const h = svgHeight - margin.top - margin.bottom;
const w = svgWidth - margin.right - margin.left;

document.addEventListener("DOMContentLoaded", function(event){
          drawChart();
});

function drawChart(){
        const svg = d3.select("body")
                      .append("svg")
                      .attr("height",svgHeight)
                      .attr("width",svgWidth);

        const xscale = d3.scaleLinear()
              .range([0,w])
              .domain([0,50]);

        const yscale = d3.scaleLinear()
                  .range([h,0])
                  .domain([0,30]);

        const xaxis = d3.axisBottom().scale(xscale);
        const yaxis = d3.axisRight().scale(yscale);

        var rh100line = d3.line()
                      .x(function(d){
                        return xscale(d.x);
                      })
                      .y(function(d){
                        return yscale((622*1*d.y)/(101.325-1*d.y));
                      })
                      .curve(d3.curveMonotoneX);

        svg.append("g")
          .attr("class","axis")
          .attr("transform","translate(0," + h + ")")
          .call(xaxis);

        svg.append("g")
          .attr("class","axis")      
          .call(yaxis);

        svg.append("path")
            .datum(tp1)
            .attr("class","line")
            .attr("d", rh100line);

}
path {
  fill: none;
  stroke:black;
  stroke-width:1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>


来源:https://stackoverflow.com/questions/61415303/d3js-plotting-line-graph-from-array-data-data-is-undefined-error

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!