簡體   English   中英

最后的刻度標簽未出現在D3折線圖中

[英]Last tick label does not appear in D3 Line Chart

我正在嘗試根據Mike Bostock的示例( https://bl.ocks.org/mbostock/3884955 )編寫一個通用的折線圖函數。 我遇到了一個問題,即我的每月圖形x軸上的最后一個刻度標簽未顯示。 最后一個刻度在“每周”圖形x軸上顯示正常。

JS小提琴鏈接: http : //jsfiddle.net/Q5Jag/11879/

我懷疑這里的問題可能是由於為x軸指定的范圍,由於某種原因它忽略了最后一個值。 但是我不確定這到底是怎么回事。 有人可以幫我調試嗎?

這是我的代碼:

  function renderMultiLineChart(datafile, chartDiv, xAxisLabel, yAxisLabel, graphCadence){ var margin = {top: 20, right: 60, bottom: 80, left: 60}, width = 760 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; var parseDate = d3.timeParse("%m/%d/%y"); var x = d3.scaleUtc() .range([0, width]); var y = d3.scaleLinear() .range([height, 0]); var color = d3.scaleOrdinal(d3.schemeCategory10); //var xAxis = d3.axisBottom(x).tickFormat(function(d){ return dx;}); switch(graphCadence) { case "Daily": var xAxis = d3.axisBottom(x).ticks(d3.timeDay.every(1)).tickFormat(d3.timeFormat("%m/%d")) break; case "Weekly": var xAxis = d3.axisBottom(x).ticks(d3.timeSaturday.every(1)).tickFormat(d3.timeFormat("%m/%d")) break; case "Monthly": //var xAxis = d3.axisBottom(x).ticks(d3.timeDay.every(1)) var xAxis = d3.axisBottom(x).ticks(d3.timeMonth.every(1)).tickFormat(d3.utcFormat("%m/%d")) break; } var yAxis = d3.axisLeft(y); var line = d3.line() .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.count); }) var div = d3.select(chartDiv).append("div") .attr("class", "tooltip") .style("opacity", 0); var svg = d3.select(chartDiv).append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); //https://pharos-rest-service-iad.iad.proxy.amazon.com/s3/tool.csv d3.csv(datafile, function(error, data) { color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; })); data.forEach(function(d) { //console.log(d); d.date = parseDate(d.date); }); var datapoints = color.domain().map(function(name) { return { name: name, values: data.map(function(d) { return {date: d.date, count: +d[name]}; }) }; }); console.log(data); x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([ d3.min(datapoints, function(c) { return d3.min(c.values, function(v) { return v.count; }); }), d3.max(datapoints, function(c) { return d3.max(c.values, function(v) { return v.count; }); }) ]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .attr("dx", "-.8em") .attr("dy", ".15em") .style("text-anchor", "end") .attr("transform", "rotate(-45)"); // text label for the x axis svg.append("text") .attr("transform", "translate(" + (width/2) + " ," + (height + margin.top + 30) + ")") .style("text-anchor", "middle") .text(xAxisLabel); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .style("fill", "black") // set the line colour .text(yAxisLabel); var datapoint = svg.selectAll(".datapoint") .data(datapoints) .enter().append("g") .attr("class", "datapoint"); datapoint.append("path") .attr("class", "line") .attr("d", function(d) { return line(d.values); }) .style("stroke", function(d) { return color(d.name); }); j = -1; datapoint.selectAll("circle") .data(function(d){return d.values}) .enter() .append("circle") .attr("r", 3) .attr("cx", function(d,i) { return x(d.date); }) .attr("cy", function(d) { return y(d.count); }) .on("mouseover", function(d) { div.transition() .duration(200) .style("opacity", 1); div.html("<b>"+d.count+"</b>") .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); }) .on("mouseout", function(d) { div.transition() .duration(500) .style("opacity", 0); }) .style("fill", function(d,i) { if (i == 0) { j++ }; return color(datapoints[j].name); }); var legendRectSize = 8; var legendSpacing = 80; var legendHolder = svg.append('g') // translate the holder to the right side of the graph .attr('transform', "translate(" + (100+margin.left+margin.right) + ","+(height+margin.bottom-20)+")") var legend = legendHolder.selectAll('.legend') .data(color.domain()) .enter() .append('g') .attr('class', 'legend') .attr("transform", function (d, i) { if (i === 0) { dataL = legendRectSize + legendSpacing return "translate(0,0)" } else { var newdataL = dataL dataL += legendRectSize + legendSpacing return "translate(" + (newdataL) + ",0)" } }); legend.append('rect') .attr('width', legendRectSize) .attr('height', legendRectSize) .style('fill', color) .style('stroke', color); legend.append('text') .attr('x', legendRectSize + 5) .attr('y', legendRectSize) .text(function(d) { return d; }); }); } renderMultiLineChart("https://gist.githubusercontent.com/techyogii/323024b01c1eb4d0c07637e183e1e6d7/raw/422ed207cc2c38426fa726795ecd963f153135dd/app_usage","div#multiChartMonthly","Snapshot Date","Metric Count","Monthly") renderMultiLineChart("https://gist.githubusercontent.com/techyogii/8ed38bdb3b8e44194ee8570ef9cc5b75/raw/d0c85aaf9eaa7e8819fd6e6e210885b0cfa6f47d/app_usage_weekly","div#multiChartWeekly","Snapshot Date","Metric Count","Weekly") 
 body { font: 10px sans-serif; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .x.axis path { /*display: none;*/ } .line { fill: none; stroke: steelblue; stroke-width: 1.5px; } div.tooltip { position: absolute; text-align: center; /*width: 60px; height: 28px;*/ padding: 4px; font: 14px sans-serif; background: lightsteelblue; border: 0px; border-radius: 10px; pointer-events: none; } .legend { font-size: 12px; } rect { stroke-width: 2; } 
 <script src="https://d3js.org/d3.v4.min.js"></script> <div id="multiChartWeekly"> <div id="multiChartMonthly"> 

謝謝,Yogesh

我認為問題在於d3.timeMonth工作方式與數據格式之間的d3.timeMonth 您會看到d3.timeMonth在標記每個月的第一天,而數據則在每個月的最后一天分組。 因此,當您調用x.domain(d3.extent(data, function(d) { return d.date; })); ,最后一個數據點的日期小於下一個標簽的日期。

一種可能的解決方案是更改解析功能,將所有月份的日期提前一天,以使其與月份的第一天對齊。 見下文。

要刪除任何在月中結束的日期,您可以在分析日期之后過濾數據集以進行清理。

 function renderMultiLineChart(datafile, chartDiv, xAxisLabel, yAxisLabel, graphCadence){ var margin = {top: 20, right: 60, bottom: 80, left: 60}, width = 760 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; var parseDate = function(dateString){ if(graphCadence == "Monthly"){ var date = new Date(dateString); date.setDate(date.getDate()+1); return date; } return d3.timeParse("%m/%d/%y")(dateString); } var x = d3.scaleUtc() .range([0, width]); var y = d3.scaleLinear() .range([height, 0]); var color = d3.scaleOrdinal(d3.schemeCategory10); //var xAxis = d3.axisBottom(x).tickFormat(function(d){ return dx;}); switch(graphCadence) { case "Daily": var xAxis = d3.axisBottom(x).ticks(d3.timeDay.every(1)).tickFormat(d3.timeFormat("%m/%d")) break; case "Weekly": var xAxis = d3.axisBottom(x).ticks(d3.timeSaturday.every(1)).tickFormat(d3.timeFormat("%m/%d")) break; case "Monthly": //var xAxis = d3.axisBottom(x).ticks(d3.timeDay.every(1)) var xAxis = d3.axisBottom(x).ticks(d3.timeMonth.every(1)).tickFormat(d3.utcFormat("%m/%d")) break; } var yAxis = d3.axisLeft(y); var line = d3.line() .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.count); }) var div = d3.select(chartDiv).append("div") .attr("class", "tooltip") .style("opacity", 0); var svg = d3.select(chartDiv).append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); //https://pharos-rest-service-iad.iad.proxy.amazon.com/s3/tool.csv d3.csv(datafile, function(error, data) { color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; })); data.forEach(function(d) { d.date = parseDate(d.date); }); if(graphCadence == "Monthly"){ data = data.filter(function(d){ return d.date.getDate() == 1 }); } var datapoints = color.domain().map(function(name) { return { name: name, values: data.map(function(d) { return {date: d.date, count: +d[name]}; }) }; }); x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([ d3.min(datapoints, function(c) { return d3.min(c.values, function(v) { return v.count; }); }), d3.max(datapoints, function(c) { return d3.max(c.values, function(v) { return v.count; }); }) ]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .attr("dx", "-.8em") .attr("dy", ".15em") .style("text-anchor", "end") .attr("transform", "rotate(-45)"); // text label for the x axis svg.append("text") .attr("transform", "translate(" + (width/2) + " ," + (height + margin.top + 30) + ")") .style("text-anchor", "middle") .text(xAxisLabel); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .style("fill", "black") // set the line colour .text(yAxisLabel); var datapoint = svg.selectAll(".datapoint") .data(datapoints) .enter().append("g") .attr("class", "datapoint"); datapoint.append("path") .attr("class", "line") .attr("d", function(d) { return line(d.values); }) .style("stroke", function(d) { return color(d.name); }); j = -1; datapoint.selectAll("circle") .data(function(d){return d.values}) .enter() .append("circle") .attr("r", 3) .attr("cx", function(d,i) { return x(d.date); }) .attr("cy", function(d) { return y(d.count); }) .on("mouseover", function(d) { div.transition() .duration(200) .style("opacity", 1); div.html("<b>"+d.count+"</b>") .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); }) .on("mouseout", function(d) { div.transition() .duration(500) .style("opacity", 0); }) .style("fill", function(d,i) { if (i == 0) { j++ }; return color(datapoints[j].name); }); var legendRectSize = 8; var legendSpacing = 80; var legendHolder = svg.append('g') // translate the holder to the right side of the graph .attr('transform', "translate(" + (100+margin.left+margin.right) + ","+(height+margin.bottom-20)+")") var legend = legendHolder.selectAll('.legend') .data(color.domain()) .enter() .append('g') .attr('class', 'legend') .attr("transform", function (d, i) { if (i === 0) { dataL = legendRectSize + legendSpacing return "translate(0,0)" } else { var newdataL = dataL dataL += legendRectSize + legendSpacing return "translate(" + (newdataL) + ",0)" } }); legend.append('rect') .attr('width', legendRectSize) .attr('height', legendRectSize) .style('fill', color) .style('stroke', color); legend.append('text') .attr('x', legendRectSize + 5) .attr('y', legendRectSize) .text(function(d) { return d; }); }); } renderMultiLineChart("https://gist.githubusercontent.com/JstnPwll/5a24137a36c9246cf065c58d7f5bb5a5/raw/ff986ee88338e99d10ab93035ffacd3ffe92fd4e/gistfile1.txt","div#multiChartMonthly","Snapshot Date","Metric Count","Monthly") renderMultiLineChart("https://gist.githubusercontent.com/techyogii/8ed38bdb3b8e44194ee8570ef9cc5b75/raw/d0c85aaf9eaa7e8819fd6e6e210885b0cfa6f47d/app_usage_weekly","div#multiChartWeekly","Snapshot Date","Metric Count","Weekly") 
 body { font: 10px sans-serif; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .x.axis path { /*display: none;*/ } .line { fill: none; stroke: steelblue; stroke-width: 1.5px; } div.tooltip { position: absolute; text-align: center; /*width: 60px; height: 28px;*/ padding: 4px; font: 14px sans-serif; background: lightsteelblue; border: 0px; border-radius: 10px; pointer-events: none; } .legend { font-size: 12px; } rect { stroke-width: 2; } 
 <script src="https://d3js.org/d3.v4.min.js"></script> <div id="multiChartWeekly"> <div id="multiChartMonthly"> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM