D3 v4.x学习(1-12)—— 堆栈图探究

堆栈图布局可以计算二维数组每一数据层的基线???

看图说话,堆栈图可以用于三维数据的展示,x轴和y轴 是两个维度,新增了颜色维度,也就是三个维度,堆栈图的好处是可以将数据堆叠起来,关于堆栈图的衍生,用区域生产器绘制堆栈图暂且放一放,本文主要展示上图实现的代码。

<template>
  <div id='svgContainer' style="">
    <div class="every">
      <h3>堆栈图</h3>
      <div class="svg" id="stack"></div>
    </div>
</template>
<script>
import * as d3 from 'd3'
export default {
  methods: {
    stack () {
      let width = 400
      let height = 400
      let padding = {
        left: 40,
        right: 10,
        top: 20,
        bottom: 20
      }
      let margin = 10 // 控制堆栈图的间隙
      let data = [
        {month: '2015-1-1', apples: 3840, bananas: 1920, cherries: 960, oranges: 300},
        {month: '2015-1-2', apples: 1600, bananas: 1440, cherries: 960, oranges: 400},
        {month: '2015-1-3', apples: 640, bananas: 960, cherries: 640, oranges: 200},
        {month: '2015-1-4', apples: 320, bananas: 480, cherries: 640, oranges: 500}
      ]
      // 数据转换器
      let stack = d3.stack()
        .keys(['apples', 'bananas', 'cherries', 'oranges'])
        .order(d3.stackOrderNone)// 使用原始数据的顺序不进行顺序调整
        .offset(d3.stackOffsetNone)
      let stackData = stack(data)
      let colorZ = d3.scaleOrdinal(d3.schemeCategory10) // 这里color其实是第三维度,他代表水果种类
      // x比例尺
      let xScale = d3.scaleBand()
        .range([0, width - padding.left - padding.right])
      // x值域,其实就是月份
      xScale.domain(data.map((d) => d.month))
      let yScale = d3.scaleLinear()
        .range([height - padding.top - padding.bottom, 0])
      // y值域,求的是转化后的数组的最后一个数组中的第二个元素的最大值,绕的我都有点晕,最大值怎么求可以自己写function
      yScale.domain([0, d3.max(stackData[stackData.length - 1], (item) => item[1])])

      // x轴和y轴
      let xAxis = d3.axisBottom().scale(xScale)
      let yAxis = d3.axisLeft(yScale)
      // 绘图
      let svg = d3.select('#stack')
        .append('svg')
        .attr('width', width)
        .attr('height', height)
      // 添加x轴
      svg.append('g')
        .attr('class', 'axis')
        .attr('transform', 'translate(' + padding.left + ',' + (height - padding.bottom) + ')')
        .call(xAxis)
      // 添加y轴
      svg.append('g')
        .attr('class', 'axis')
        .attr('transform', 'translate(' + padding.left + ',' + padding.top + ')')
        .call(yAxis)
      // 将二维数组的第一维剥离,打散成n列
      let rectContainer = svg.selectAll('rectContainer')
        .data(stackData)
        .enter()
        .append('g')
        .attr('class', 'rectContainer')
        .attr('fill', (d, i) => { return colorZ(d.key) })
      // 渲染每一列
      rectContainer.selectAll('rect')
        .data((d) => d)
        .enter()
        .append('rect')
        .attr('x', (d) => { return xScale(d.data.month) + padding.left + margin / 2 })
        .attr('y', (d) => { return yScale(d[1]) + padding.top })
        .attr('width', (d) => { return xScale.bandwidth() - margin })
        .attr('height', (d) => { return height - padding.top - padding.bottom - yScale(d[1] - d[0]) })
        .attr('stroke', '#ccc')

      // 添加描述
      svg.selectAll('circle')
        .data(['apples', 'bananas', 'cherries', 'oranges'])
        .enter()
        .append('circle')
        .attr('cx', (d) => { return width - padding.right - 80 })
        .attr('cy', (d, i) => { return padding.top + 25 * i })
        .attr('r', '6')
        .attr('fill', (d) => { return colorZ(d) })
      let texts = svg.selectAll('textContainer')
        .data(['apples', 'bananas', 'cherries', 'oranges'])
        .enter()
        .append('g')
        .attr('class', 'textContainer')
      texts.append('text')
        .attr('x', (d) => { return width - padding.right - 60 })
        .attr('y', (d, i) => { return padding.top + 25 * i })
        .attr('dy', '0.32em')
        .text((d) => d)
        .attr('fill', (d) => colorZ(d))
    }
  },
  mounted () {
    this.stack()
  }
}
</script>
<style lang="less">
#svgContainer{
  width: 100%;
  height: 100%;
  .every{
    width: 400px;
    height: 425px;
    margin:15px;
    float: left;
    h3{
      margin:0;
      .button{
        float: right;
        margin-right: 20px;
        font-size: 14px;
        cursor: pointer;
        padding: 2px 8px;
        border:1px solid #ccc;
        background: yellowgreen;
        border-radius: 4px;
        &:hover{
          background: violet;
        }
      }
    }
    .svg{
      width: 400px;
      height: 400px;
    }
  }
}
</style>

猜你喜欢

转载自blog.csdn.net/dkr380205984/article/details/81704435