线条没有出现在d3.js折线图中(只有轴可见)

时间:2018-01-23 05:02:48

标签: javascript d3.js linechart linegraph

我想在d3.js中创建一个折线图,但只有我的轴出现了;这条线没有显示出来。

正在发挥作用的事情:1。我的轴标记正确2.在Chrome中查看页面元素时,该行的x和y属性似乎是“工作”。 (即,为线/定义的坐标数据不是' NaN'值)。我认为与我的行相关的属性肯定有问题(Javascript代码的结尾)。

有没有可能发生这种情况的原因?

这是我的情节/图表输出目前的样子:

Current state of plot

这是我的HTML,Javascript和我用于剧情的数据:

HTML:

<html>
    <head>
        <script src="https://d3js.org/d3.v4.min.js"></script>
    </head>
    <body>
        <div id="merit-order-chart"></div>
    </body>
    <script type="text/javascript" src="/src.js"></script>

</html>

JAVASCRIPT:

 // create a SVG element
 let svg2 = d3.select("#merit-order-chart").append("svg");

 // sizing parameters
 let margin2 = {top: 20, right: 50, bottom: 40, left: 80};
 let width2 = 800;
 let height2 = 400;
 let chartWidth2 = width2 - margin2.left - margin2.right;
 let chartHeight2 = height2 - margin2.top - margin2.bottom;

 // sizing the SVG
 svg2.attr("width", width2 + "px")
   .attr("height", height2 + "px");

 // creating the x and y scales
 let y2 = d3.scaleLinear()
   .clamp(true)
   .range([chartHeight2, 0]);
 let x2 = d3.scaleTime()
   .clamp(true)
   .range([0, chartWidth2]);

 // formatting of the x and y axes
 let xAxis2 = d3.axisBottom()
   .scale(x2)
   .tickFormat(d3.timeFormat("%Y-%m-%d %H:%M:%S"))
   .ticks(4);
 let yAxis2 = d3.axisLeft()
   .scale(y2)
   .ticks(8);


 // adding a 'group' element for all the things attached to the chart
 let chart2 = svg2.append("g")
   .attr("transform", `translate(${margin2.left},${margin2.top})`);


 // adding the x and y axis elements to the chart group (g)
 const xg2 = chart2.append("g")
   .classed("x axis", true)
   .attr("transform", `translate(0,${chartHeight2})`)
   .call(xAxis2);
 const yg2 = chart2.append("g")
   .classed("y axis", true)
   .call(yAxis2);


 d3.csv("/price-data.csv", (err, csv) => {
   const clean2 = csv.map(d2 => {
     // clean up number formats
     d2.p = parseFloat(d2.p); 
     d2.settlementdate = Date.parse(d2.settlementdate)
     d2.index = parseFloat(d2.index);
     return d2;
   });

 // re-sizing the x and y axes

   x2.domain([d3.min(clean2, d2 => d2.settlementdate), d3.max(clean2, d2 => d2.settlementdate)]);
   xg2.call(xAxis2);  
   y2.domain([-1000, 14125]); 
   yg2.call(yAxis2);


 chart2.selectAll(".prices")
   .data(clean2)
      .enter()
     .append("line")
       .attr("x", d2 => x2(d2.settlementdate))
       .attr("y", d2 => y2(d2.p))
       .attr("stroke-width", 5)
       .attr("stroke", "black")
       //.style("stroke", "rgb(6,120,155)");
  });

DATA(.csv):

settlementdate,p,index
1/1/2017 0:00,50,1
1/1/2017 0:05,35,2
1/1/2017 0:10,100,3
1/1/2017 0:15,5000,4

1 个答案:

答案 0 :(得分:1)

你需要使用一个线生成器,目前你正在传递一个代表每个点的对象数组,并为每个点附加一条线 - 这种方法不起作用(部分原因是线没有x和y属性,但是x1,x2,y1,y2属性)。

您需要使用线路生成器:

 let line = d3.line()
   .x(function(d) { return x2(d.settlementdate); }) // x value for each point
   .y(function(d) { return y2(d.p); })              // y value for each point

这将返回一个路径,其中每个坐标都有一个顶点。因此,您需要附加路径而不是行,并且路径的绘图说明包含在d属性中,因此您可以使用.attr("d", line)

最后,由于每个数据集需要一个路径,而不是每个数据点一个路径,因此将数据嵌套到数组中。通过这样做,你得到一条有很多点的线,而不是很多没有点的线。

我更改了比例以显示曲线,但结果却缩小了峰值

 chart2.selectAll(".prices")
   .data([clean2])
      .enter()
      .append("path")
      .attr("d",line)
      .attr("stroke-width", 5)
      .attr("stroke", "black")
      .attr("fill","none")

var csv = [
  { settlementdate: "1/1/2017 0:00",p:50,index:1 },
  { settlementdate: "1/1/2017 0:05",p:35,index:2 },
  { settlementdate: "1/1/2017 0:10",p:100,index:3 },
  { settlementdate: "1/1/2017 0:15",p:5000,index:4 }
]


// create a SVG element
 let svg2 = d3.select("#merit-order-chart").append("svg");

 // sizing parameters
 let margin2 = {top: 20, right: 50, bottom: 40, left: 80};
 let width2 = 800;
 let height2 = 400;
 let chartWidth2 = width2 - margin2.left - margin2.right;
 let chartHeight2 = height2 - margin2.top - margin2.bottom;

 // sizing the SVG
 svg2.attr("width", width2 + "px")
   .attr("height", height2 + "px");

 // creating the x and y scales
 let y2 = d3.scaleLinear()
   .clamp(true)
   .range([chartHeight2, 0]);
 let x2 = d3.scaleTime()
   .clamp(true)
   .range([0, chartWidth2]);

 // formatting of the x and y axes
 let xAxis2 = d3.axisBottom()
   .scale(x2)
   .tickFormat(d3.timeFormat("%Y-%m-%d %H:%M:%S"))
   .ticks(4);
 let yAxis2 = d3.axisLeft()
   .scale(y2)
   .ticks(8);


 // adding a 'group' element for all the things attached to the chart
 let chart2 = svg2.append("g")
   .attr("transform", `translate(${margin2.left},${margin2.top})`);


 // adding the x and y axis elements to the chart group (g)
 const xg2 = chart2.append("g")
   .classed("x axis", true)
   .attr("transform", `translate(0,${chartHeight2})`)
   .call(xAxis2);
 const yg2 = chart2.append("g")
   .classed("y axis", true)
   .call(yAxis2);
   
 let line = d3.line()
   .x(function(d) { return x2(d.settlementdate); })
   .y(function(d) { return y2(d.p); })



   const clean2 = csv.map(d2 => {
     // clean up number formats
     d2.p = parseFloat(d2.p); 
     d2.settlementdate = Date.parse(d2.settlementdate)
     d2.index = parseFloat(d2.index);
     return d2;
   });

 // re-sizing the x and y axes

   x2.domain([d3.min(clean2, d2 => d2.settlementdate), d3.max(clean2, d2 => d2.settlementdate)]);
   xg2.call(xAxis2);  
   y2.domain([0, 200]); 
   yg2.call(yAxis2);


 chart2.selectAll(".prices")
   .data([clean2])
      .enter()
     .append("path")
	    .attr("d",line)
       .attr("stroke-width", 5)
       .attr("stroke", "black")
	   .attr("fill","none")
       //.style("stroke", "rgb(6,120,155)");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
 <div id="merit-order-chart"></div>