我有一个图表,每天都有数据点,但我对x轴的默认设置不满意。
默认的x轴选择要标记的点,例如使用xAxis.ticks(d3.time.month);
,它会将每个月的第1个标记为该月的名称:
|-------|-------|-------|-------|-------|-------|
nov dec jan feb mar apr may
这适用于条形图,其中上面每个月只有一个条形图,但它对于区域图形具有误导性,例如, 'dec'中的'd'出现在28,29th&的数据点下面。十一月三十日。
我希望它标记月份所涵盖的范围(刻度之间的差距):
|-------|-------|-------|-------|-------|-------|
nov dec jan feb mar apr
任何简单的方法都可以在高级别指定它吗?
答案 0 :(得分:0)
要使它们出现在范围的中间,您需要向text
元素添加偏移量(dx)。此偏移量将等于间隔大小的一半,您可以动态计算它。
这是一个非常相似的example。
答案 1 :(得分:0)
我遇到了同样的问题,并通过使用另一个缩放15天的X轴刻度来解决它。
// scale is your usual x scale. change dates on the domain by 15 days
var d0 = scale.domain()[0];
d0.setDate(d0.getDate() - 15);
var d1 = scale.domain()[1];
d1.setDate(d1.getDate() - 15);
// use this new x scale for the axis only
new_scale = d3.time.scale().domain([d0, d1]).range(scale.range());
d3.svg.axis().scale(new_scale);
这样你就没有笨拙的移动文本,仍然把所有繁重的工作留给了d3。为了显示刻度线,您将使用具有正常刻度的第二个x轴。
答案 2 :(得分:0)
(2019)使用最新的d3v5,其他stackoverflow响应1和mbostock trick to select and edit the labels text property,axis styling。
首先给出x_scale
和数量ticks
,您可以计算所有刻度的渲染像素的距离,包括非线性比例。下面的函数返回一个带有刻度距离/空格的数组。
// ticksDistance is constant for a specific x_scale
// apply scale to ticks and calcule distance
const getTicksDistance = (scale) => {
const ticks = scale.ticks(); // return array with ticks
const spaces = []
for(let i=0; i < ticks.length - 1; i++){
spaces.push(scale(ticks[i+1]) - scale(ticks[i]))
}
return spaces;
};
const ticksSpacingTime = getTicksDistance(x_scale_time);
然后使用该距离将标签从当前位置移开,索引i
为您提供位置d3遍历文本标签。
svg.append("g")
.attr("class", "x-axis-shifted")
.attr("transform", "translate(0,100)")
.call(x_axis)
.selectAll("text")
.attr("x", (d,i) => ticksSpacingTime[i]/2)
const x_scale_time = d3.scaleTime()
.domain([new Date(2017,12,1),new Date()])
.range([0, 960]);
const x_axis_time = d3.axisBottom()
.scale(x_scale_time)
.ticks(d3.timeMonth.every(1))
const x_scale_pow = d3.scalePow().exponent(2)
.domain([0,20000])
.range([0, 960]);
const x_axis_pow = d3.axisBottom()
.scale(x_scale_pow)
.ticks(10)
// ticksDistance is constant for a specific x_scale
const getTicksDistance = (scale) => {
const ticks = scale.ticks();
const spaces = []
for(let i=0; i < ticks.length - 1; i++){
spaces.push(scale(ticks[i+1]) - scale(ticks[i]))
}
return spaces;
};
//you have to recalculate when x_scale or ticks change
const ticksSpacingTime = getTicksDistance(x_scale_time);
const ticksSpacingPow = getTicksDistance(x_scale_pow);
const svg = d3.select("body").append("svg")
.attr("width", "500px")
.attr("height","350px")
.style("width", "100%")
.style("height", "auto");
// normal
svg.append("g")
.attr("class", "x-axis-time")
.attr("transform", "translate(0,0)")
.call(x_axis_time)
// shift labels to half of the ticks distance
svg.append("g")
.attr("class", "x-axis-time-shifted")
.attr("transform", "translate(0,40)")
.call(x_axis_time)
.selectAll("text")
.attr("x", (d,i) => ticksSpacingTime[i]/2)
// normal
svg.append("g")
.attr("class", "x-axis")
.attr("transform", "translate(0,110)")
.call(x_axis_pow)
// shift labels to half of the ticks distance
svg.append("g")
.attr("class", "x-axis-shifted")
.attr("transform", "translate(0,150)")
.call(x_axis_pow)
.selectAll("text")
.attr("x", (d,i) => ticksSpacingPow[i]/2)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>