时间刻度的圆x轴到最近的半小时

时间:2017-12-29 15:39:52

标签: javascript d3.js

My current graph

我正在构建一个图表,它正在从postgres后端获取数据。对于x轴的构造,我有以下内容:

var x = d3.scaleTime()
    .domain(d3.extent(data_prices, function(d){
        var time = timeParser(d.timestamp);
        return time;
    }))
    .range([0,width])

其中timeParser是表示d3.timeParse()的函数。

我的数据点是16:58而另一个是22:06,它看起来有点难看,因为它只是坚持在那边。例如,我怎么说,有一个轻微的说法,每个+/- 30分钟,并继续每端的趋势线路径? (或至少只是第一部分)

1 个答案:

答案 0 :(得分:2)

要在时间范围内创建填充,请使用interval.offset。根据{{​​3}}:

  

返回等于date加步长间隔的新日期。如果未指定step,则默认为1.如果step为negative,则返回的日期将在指定日期之前。

让我们看看它有效。这是一个基于时间刻度的轴,其最小值和最大值与您的相似:

var svg = d3.select("svg");
var data = ["16:58", "18:00", "20:00", "22:00", "22:06"].map(function(d) {
  return d3.timeParse("%H:%M")(d)
});

var scale = d3.scaleTime()
  .domain(d3.extent(data))
  .range([20, 580]);

var axis = d3.axisBottom(scale);

var gX = svg.append("g")
  .attr("transform", "translate(0,50)")
  .call(axis)
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="600" height="100"></svg>

现在,要创建填充,我们只需要在极端情况下减去并添加30分钟:

var scale = d3.scaleTime()
    .domain([d3.timeMinute.offset(d3.min(data), -30),
        //subtract 30 minutes here --------------^
            d3.timeMinute.offset(d3.max(data), 30)
        //add 30 minutes here ------------------^
        ])
    .range([20, 580]);

结果如下:

var svg = d3.select("svg");
var data = ["16:58", "18:00", "20:00", "22:00", "22:06"].map(function(d) {
  return d3.timeParse("%H:%M")(d)
});

var scale = d3.scaleTime()
  .domain([d3.timeMinute.offset(d3.min(data), -30), d3.timeMinute.offset(d3.max(data), 30)])
  .range([20, 580]);

var axis = d3.axisBottom(scale);

var gX = svg.append("g")
  .attr("transform", "translate(0,50)")
  .call(axis)
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="600" height="100"></svg>

请注意,此解决方案不会将极端刻度舍入到最近的半小时:添加减去正好半小时

所以,要四舍五入到最近的半小时,你可以使用Math.floorMath.ceil进行简单的数学计算:

.domain([
    d3.min(data).setMinutes(Math.floor(d3.min(data).getMinutes() / 30) * 30), 
    d3.max(data).setMinutes(Math.ceil(d3.max(data).getMinutes() / 30) * 30)
])

以下是演示:

var svg = d3.select("svg");
var data = ["16:58", "18:00", "20:00", "22:00", "22:06"].map(function(d) {
  return d3.timeParse("%H:%M")(d)
});

var scale = d3.scaleTime()
  .domain([d3.min(data).setMinutes(Math.floor(d3.min(data).getMinutes() / 30) * 30), d3.max(data).setMinutes(Math.ceil(d3.max(data).getMinutes() / 30) * 30)])
  .range([20, 580]);

var axis = d3.axisBottom(scale);

var gX = svg.append("g")
  .attr("transform", "translate(0,50)")
  .call(axis)
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="600" height="100"></svg>