【问题标题】:D3.JS ticks method not working on x-axis that is using datesD3.JS 刻度方法在使用日期的 x 轴上不起作用
【发布时间】:2021-01-09 23:14:04
【问题描述】:

我已经解决这个问题好几天了,但未能找到解决方案。我正在尝试为每一天制作新的 covid 病例图表,但是根据一年多的数据,我无法每天都有一个刻度线。不幸的是,到目前为止我尝试过的所有方法都不会限制 x 轴上的刻度数,结果非常难看。

就目前而言,这是我的 x 轴和刻度代码,我试图将刻度设置为每两个月一次。

const xAxis = d3.axisBottom(x)
                .tickFormat(d3.timeFormat("%b"))
                .ticks(d3.timeMonth.every(2))

但是,我也尝试通过执行以下操作将硬计数添加到滴答数:

const xAxis = d3.axisBottom(x)
                .tickFormat(d3.timeFormat("%b"))
                .ticks(5)

不幸的是,将人数添加到滴答数对我也不起作用。我还尝试移动我的代码以将刻度数限制在我调用 x 轴组的位置,如下所示:

yAxisGroup.call(yAxis)
     .ticks(5)

谁能告诉我我在这里做错了什么?

我不确定它是否需要,但这里是整个组件的代码。整个项目都在做出反应。

import React, { Component } from 'react'
import * as d3 from 'd3'

export default class NewCasesGraph extends Component {

    componentDidUpdate = () => {
       
        let covidArray = Object.entries(this.props.data.cases);

        for(let i = covidArray.length - 1; i > 1; i--){
            let currentDay =parseInt(covidArray[i][1])
            let previousDay =parseInt((covidArray[(i-1)][1]) || 0)
            covidArray[i][1] = currentDay - previousDay
        }

        for(let j = 0; j <covidArray.length; j++){
            covidArray[j][0] = new Date(covidArray[j][0])
        }

        // console.log(covidArray)

        this.updateGraph(covidArray)
    }

    updateGraph(data){
        // console.log('data: ', data)
        
        // tweem
        const widthTween = (d) => {

            let i = d3.interpolate(0, x.bandwidth());

            return function (t){
                return i(t)
            }

        }

        // dimensions
        const dimensions = {
            height: 500,
            width: 1000
        }

        const margin = {top: 20, right: 20, bottom: 100, left: 100}



        const svg = d3.select('.canvas')
            .append('svg')
            .attr('width', dimensions.width)
            .attr('height',dimensions.height)

        const graphWidth = dimensions.width -margin.left - margin.right
        const graphHeight = dimensions.height - margin.top - margin.bottom

        // create graph
        const graph = svg.append('g')
            .attr('width', graphWidth)
            .attr('height', graphHeight)
            .attr('transform', `translate(${margin.left}, ${margin.top})`)

        const xAxisGroup = graph.append('g')
            .attr('transform', `translate(0, ${graphHeight})`);

        // set x axis text
        xAxisGroup.selectAll('text')
            .attr('transform', 'rotate(-40)')
            .attr('text-anchor', 'end')
            .attr('fill','grey')

        const yAxisGroup = graph.append('g');

        // create y scale
        const y = d3.scaleLinear()
            .range([ graphHeight, 0])

        // cretae a band scale
        const x = d3.scaleBand()
            .range([0, graphWidth])
            .paddingInner(0.2)
            .paddingOuter(0.2)

            // create the axae
            const xAxis = d3.axisBottom(x)
                .tickFormat(d3.timeFormat("%b"))
                .ticks(d3.timeMonth.every(2))

            const yAxis = d3.axisLeft(y)
                .ticks(4)
                .tickFormat(d =>  `${d.toLocaleString()} cases`);


            const t = d3.transition().duration(750)

            // join data to rects
            const rects = graph.selectAll('rect')
            .data(data)

            // remove exit selection
            rects.exit().remove();

            // update any scales (domains)
            y.domain([0,d3.max(data, d => d[1])]);
            x.domain(data.map(item => item[0]));

            // update current shapes in the dom
            rects.attr('width', x.bandwidth)
                .attr('fill', 'orange')
                .attr('x', (d) => x(d[0]))

         //handle enter selection
        // append the enter section to the DOM
        rects.enter()
            .append('rect')
            .attr('width', 0)
            .attr('height',0)
            .attr('y', graphHeight)
            .attr('fill', '#5FA19E')
            .attr('x', (d) => x(d[0]))
            .merge(rects)
            .transition(t)
            .attrTween('width', widthTween)
            .attr('y', (d) => {
                return y(d[1])
            })
            .attr('height', d => graphHeight - y(d[1]));

        // add mouseOver
        // graph.selectAll('rect')
        //     .on('mouseover',(event, d) =>{

        //     })

        // call axae
        xAxisGroup.call(xAxis);
        yAxisGroup.call(yAxis);

        console.log(svg)
    }
    render() {
        return (
            <div>
                <h2>New Cases Graph</h2>
                <div className="canvas">

                </div>
            </div>
        )
    }
}

【问题讨论】:

  • 这是意料之中的,因为您使用的是乐队规模。正如我解释的herehere 一样,您可以更改刻度(用于时间刻度)或消除一些刻度。

标签: d3.js


【解决方案1】:

来自ticksd3-axis 方法的文档

This method has no effect if the scale does not implement scale.ticks, as with band and point scales. To set the tick values explicitly, use axis.tickValues. To set the tick format explicitly, use axis.tickFormat.

因此,如果您的域包含一年中的每个日期,请使用以下方法限制刻度数。

xAxis.tickValues(x.domain().filter((e,i)=>i%60==0));

Here's之前回答的问题相同。

【讨论】:

    猜你喜欢
    • 2021-03-05
    • 1970-01-01
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 2012-12-13
    • 1970-01-01
    相关资源
    最近更新 更多