在d3条形图中仅显示最大值

时间:2017-04-25 11:13:50

标签: javascript d3.js

我有以下条形图。

https://jsfiddle.net/zyjp1abo/

正如您所看到的,值介于1000和1005之间。显示0到1005之间的所有数据都没有意义,因为差异不可见。

我想显示1000和1005之间的条形并相应地更改y轴。简单地使用extent并更改域不起作用,因为条形图是通过底部边距绘制的。我希望它们停在最低值,即1000。

https://jsfiddle.net/zyjp1abo/1/

有什么想法吗?谢谢!

3 个答案:

答案 0 :(得分:1)

更改域名后,此行:

 .attr('height', d => Math.abs(y(d.value) - y(0)))

仍在根据0值计算条形的高度。在this example中计算高度的传统方法是将其基于图表的内部高度(变量h)。

这是一个更新的fiddle

答案 1 :(得分:1)

如果您希望域名从1000转到1005,则应使用d3.extent。那不是问题。

问题在于您使用的是d3.extent,但是您继续使用y(0)来翻译x轴和计算条形高度,这是错误的。您必须使用height和您的边距。

以下是包含这些更改的代码:



var defaults = {
  target: '#chart',
  width: 500,
  height: 170,
  margin: {
    top: 20,
    right: 20,
    bottom: 20,
    left: 50
  },
  yTicks: 5
}

class Barchart {
  constructor(config) {
    Object.assign(this, defaults, config)

    const {
      target,
      width,
      height,
      margin
    } = this
    const w = width - margin.left - margin.right
    const h = height - margin.top - margin.bottom

    const {
      yTicks
    } = this

    this.chart = d3.select(target)
      .attr('width', width)
      .attr('height', height)
      .append('g')
      .attr('transform', `translate(${margin.left}, ${margin.top})`)

    this.x = d3.scaleBand()
      .rangeRound([0, w])
      .padding(0.1)

    this.y = d3.scaleLinear()
      .rangeRound([h, 0])

    this.xAxis = d3.axisBottom(this.x)

    this.chart.append('g')
      .attr('class', 'x axis')

    this.yAxis = d3.axisLeft(this.y)
      .ticks(yTicks)

    this.chart.append('g')
      .attr('class', 'y axis')
  }

  render(data) {
    const {
      x,
      y,
      xAxis,
      yAxis,
      chart
    } = this

    // y.domain(d3.extent(data, v => v.value))
    y.domain(d3.extent(data, v => v.value))

    const domain = data.map(d => d.timestamp)
    x.domain(domain)

    chart.select('.x.axis')
      .attr('transform', `translate(0, ${(defaults.height - defaults.margin.bottom - defaults.margin.top)})`)
      .call(xAxis)

    chart.select('.y.axis')
      .call(yAxis)

    const bars = chart.selectAll('.bar')
      .data(data)

    bars
      .enter()
      .append('rect')
      .attr('class', 'bar')
      .merge(bars)
      .attr('x', d => x(d.timestamp))
      .attr('y', d => y(d.value))
      .attr('width', x.bandwidth())
      .attr('height', d => defaults.height - defaults.margin.bottom - defaults.margin.top - y(d.value))
  }

}

const random = (min = -10, max = 10) => (
  window.Math.floor(window.Math.random() * (max - min + 1)) + min
)

let bar = []
for (let i = 0; i < 20; i++) {
  bar.push({
    timestamp: Date.now() - (19 - i) * 500,
    value: random(1000, 1005)
  })
}

const barchart = new Barchart()
barchart.render(bar)
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg id="chart">
</svg>
&#13;
&#13;
&#13;

PS:您可以简化SVG大小和边距的数学运算。

PPS:关于dataviz是否可以具有非零基线,存在很多争论。我相信,在某些情况下,当变化率比绝对值更重要时,某些类型的图表可以而且应该具有非零基线,特别是折线图。但是,条形图应始终的基线为零。

答案 2 :(得分:0)

y.domain([0, d3.max(data, v => v.value)])

将此处的0更改为1000,以及其他地方