【问题标题】:D3 Y-axis with multiple labelsD3 Y 轴有多个标签
【发布时间】:2021-08-09 04:30:04
【问题描述】:

我想创建一个 d3 图表,其中 y 轴上的标签将显示在给定的图像中

它们是月份 -> 低于相应季度 -> 低于相应年份

请帮助我如何创建它。

【问题讨论】:

    标签: d3.js graph charts data-visualization timeline


    【解决方案1】:

    这是实现这一目标的一种方法。

    <html>
        <head>
            <script src="https://d3js.org/d3.v7.min.js"></script>
        </head>
        
        <body>
            <div id="chart"></div>
            <script>
                // dimensions
    
                const width = 800;
                const height = 100;
    
                const margin = { left: 20, right: 20 };
    
                // add main svg element
    
                const svg = d3.select('#chart')
                  .append('svg')
                    .attr('width', width)
                    .attr('height', height);
    
                // create x scale
    
                const startDate = new Date(2019, 1, 01);
                const endDate = new Date(2022, 0, 01);
    
                const months = d3.timeMonth.range(startDate, endDate);
    
                const x = d3.scaleTime()
                    .domain([startDate, endDate])
                    .range([margin.left, width - margin.right]);
    
                // Month label
    
                const monthAxis = g => g.append('g')
                    .call(d3.axisBottom(x)
                                   // every month, show abbreviation
                            .ticks(d3.timeMonth.every(1), d3.timeFormat('%b')));
    
                // Quarter label
    
                // map from month index (Jan is 0) to quarter label
                const monthToQuarter = new Map([
                  [2, 'Q1'], // March
                  [5, 'Q2'], // June
                  [8, 'Q3'], // September
                  [11, 'Q4'] // December
                ]);
    
                const quarterAxis = g => g.append('g')
                    // move these labels 30 pixels down
                    .attr('transform', `translate(0,30)`)
                    .call(d3.axisBottom(x)
                            // don't add room for ticks
                            .tickSize(0)
                            // only have labels for Mar, Jun, Sep, and Dec
                            .tickValues(months.filter(d => monthToQuarter.has(d.getMonth())))
                            // show the quarter instead of the date
                            .tickFormat(d => monthToQuarter.get(d.getMonth())))
                    // remove the baseline
                    .call(g => g.select('.domain').remove())
                    // remove tick lines
                    .call(g => g.selectAll('.tick>line').remove())
                
                // Year label
                
                const yearAxis = g => {
                  const group = g.append('g')
                      // move these labels 60 pixels down
                      .attr('transform', `translate(0,60)`);
    
                  // data for line segments for year ranges
                  // lines go from february to january
                  const segments = months.filter(d => d.getMonth() === 1)
                    .map(feb => {
                      const jan = d3.timeMonth.offset(feb, 11);
                      return [feb, jan];
                    });
                  
                  const y = 6;
                  
                  // add lines
                  group.append('g')
                    .selectAll('line')
                    .data(segments)
                    .join('line')
                      .attr('x1', d => x(d[0]))
                      .attr('x2', d => x(d[1]))
                      .attr('y1', y)
                      .attr('y2', y)
                      .attr('stroke', 'lightgray');
    
                  // add circles
                  group.append('g')
                    .selectAll('circle')
                    .data(segments.flat())
                    .join('circle')
                      .attr('cx', d => x(d))
                      .attr('cy', y)
                      .attr('r', 3)
                      .attr('fill', 'lightgray');
    
                  // add labels for years
                  group.append('g')
                      .call(d3.axisBottom(x)
                              // don't add room for ticks
                              .tickSize(0)
                              // center year labels between July and August
                              .tickValues(
                                months
                                  .filter(d => d.getMonth() === 6)
                                  .map(d => d3.timeDay.offset(d, 15))
                              )
                              .tickFormat(d => d.getFullYear()))
                      // remove the baseline
                      .call(g => g.select('.domain').remove())
                      // remove tick lines
                      .call(g => g.selectAll('.tick>line').remove())
                      /*
                        Duplicate the label and make it have a thick
                        white stroke. This provides a white background
                        to the labels so that the line does not show
                        behind them.
    
                        The same technique is used here:
                        https://observablehq.com/@d3/collapsible-tree
                      */
                      .call(g => g.selectAll('.tick>text').clone()
                                     .lower()
                                     .attr('stroke', 'white')
                                     .attr('stroke-width', '4')
                                     .attr('fill', null)
                                     .text(d => d.getFullYear()))
                }
    
                // Draw axes
    
                svg.append('g')
                  .call(monthAxis)
                  .call(quarterAxis)
                  .call(yearAxis);
            </script>
        </body>
    </html>
    

    这增加了三个轴,一个在另一个之下。多年来的轴需要更多的工作来处理线和圆。

    这是输出的样子:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-02
      • 1970-01-01
      • 2012-04-26
      • 2014-08-22
      • 1970-01-01
      • 2017-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多