d3绘制柱状图

主要代码实现如下

const sample = [
  {
    language: 'Rust',
    value: 78.9,
    color: '#000000'
  },
  {
    language: 'Kotlin',
    value: 75.1,
    color: '#00a2ee'
  },
  {
    language: 'Python',
    value: 68.0,
    color: '#fbcb39'
  },
  {
    language: 'TypeScript',
    value: 67.0,
    color: '#007bc8'
  },
  {
    language: 'Go',
    value: 65.6,
    color: '#65cedb'
  },
  {
    language: 'Swift',
    value: 65.1,
    color: '#ff6e52'
  },
  {
    language: 'JavaScript',
    value: 61.9,
    color: '#f9de3f'
  },
  {
    language: 'C#',
    value: 60.4,
    color: '#5d2f8e'
  },
  {
    language: 'F#',
    value: 59.6,
    color: '#008fc9'
  },
  {
    language: 'Clojure',
    value: 59.6,
    color: '#507dca'
  }
];

const margin = 60,
  width = 1000,
  height = 600,
  chartWidth = width - 2 * margin,
  chartHeight = height - 2 * margin

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

const chart = svg.append('g').attr('transform', `translate(${margin}, ${margin})`)

//创建y轴比例尺
const yScale = d3.scaleLinear().range([chartHeight, 0]).domain([0, 100])

//生成y轴
chart.append('g').call(d3.axisLeft(yScale))

//创建x轴比例尺,并设置填充内间距为0.5
const xScale = d3.scaleBand().range([0, chartWidth]).domain(sample.map(s => s.language)).padding(0.5)

//直接通过axisBottom生成x轴,由于要显示到底部,所以应计算位置坐标
chart.append('g').attr('transform', `translate(0, ${chartHeight})`).call(d3.axisBottom(xScale))

//绘制柱状图矩形上的文字提示信息
const bondGroups = chart.append('g').selectAll().data(sample).enter().append('text').attr('class', 'label').attr('y', d => yScale(d.value) - 10).attr('x', d => xScale(d.language)).text(d => `$${d.value}%`)

//创建鼠标hover时的区域
const hoverBox = chart.append('g').attr('class', 'hover')

//渲染出柱状图
chart.append('g').selectAll().data(sample).enter().append('rect').attr('class', 'bar').attr('x', d => xScale(d.language)).attr('y', d => yScale(d.value))
  .attr('height', d => chartHeight - yScale(d.value)).attr('width', xScale.bandwidth())
  .on('mouseenter', function (actual, i) {
    //鼠标进入时,透明度降低,并且有扩大的效果,即x坐标向左平移一段距离,并且宽度增大扩大距离的2倍
    d3.select(this).transition().duration(300).attr('opacity', 0.5).attr('x', d => xScale(d.language) - 5).attr('width', xScale.bandwidth() + 10)

    d3.selectAll('.label').attr('opacity', 0)
    //拿到当前鼠标悬浮矩形的y轴值
    const y = yScale(actual.value)

    //划线
    chart.append('line').attr('class', 'limit').attr('x1', 0).attr('y1', y).attr('x2', chartWidth).attr('y2', y).attr('stroke', 'red').attr('stroke-dasharray', '3 6')

    //鼠标hover时,计算值之间的对比,并显示到柱状图矩形上
    hoverBox.selectAll('text').data(sample).enter().append('text').attr('class', 'divergence').attr('x', d => xScale(d.language)).attr('y', d => yScale(d.value) - 10).text((d, idx) => {
      const divergence = (d.value - actual.value).toFixed(1)

      let text = ''
      if (divergence > 0) text += '+'
      text += `${divergence}%`

      return idx === i ? '' : text
    })
  }).on('mouseleave', function () {
    d3.select(this).transition().duration(300).attr('opacity', 1).attr('x', d => xScale(d.language)).attr('width', xScale.bandwidth())

    d3.selectAll('.divergence').remove()
    d3.selectAll('.label').attr('opacity', 1)
    chart.selectAll('.limit').remove()
  })

  //绘制平行的坐标系轴线,其实是将刻度线反向延长
chart.append('g').attr('class', 'grid').call(
  d3.axisLeft().scale(yScale).tickSize(-chartWidth, 0, 0).tickFormat('')
)

//描述文字
chart.append('text').attr('x', -(chartHeight / 2)).attr('y', -margin / 2).attr('transform', 'rotate(-90)').attr('text-anchor', 'middle').text('Love meter (%)')
chart.append('text').attr('x', chartWidth / 2).attr('y', chartHeight + 40).attr('text-anchor', 'middle').text('Languages')
chart.append('text').attr('x', chartWidth / 2).attr('y', -20).attr('text-anchor', 'middle').text('Most loved programming languages in 2018')

最终实现效果

你可以在这里查看完整代码

See the Pen BOmvKy by Leevare (@leevare) on CodePen.

是不是很炫呢?

代码实现参考自:https://juejin.im/entry/5b9237f4e51d450e877f1419?utm_source=gold_browser_extension

如果您觉得本文对您有用,欢迎捐赠或留言~
微信支付
支付宝

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注