在d3图的y轴上正确显示所有月份

时间:2019-02-12 12:14:43

标签: javascript html d3.js svg

尝试在我的y轴上使用scaleTime()并在全部12个月内填充它。

在这里设置范围和域,然后在%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"));

我希望y刻度显示在底部的1月,顶部的12月,以及介于其间的所有月份。

显示的第一个月是2月,然后是所有月份,然后在最后的刻度线下方显示了12月。

下面是完整的代码段:

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>

1 个答案:

答案 0 :(得分:1)

您在这里有一些选择。第一种,最直接的方法是指定您想要的刻度数-在您的情况下为12。

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

使用这种方法,您可能会发现d3仍然无法渲染适当数量的刻度,这显然令人沮丧。

根据docs

  

指定的计数只是一个提示;规模可能会增加或减少   值取决于域。

另一种选择是显式定义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"));