javascript - 在 d3 时间轴的开头添加额外的刻度

标签 javascript d3.js

我一直在研究 x 轴,它会根据别处设置的区间变量来格式化轴上的刻度。这是一个字符串('decade'、'lustrum'、'years'、days' 等)。我让它正常工作,它通常可以完成工作。下面是 17/8/19198 到 24/08/2017 之间的日期范围示例,具有 lustrum(五年)间隔。有一个没有刻度标签的辅助(次)轴,它也根据间隔发生变化/我还为我们的房屋风格添加了一些格式。 示例

enter image description here

我遇到的问题是我想在长轴的开头添加一个额外的勾号,以便它与我们始终标记初始日期的房屋风格相匹配。我使用过 .nice() 但这也会在末尾添加一个勾号,它也默认为轴上的下一个舍入增量所以如果图表从 2009 年开始并且我有一个十年的间隔那么 .nice 会强制图表回到 2000 年,这是不好的

我想实现的是这个 enter image description here他的:

我认为这就像访问轴刻度数组并将 domain()[0] 值移到零位置一样简单。但这似乎不起作用。当我将它们分配给测试变量时,我实际上似乎并没有访问它们。我得到的是每两年一次的日期刻度。

不胜感激,谢谢

这是我的代码:

function xaxisDate() {
    let mindate = new Date(1970, 1, 1);
    let maxdate = new Date(2017, 6, 1);
    let scale = d3.scaleTime()
        .domain([mindate, maxdate])
        .range([0, 220]);
    let frameName;
    let interval = 'lustrum';
    let minorAxis = true;
    let tickSize = 10;
    let minorTickSize = 5;
    let fullYear = false;
    let align = 'bottom';
    let xLabel;
    let xLabelMinor;

    function axis(parent) {
        //scale.nice(getTicks(interval))
        function getAxis(alignment) {
            return {
                top: d3.axisTop(),
                bottom: d3.axisBottom(),
            }[alignment];
        }

        const xAxis = getAxis(align)
            .tickSize(tickSize)
            .ticks(getTicks(interval))
            .tickFormat(tickFormat(interval))
            .scale(scale)

        test = scale.ticks()
        console.log('before',test);

        // console.log('domain',scale.domain()[0])
        // scale.ticks().unshift(scale.domain()[0]);
        // console.log('after',scale.ticks())
        // xAxis.tickValues()

        const xMinor = d3.axisBottom()
            .tickSize(minorTickSize)
            .ticks(getTicksMinor(interval))
            .tickFormat('')
            .scale(scale);

        xLabel = parent.append('g')
            .attr('class', 'axis xAxis axis baseline')
            .call(xAxis);

        if (minorAxis) {
            xLabelMinor = parent.append('g')
                .attr('class', (d) => {
                    const plotHeight = d3.select('.chart-plot').node().getBBox().height;
                    if (plotHeight === tickSize) {
                        return 'axis xAxis';
                    }
                    return 'axis xAxis axis baseline';
                })
                .call(xMinor);
        }

        if (frameName) {
            xLabel.selectAll('.axis.xAxis text')
            .attr('id', frameName + 'xLabel');
            xLabel.selectAll('.axis.xAxis line')
            .attr('id', frameName + 'xTick');
            if (minorAxis) {
                xLabelMinor.selectAll('.axis.xAxis line')
                .attr('id', frameName + 'xTick');
            }
        }

        xLabel.selectAll('.domain').remove();
    }

    function getTicks(interval) {
        console.log('interval',interval)
        return {
            'century' : d3.timeYear.every(100),
            'jubilee': d3.timeYear.every(50),
            'decade': d3.timeYear.every(10),
            'lustrum': d3.timeYear.every(5),
            'years': d3.timeYear.every(1),
            'quarters': d3.timeMonth.every(3),
            'months': d3.timeMonth.every(1),
            'weeks': d3.timeWeek.every(1),
            'days': d3.timeDay.every(1),
            'hours': d3.timeHour.every(1)
        }[interval];
    }
    function getTicksMinor(interval) {
        const test = d3.timeYear.every(1);
        console.log('test', test)
        return {
            'century': d3.timeYear.every(10),
            'jubilee': d3.timeYear.every(10),
            'decade': d3.timeYear.every(1),
            'lustrum': d3.timeYear.every(1),
            'years': d3.timeMonth.every(1),
            'quarters': d3.timeMonth.every(1),
            'months': d3.timeDay.every(1),
            'weeks': d3.timeDay.every(1),
            'days': d3.timeHour.every(1),
            'hours': d3.timeMinute.every(1)
        }[interval];
    }

    function tickFormat(interval) {
        let formatFullYear = d3.timeFormat('%Y'),
        formatYear = d3.timeFormat('%y'),
        formatMonth = d3.timeFormat('%b'),
        formatWeek = d3.timeFormat('%W'),
        formatDay = d3.timeFormat('%d'),
        formatHour = d3.timeFormat('%H:%M');
        return {
            'century': d3.timeFormat('%Y'),
            'jubilee': function(d, i) {
                const format = checkCentury(d, i);
                return format;
            },
            'decade': function(d, i) {
                const format = checkCentury(d, i);
                return format;
            },
            'lustrum':function(d, i) {
                const format = checkCentury(d, i);
                return format;
            },
            'years': function(d, i) {
                const format = checkCentury(d, i);
                return format;
            },
            'quarters':function(d, i) {
                const format = getQuarters(d, i);
                return format;
            },
            'months': function(d, i) {
                const format = checkMonth(d, i);
                return format;
            },
            'weeks':function(d, i) {
                const format = getWeek(d, i);
                return format;
            },
            'days':function(d, i) {
                const format = getDays(d, i);
                return format;
            },
            'hours': function(d, i) {
                const format = getHours(d, i);
                return format;
            },
        }[interval];

        function getHours(d, i) {
            if (d.getHours() === 1 || i === 0) {
                return formatHour(d) + ' ' + formatDay(d);
            }
            return formatHour(d);
        }

        function getDays(d, i) {
            if (d.getDate() === 1 || i === 0) {
                return formatDay(d) + ' ' + formatMonth(d);
            }
            return formatDay(d);
        }

        function getWeek(d, i) {
            if (d.getDate() < 9) {
                return formatWeek(d) + ' ' + formatMonth(d);
            }
            return formatWeek(d);
        }

        function getQuarters(d, i) {
            if (d.getMonth() < 3 && i < 4) {
                return 'Q1 ' + formatFullYear(d);
            }
            if (d.getMonth() < 3) {
                return 'Q1';
            }
            if (d.getMonth() >= 3 && d.getMonth() < 6) {
                return 'Q2';
            }
            if (d.getMonth() >= 6 && d.getMonth() < 9) {
                return 'Q3';
            }
            if (d.getMonth() >= 9 && d.getMonth() < 12) {
                return 'Q4';
            }
        }

        function checkMonth(d, i) {
            if (d.getMonth() === 0 || i === 0) {
                const newYear = d3.timeFormat('%b %Y');
                return newYear(d);
            }
            return formatMonth(d);
        }

        function checkCentury(d, i) {
            if (fullYear || (+formatFullYear(d) % 100 === 0) || (i === 0)) {
                return formatFullYear(d);
            }
            return formatYear(d);
        }
    }
    axis.align = (d) => {
        align = d;
        return axis;
    };
    axis.frameName = (d) => {
        if (d === undefined) return frameName;
        frameName = d;
        return axis;
    };
    axis.scale = (d) => {
        scale = d;
        return axis;
    };
    axis.domain = (d) => {
        scale.domain(d);
        return axis;
    };
    axis.range = (d) => {
        scale.range(d);
        return axis;
    };

    axis.fullYear = (d) => {
        if (d === undefined) return fullYear;
        fullYear = d;
        return axis;
    };
    axis.interval = (d) => {
        interval = d;
        return axis;
    };
    axis.tickSize = (d) => {
        if (!d) return tickSize;
        tickSize = d;
        return axis;
    };
    axis.minorTickSize = (d) => {
        if (!d) return minorTickSize;
        minorTickSize = d;
        return axis;
    };
    axis.minorAxis = (d) => {
        if (d === undefined) return minorAxis;
        minorAxis = d;
        return axis;
    };
    axis.xLabel = (d) => {
        if (d === undefined) return xLabel;
        xLabel = d;
        return axis;
    };
    axis.xLabelMinor = (d) => {
        if (d === undefined) return xLabelMinor;
        xLabelMinor = d;
        return axis;
    };
    return axis;

最佳答案

答案在于 tickValues。然后您需要返回刻度数组的值,正如我所想的那样,将 domain[0] 值移入其中。设置 xAxis 后,您需要插入以下内容:

 let newTicks = scale.ticks(getTicks(interval))
        newTicks.unshift(scale.domain()[0]);
        xAxis.tickValues(newTicks)

关于javascript - 在 d3 时间轴的开头添加额外的刻度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46217208/

相关文章:

javascript - 使用动态输入删除 Javascript 中的一个项目

javascript - 如何突出显示搜索结果的颜色

d3.js - d3js - 如何按顺序插入内容?

javascript - 使用不带 DOT 的 d3.js 的有向无环图

javascript - Angular2 中 IFrame 的跨域问题

javascript - 使用动态值在对象中设置值

javascript - 如何返回数组中所有值的总和?

javascript - arc.centroid 在 D3 中返回 (NaN, NaN)

javascript - 带复选框的平行坐标

javascript - 视觉 : CSS does not apply to D3's svg when using scoped