学习D3.js(二十五)实时滑动柱状图

551 阅读2分钟

我正在参加「掘金·启航计划」

引入D3模块

  • 引入整个D3模块。
<!-- D3模块 -->
<script src="https://d3js.org/d3.v7.min.js"></script>

数据

const data = [
  { age_group: 0, people: 4589196 },
  { age_group: 5, people: 4390483 },
  { age_group: 10, people: 4001749 },
  { age_group: 15, people: 3801743 },
  { age_group: 20, people: 3751061 },
  { age_group: 25, people: 3236056 },
  { age_group: 30, people: 2665174 },
  { age_group: 35, people: 2347737 },
  { age_group: 40, people: 2004987 },
  { age_group: 45, people: 1648025 },
  { age_group: 50, people: 1411981 },
  { age_group: 55, people: 1064632 },
  { age_group: 60, people: 887508 },
  { age_group: 65, people: 640212 },
  { age_group: 70, people: 440007 },
  { age_group: 75, people: 265879 },
  { age_group: 80, people: 132449 },
  { age_group: 85, people: 48614 },
  { age_group: 90, people: 20093 }
]
  • 默认格式数据。

添加画布

const width = 600
const height = 400
const margin = { top: 50, right: 50, bottom: 50, left: 100 }

const svg = d3
  .select('.d3Chart')
  .append('svg')
  .attr('width', width + margin.left + margin.right)
  .attr('height', height + margin.top + margin.bottom)

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

比例尺和配置信息

// 比例尺
const x = d3.scaleBand().rangeRound([0, width]).padding(0.1)
const y = d3.scaleLinear().range([height, 0]).domain([0, 10000000])
x.domain(
  data.map(function (d) {
    return d.age_group
  })
)
  • x轴创建序数线性比例尺。传入数据age_group字段数组,用户展示x坐标轴。
  • y轴创建线性比例尺。
const color = d3.scaleOrdinal().range(['#42adf4', '#ff96ca']).domain([1, 2])
  • 创建序数依次比例尺。进行颜色计算。

绘制图表

// 绘制坐标轴
const xAxis = d3.axisBottom(x)
chart.append('g').attr('class', 'axis axis--x').attr('transform', `translate(0, ${height})`).call(xAxis)
chart.append('g').attr('class', 'axis axis--y').call(d3.axisLeft(y))

image.png

  • 绘制坐标轴。
function updateBetter(sex, step) {
  // 第一步
  x.domain(
    data.map(function (d) {
      return d.age_group
    })
  )
  chart.select('.axis--x').call(xAxis)

  // 第二步
  const bars = chart.selectAll('.bar').data(data, (d) => {
    return d.age_group
  })
  bars
    .enter()
    .append('rect')
    .attr('class', 'bar')
    .attr('x', (d) => x(d.age_group))
    .attr('y', (d) => y(0))
    .attr('width', x.bandwidth())
    .attr('height', 0)
    .attr('fill', (d) => color(1))
    .transition('enter-transition')
    .duration(500)
    .attr('y', (d) => y(d.people))
    .attr('height', (d) => height - y(d.people))

  // 第三步
  bars
    .transition('update-transition')
    .duration(500)
    .attr('x', (d) => x(d.age_group))
    .attr('y', (d) => y(d.people))
    .attr('height', (d) => height - y(d.people))
    .attr('fill', (d) => color(1))

  // 第四步
  bars.exit().transition('exit-transition').duration(500).attr('height', 0).attr('y', y(0)).attr('x', 0).remove()

  // 第五步
  data.shift()
  data.push({
    sex: 2,
    age_group: ~~(Math.random() * 300) + '' + ~~(Math.random() * 300),
    people: ~~(Math.random() * 5000000)
  })
}

updateBetter()

4.gif

  • 计算数据重新获取x轴比例尺。并重新绘制x坐标轴
  • 绑定数据,以age_group字段为唯一标识。绘制柱状图并添加加载动画。(唯一标识符作用:第二次执行数据绑定,判断DMO是否存在,存在进行修改操作,不存在执行删除,多出数据进行新增)
  • 创建修改操作,对第二次进行绑定的数据进行修改。
  • 创建删除操作,对无法绑定的DOM元素进行删除。
  • 删除原始数据第一个值,添加一个全新的值。
setInterval(() => {
  updateBetter()
}, 1000)

1.gif

  • 添加时间函数。让柱状图动起来。