简体   繁体   中英

Correctly displaying all months in y-axis of d3 graph

Trying to use a scaleTime()for my y axis and populate it with all 12 months.

Here I set the ranges and domain and then apply the full month name format with %B.

const yScale = d3.scaleTime()
.domain([new Date().setMonth(0),new Date().setMonth(11)])
.range([h-padding, padding]);

const yAxis = d3.axisLeft(yScale)
      .tickFormat(d3.timeFormat("%B"));

I expect the y scale to show January at the bottom, December at the top and all month ordered in between.

Instead the first month shown is February, followed by all the months and then December is shown just below the final tick line.

Below is the full code snippet:

 document.addEventListener('DOMContentLoaded', async function() { const res = await d3.json("https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/global-temperature.json"); const BASE_TEMP = parseFloat(res.baseTemperature); document.getElementById("description").textContent =res.monthlyVariance[0]["year"] + "-" + res.monthlyVariance[res.monthlyVariance.length-1]["year"] + ": Base Temperature: " + BASE_TEMP; const w = 800; const h = 500; const padding = 60; const barWidth = (w-padding)/res.monthlyVariance.length; const barHeight = (h-padding)/12; const xScale = d3.scaleTime() .domain([new Date().setFullYear(d3.min(res.monthlyVariance, (d,i)=>parseInt(d["year"]))),new Date().setFullYear(d3.max(res.monthlyVariance, (d,i)=>parseInt(d["year"])))]) .range([padding, w - padding]); const yScale = d3.scaleTime() .domain([new Date().setMonth(0),new Date().setMonth(11)]) .range([h-padding, padding]); const xAxis = d3.axisBottom(xScale); const yAxis = d3.axisLeft(yScale) .tickFormat(d3.timeFormat("%B")); const svg = d3.select("#canvas") .append("svg") .attr("width", w) .attr("height", h); svg.append("g") .attr("id", "x-axis") .attr("transform", "translate(0," + (h - padding) + ")") .call(xAxis); svg.append("g") .attr("id", "y-axis") .attr("transform", "translate(" + padding + ",0)") .call(yAxis); svg.selectAll("rect") .data(res.monthlyVariance) .enter() .append("rect") .attr("width",barWidth) .attr("height",barHeight) .attr("x",(d,i)=>xScale(new Date().setFullYear(d["year"]))) .attr("y", (d,i)=>yScale(new Date().setMonth(parseInt(d["month"])-1))) .attr("data-year",(d,i)=>d["year"]) .attr("data-month",(d,i)=>d["month"]) .attr("data-temp",(d,i)=>(BASE_TEMP+parseFloat(d["variance"]))) .attr("class", "cell") .attr("fill", function(d,i){ let variance = parseInt(d["variance"]); let color = "green"; if (variance<-2) {color="blue"} else if (variance<-1) {color="lightgreen"} else if (variance<1) {color="green"} else if (variance<2) {color="orange"} else {color="red"} return color;}); });
 #container { position:absolute; width:800px; top: 50%; left: 50%; transform: translate(-50%,-50%); text-align:center; } #title { font-size:20px; } .cell:hover { background:lightgrey; }
 <body> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.1/d3.min.js"></script> <div id="container"> <div id="title">Variation in Monthly Land Temperature</div> <div id="description">Update this Message from Dataset</div> <div id="canvas"></div> </div> </body>

You have a few options here. The first, most straight-forward way, is to specify the number of ticks you want - in your case 12.

const yAxis = d3.axisLeft(yScale)
  .ticks(12)
  .tickFormat(d3.timeFormat("%B"));

With this approach what you might find that d3 will still fail to render the appropriate number of ticks, which is obviously frustrating.

According to the docs

The specified count is only a hint; the scale may return more or fewer values depending on the domain.

Another option is to explicitly define the tick values .

const tickValues = Array(12).fill(1).map((val, index) => new Date().setMonth(index));
const yAxis = d3.axisLeft(yScale)
  .tickValues(tickValues)
  .tickFormat(d3.timeFormat("%B"));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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