D3 v4.x学习(3)—— 折线图和区域图实现

  本文承接D3学习(2)的内容,贴出d3 v4.x折线图和区域生成器的代码部分。

<template>
  <div id='svgContainer' style="">
    <div class="every">
      <h3>折线图探究
        <div class="button" @click="changeData('line')">点击触发更新</div>
      </h3>
      <div class="svg" id="line"></div>
    </div>
    <div class="every">
      <h3>区域生成器</h3>
      <div class="svg" id="area"></div>
    </div>
  </div>
</template>
<script>
import * as d3 from 'd3'
export default {
  data () {
    return {
      lineData: [10, 30, 25, 12, 43, 25, 18, 36],
      areaData: [10, 30, 25, 12, 43, 25, 18, 12]
    }
  },
  methods: {
    changeData (which) {
      if (which === 'line') {
        this.lineData.sort(d3.ascending)
      }
    },
    //折线
    line () {
      let _this = this
      let width = 400
      let height = 400
      let padding = {
        left: 30,
        right: 30,
        top: 20,
        bottom: 20
      }
      // 初始化svg画布
      // 处理数据更新做的判断
      document.getElementById('line').innerHTML = ''
      let svg = d3.select('#line')
        .append('svg')
        .attr('width', width + 'px')
        .attr('height', height + 'px')

      let min = d3.min(_this.lineData) - 5
      let max = d3.max(_this.lineData) + 5
      // 比例尺
      let xScale = d3.scaleBand().domain(['1月', '2月', '3月', '4月', '5月', '6月']).range([0, width - padding.left - padding.right])
      let yScale = d3.scaleLinear().domain([min, max]).range([height - padding.top - padding.bottom, 0]) // 值域取反
      let xAxis = d3.axisBottom().scale(xScale)
      let yAxis = d3.axisLeft(yScale)
      // 添加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)
      // 设置折线
      let line = d3.line()
        .x(function (d, i) {
          return padding.left + (width - padding.left - padding.right) / _this.lineData.length * (i + 0.5)
        })
        .y(function (d, i) {
          return yScale(d)
        })
        .curve(d3.curveBasis)
      // 绘制折现路径
      svg.append('path')
        .attr('d', line(_this.lineData))
        .attr('stroke', 'red')
        .attr('stroke-width', '4px')
        .attr('fill', 'none')
        .attr('class', 'line') // 添加动画
    },
    //区域
    area () {
      let _this = this
      let width = 400
      let height = 400
      let padding = {
        left: 30,
        right: 30,
        top: 20,
        bottom: 20
      }
      document.getElementById('area').innerHTML = ''
      let svg = d3.select('#area')
        .append('svg')
        .attr('width', width + 'px')
        .attr('height', height + 'px')
      let xScale = d3.scaleBand().domain(['1月', '2月', '3月', '4月', '5月', '6月']).range([0, width - padding.left - padding.right])
      let yScale = d3.scaleLinear().domain([d3.min(_this.areaData), d3.max(_this.areaData)]).range([height - padding.bottom - padding.top, 0])
      let xAxis = d3.axisBottom().scale(xScale)
      let yAxis = d3.axisLeft().scale(yScale)
      svg.append('g')
        .attr('class', 'axis')
        .attr('transform', 'translate(' + padding.left + ',' + (height - padding.bottom) + ')')
        .call(xAxis)
      svg.append('g')
        .attr('class', 'axis')
        .attr('transform', 'translate(' + padding.left + ',' + padding.top + ')')
        .call(yAxis)

      // 颜色渐变
      let defs = svg.append('defs')
      let linearGradient = defs.append('linearGradient')
        .attr('id', 'linearColor')
        .attr('x1', '0%')
        .attr('y1', '0%')
        .attr('x2', '0%')
        .attr('y2', '0%')
        .attr('y2', '100%')
      let a = d3.rgb(235, 0, 233)
      let b = d3.rgb(133, 0, 187)
      linearGradient.append('stop')
        .attr('offset', '0%')
        .style('stop-color', 'white')
        .transition().duration(2000)
        .style('stop-color', a.toString())
      linearGradient.append('stop')
        .style('stop-color', 'white')
        .transition().duration(2000)
        .attr('offset', '100%')
        .style('stop-color', b.toString())
      let area = d3.area()
        .x(function (d, i) { return padding.left + (width - padding.left - padding.right) / _this.lineData.length * (i + 0.5) })
        .y(function (d, i) { return height - padding.bottom })
        .y1(function (d, i) { return yScale(d) })
        .curve(d3.curveBasis)
      svg.append('path')
        .attr('d', area(_this.areaData))
        .style('fill', 'url(#' + linearGradient.attr('id') + ')')
    },

  },
  watch: {
    lineData () {
      this.line()
    }
  },
  mounted () {
    this.bar()
    this.line()
    this.area()
    this.pie()
    this.forceDirected()
  }
}
</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;
    }
  }
}
// 折线动画
.line{
    stroke-dasharray: 700;             /* //设置虚线的间隔长度 */
    stroke-dashoffset: 700;             /* 设置线段偏移长度 */
    animation: dash 2s forwards;
}
@keyframes dash {
  0%{
    stroke-dashoffset:700;
  }
  100%{
    stroke-dashoffset: 0;
  }
}

</style>

猜你喜欢

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