我正在使用D3 (v4)显示一个在x轴上带有日期的条形图。
我正在尝试让tick显示月份的日期,除非它是我想让它显示月份的第1天,即指示月份发生变化的时间。我甚至不知道该从何说起。
当前格式如下所示:
但我希望它看起来更像这样:
生成轴的当前代码如下所示:
let timeFormat = "%b %d"
xAxis = g => g
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(d3.axisBottom(x).tickFormat(d3.timeFormat(timeFormat)))
我基本上需要一些类似的东西
let timeFormat = "%d == 0" ? "%b" : "%d"
我知道在这个上下文中这是胡说八道的JS,但是它说明了我正在寻找的逻辑
以下是我的图表的简化版本的代码片段:
let keys = [];
var w = 400;
var h = 200;
var margin = {
top: 30,
bottom: 40,
left: 50,
right: 20,
}
var width = w - margin.left - margin.right
var height = h - margin.top - margin.bottom
var data = [
{
"count":100,
"date":"2018-11-30T00:00:00"
},
{
"count":50,
"date":"2018-12-01T00:00:00"
},
{
"count":75,
"date":"2018-12-02T00:00:00"
},
]
var x = d3.scaleTime()
.domain(d3.extent(data, function(d) { return new Date(d.date) }))
.range([0, width]);
var y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.count)])
.range([height, 0]);
var svg = d3.select('body').append('svg')
.attr('class', 'chart')
.attr('width', w)
.attr('height', h);
var chart = svg.append('g')
.classed('graph', true)
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
let timeFormat = "%b %d"
chart.append('g')
.classed('x axis', true)
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x)
.tickFormat(d3.timeFormat(timeFormat))
.ticks(2)
)
chart.append('g')
.classed('y axis', true)
.call(d3.axisLeft(y))
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.0.0/d3.min.js"></script>
发布于 2018-12-11 22:37:37
您可以从scale
获取ticks
,并使用它来查看上一个刻度是否为另一个月,并基于此选择您的格式:
const longFormat = d3.timeFormat('%b');
const shortFormat = d3.timeFormat('%d');
const axis = d3.axisBottom(x);
axis.tickFormat((d, i) => {
const ticks = axis.scale().ticks();
if (i > 0 && ticks[i - 1].getMonth() === d.getMonth()) {
return shortFormat(d);
}
else {
return longFormat(d);
}
});
xAxis = g => g
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(axis)
编辑:如果你使用的不是time scale而是scaleBand
,你应该能够使用域来计算格式:
const ticks = axis.scale().domain();
发布于 2018-12-14 19:17:25
另一个版本:
function multiFormat(date) {
var formatMillisecond = d3.timeFormat(".%L"),
formatSecond = d3.timeFormat(":%S"),
formatMinute = d3.timeFormat("%I:%M"),
formatHour = d3.timeFormat("%I %p"),
formatDay = d3.timeFormat("%_d"),
formatWeek = d3.timeFormat("%_d"),
formatMonth = d3.timeFormat("%b"),
formatYear = d3.timeFormat("%Y");
return (d3.timeSecond(date) < date ? formatMillisecond
: d3.timeMinute(date) < date ? formatSecond
: d3.timeHour(date) < date ? formatMinute
: d3.timeDay(date) < date ? formatHour
: d3.timeMonth(date) < date ? (d3.timeWeek(date) < date ? formatDay : formatWeek)
: d3.timeYear(date) < date ? formatMonth
: formatYear)(date);
}
...
.tickFormat(function(d){return multiFormat(d);})
...
let keys = [];
var w = 400;
var h = 200;
var margin = {
top: 30,
bottom: 40,
left: 50,
right: 20,
}
var width = w - margin.left - margin.right
var height = h - margin.top - margin.bottom
var data = [
{
"count":100,
"date":"2018-11-30T00:00:00"
},
{
"count":50,
"date":"2018-12-01T00:00:00"
},
{
"count":75,
"date":"2018-12-02T00:00:00"
},
]
var x = d3.scaleTime()
.domain(d3.extent(data, function(d) { return new Date(d.date) }))
.range([0, width]);
var y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.count)])
.range([height, 0]);
var svg = d3.select('body').append('svg')
.attr('class', 'chart')
.attr('width', w)
.attr('height', h);
var chart = svg.append('g')
.classed('graph', true)
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
function multiFormat(date) {
var formatMillisecond = d3.timeFormat(".%L"),
formatSecond = d3.timeFormat(":%S"),
formatMinute = d3.timeFormat("%I:%M"),
formatHour = d3.timeFormat("%I %p"),
formatDay = d3.timeFormat("%_d"),
formatWeek = d3.timeFormat("%_d"),
formatMonth = d3.timeFormat("%b"),
formatYear = d3.timeFormat("%Y");
return (d3.timeSecond(date) < date ? formatMillisecond
: d3.timeMinute(date) < date ? formatSecond
: d3.timeHour(date) < date ? formatMinute
: d3.timeDay(date) < date ? formatHour
: d3.timeMonth(date) < date ? (d3.timeWeek(date) < date ? formatDay : formatWeek)
: d3.timeYear(date) < date ? formatMonth
: formatYear)(date);
}
chart.append('g')
.classed('x axis', true)
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x)
.tickFormat(function(d){return multiFormat(d);})
.ticks(2)
)
chart.append('g')
.classed('y axis', true)
.call(d3.axisLeft(y))
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.0.0/d3.min.js"></script>
https://stackoverflow.com/questions/53726046
复制相似问题