自定义d3时间轴

d3的时间比例尺scaleTime在使用的时候遇到过展示格式是YYYY-MM-DD HH:mm:ss的时候,出现文字覆盖的问题,内部的ticks方法并不能很好的控制间距,因为ticks只是一个参考值,实际展示时,坐标轴label个数可能多于ticks,也就比较难避免覆盖问题。
如果要解决时间展示覆盖问题,一个方案是实际展示的个数不大于ticks,这样就可以避免覆盖。d3提供了tickValues方法用于完全自定义坐标轴的显示,当然也需要自己实现时间轴的处理,包括间距的计算,缩放时候的处理,时分秒的处理,尽量让时间可读性更好。下面给出供参考的方案

// scale 缩放函数,坐标轴对应的domain和range,最大的ticks

export function getTickValues(scale, domain, range, ticks = 10) {
//找到开始结束位置对应的时间戳
//优化开始时间和结束时间
let left = nice(scale.invert(range[0]))
let right = nice(scale.invert(range[1]))
let leftRightRange = (right - left) / 1000
let interval = Math.ceil(leftRightRange / ticks)
let count = Math.ceil((domain[1] - domain[0]) / 1000 / interval)

// 时间取整
if (interval / 86400 > 0.5) {
  interval = Math.ceil(interval / 86400) * 86400
} else if (interval > 3600) {
  interval = Math.ceil(interval / 3600) * 3600
} else if (interval > 1800) {
  interval = Math.ceil(interval / 1800) * 1800
} else if (interval > 900) {
  interval = Math.ceil(interval / 900) * 900
} else if (interval > 600) {
  interval = Math.ceil(interval / 600) * 600
} else if (interval > 300) {
  interval = Math.ceil(interval / 300) * 300
} else if (interval > 60) {
  interval = Math.ceil(interval / 60) * 60
}

let tickValues = d3.range(count).map(item => {
  return item * interval * 1000 + domain[0]
})
// 过滤不在范围内的值
return tickValues.filter(item => {
  return item >= left && item <= right
})
}

通过invert函数,找出range对应的domain,然后处理每一段的间距,然后取整。从开始时间获得所有间距,过滤不可见的数据。
适用于折线图的展示,对于柱状图,类似的方式,不过需要在此基础上多处理一步。

你可能感兴趣的:(javascript,d3,数据可视化)