【问题标题】:Bars are going beyond the chart range in d3 bar chart条形超出 d3 条形图中的图表范围
【发布时间】:2021-08-12 14:34:13
【问题描述】:

分组条形图中的条形图在 x 轴上正确定位,但是即使我有一个预定义的范围,一些条形图总是超出图表,一些 y 值等于例如巨大的-31199600。

CodeSandbox

// chart dimensions
const height = 600;
const colorScale = d3.scaleOrdinal().range(['#4FD8DD']);
const itemWidth = 140;
const barWidth = 3;
const barMargin = 5;
const xMargin = 80;
const yMargin = 150;

 const svg = svgEl
      .append('g')
      .attr('class', 'grouped-bar-chart')
      .attr('width', storeData.dataset.length * itemWidth + xMargin * 2)
      .attr('height', height);

    const xScale = d3
      .scaleBand()
      .domain(storeData.dataset.map((d) => d.city))
      .range([0, storeData.dataset.length * itemWidth]);

    const yScale = d3.scaleLinear().range([-120, height - 200]);

    yScale.domain([d3.max(storeData.dataset[0].values, (d) => d.value), 0]);

    // draw chart
    svg
      .selectAll('g.city')
      .data(storeData.dataset, (d) => d.city)
      .enter()
      .append('g')
      .classed('city', true)
      .attr(
        'transform',
        (d) =>
          `translate(${xMargin + xScale(d.city) + itemWidth / 2},${yMargin})`
      )
      .each(function (d) {
        const city = d3.select(this);
        for (let i = 0; i < d.values.length; i++) {
          const y = yScale(d.values[i].value);
          console.log(
            'yScale(d.values[i].value) --->',
            yScale(d.values[i].value)
          );
          console.log('yScale(0) --->', yScale(0));
          const height = yScale(0) - y;
          const x = (i - d.values.length / 2) * (barWidth + barMargin);
          city
            .append('rect')
            .attr('x', x)
            .attr('y', y)
            .attr('width', barWidth)
            .attr('height', height)
            .style('fill', colorScale(i));
        }
      });

【问题讨论】:

    标签: javascript d3.js data-visualization bar-chart


    【解决方案1】:

    此代码将 5000 设置为最大值:

    const maxValue = d3.max(storeData.dataset[0].values, (d) => d.value);
    yScale.domain([maxValue, 0]);
    

    实际上,最大值要高得多(我得到 400000000):

    const maxValue = storeData.dataset.reduce((maxAll, item) => {
      return item.values.reduce((maxItem, val) => 
        Math.max(maxItem, val.value), maxAll);
    }, 0);
        
    console.log('MAX VALUE: ', maxValue);
    

    yScale 设置一个正确的值为domain 上限应该可以解决问题。

    【讨论】:

    • 谢谢你成功了!我有点困惑,因为我认为 d3.max 计算最大值? Math.max 和 d3.max 有什么区别或者 reduce 方法是这种情况的关键?
    • 还奇怪地显示刻度imgur.com/a/XgpoUZ2,多次显示相同的刻度值
    • 我认为d3.max 是用reduce 实现的,基本上它们都做同样的事情:检查所有值并找到最大值。在我们的例子中,d3.max 将不起作用,因为我们有包含值数组的对象数组...
    • 是的,我看到1M显示了两次
    • yAxisTickFormat 有问题。尝试修复它,如果它不起作用,请发布一个新问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多