【问题标题】:How is the number of ticks on an axis defined?如何定义轴上的刻度数?
【发布时间】:2019-03-23 15:17:48
【问题描述】:

我是 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];
};

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

【问题讨论】:

  • 嘿,你能在 jsfiddle 或其他东西上重现它吗?我有预感如何为您解决它,但我需要先测试一下。
  • @wentjun 好的,我回家后会做的
  • 当然!我已经对我的答案提出了解决方案的粗略草图。一旦我可以访问演示,我将尝试即兴创作。

标签: javascript d3.js


【解决方案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 为空(未使用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 个刻度(在您的情况下为 16 个),有时我们有少于 10 个,即使默认计数是 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);
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"&gt;&lt;/script&gt;

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-02
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-08
    • 2011-07-20
    相关资源
    最近更新 更多