如何定义轴上的刻度数?

时间:2019-03-23 15:17:48

标签: javascript d3.js

我是d3的新手,并且使用以下代码在图形上创建x轴:

export const drawXAxis = (svg, timestamps, chartWidth, chartHeight) => {
    console.log(chartWidth); // 885
    console.log(timestamps.length); // 310
    const xScale = d3.scaleLinear()
        .domain([-1, timestamps.length])
        .range([0, chartWidth]);

    const xBand = d3.scaleBand()
        .domain(
            d3.range(-1, timestamps.length))
                .range([0, chartWidth])
                .padding(0.3);

    const xAxis = d3.axisBottom()
        .scale(xScale)
        .tickFormat(function(d) {
            const ts = moment.utc(timestamps[d]);
            return ts.format('HH') + 'h';
        });

    const gX = svg.append("g")
        .attr("class", "axis x-axis")
        .attr("transform", "translate(0," + chartHeight + ")")
        .call(xAxis);

    return [xScale, xBand, xAxis, gX];
};

enter image description here

据我所知,d3决定X轴上出现的刻度数。
为了更好地控制出于缩放目的而出现在X轴上的值,我想了解d3如何确定-在这种情况下-我有16个刻度。
例如,如果我想使刻度线更均匀地间隔,我想每12或6个小时看到一次刻度线怎么办?我的数据每天一致包含0-> 23小时值,但是d3在我的图表上显示随机时间。

1 个答案:

答案 0 :(得分:1)

我只回答标题中的问题(“如何定义轴上的刻度数?” ),而不是您最后做的那个问题(”如果我想使刻度线更均匀地间隔,例如,我想每12或6个小时看到一个刻度线,该怎么办?” ),它不相关且很容易修复(此外,当然是重复的。

您的问题需要侦探工作。当然,我们的旅程始于d3.axisBottom()。如果您查看source code,将会看到回车选择中的滴答数...

tick = selection.selectAll(".tick").data(values, scale).order()

...取决于values,即:

var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues

此行告诉我们,如果tickValues为null(未使用tickValues),则代码应将scale.ticks用于具有ticks方法的刻度(连续的),我们只是序数刻度的刻度域。

这导致我们进入continuous scales。在那里,使用线性标尺(您正在使用的标尺),我们可以在source code上看到scale.ticks返回此值:

scale.ticks = function(count) {
    var d = domain();
    return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
};

但是,由于ticks是从d3.array导入的,因此我们必须go there来查看报价的计算方式。另外,由于我们没有通过count传递任何内容,因此count默认为10

所以,最后,我们到达了at this

start = Math.ceil(start / step);
stop = Math.floor(stop / step);
ticks = new Array(n = Math.ceil(stop - start + 1));
while (++i < n) ticks[i] = (start + i) * step;

或者这个:

start = Math.floor(start * step);
stop = Math.ceil(stop * step);
ticks = new Array(n = Math.ceil(start - stop + 1));
while (++i < n) ticks[i] = (start - i) / step;

取决于steps的值。如果您查看下面的tickIncrement函数,您会看到steps只能是12510(和他们的底片)。

这就是您需要知道上面变量ticks中数组长度的全部。根据起始值和停止值(即,取决于域),有时即使我们的默认计数为10,也有超过10个刻度(在您的情况下为16个),有时又少于10个。

const s = d3.scaleLinear();
  
console.log(s.domain([1,12]).ticks().length);
console.log(s.domain([100,240]).ticks().length);
console.log(s.domain([10,10]).ticks().length);
console.log(s.domain([2,10]).ticks().length);
console.log(s.domain([1,4]).ticks().length);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

如您所见,最后一个示例给了我们16个滴答声。