AntV曲线图实例代码(vue组件)

引言

有在移动端实现光滑曲线图的需求,选择了AntV的库,但官方文档不太行网上案例更少,找起来很麻烦。就把自己做的记录下来,主要是麻烦在AntV的官方文档写得不行,不好查找,给的官方案例又简单又少,api介绍的又比较混乱
我这里主要涉及到对曲线图上的点及点标签的自定义样式
legend不想查组件库的api,所以自己拿div拼了一个
还有就是chart的刷新及传值要深拷贝问题
另外chart有id,这id一定要是唯一的,否则会互相影响

效果

在这里插入图片描述

需求

  1. 光滑曲线
  2. 最低点绿色标签,绿色点;最高点红色标签,红色点;其余灰色(主要是自定义标签需要回调函数麻烦一些)
  3. 无Y轴
  4. 百分数/数字的分别处理
  5. 数据更新

使用代码

项目是vue的,封装成了一个组件,在别的地方可以直接用,使用如下

<line-chart title="实际趋势图" :infos="JSON.parse(JSON.stringify(history))" id="chart1" type="1"></line-chart>
  • title: 图的标题
  • id: 一定要有个id,并且父组件用的时候不同图用不同的id,否则会互相影响如果id是变量,则写成加:id=“idname”
  • infos: 数据,一定要用深拷贝,不然子组件watch不到传过来的数据的变化,watch的只是引用地址
  • type: 0小标题 1大标题 这里是做了两个样式的处理

数据格式

传过去的数据格式如下

     history: [
        {
          name: 'W21',
          value: '40'
        }, {
          name: 'W22',
          value: '38'
        }, {
          name: 'W23',
          value: '64'
        }, {
          name: 'W24',
          value: '56'
        }, {
          name: 'W25',
          value: '44'
        }, {
          name: 'W26',
          value: '77.3'
        }
      ],

同样也支持百分数,如下

     history: [
        {
          name: 'W21',
          value: '40%'
        }, {
          name: 'W22',
          value: '38%'
        }, {
          name: 'W23',
          value: '64%'
        }, {
          name: 'W24',
          value: '56%'
        }, {
          name: 'W25',
          value: '44%'
        }, {
          name: 'W26',
          value: '77.3%'
        }
      ],

组件代码

我template写的是pug,css写的是scss

<!--详情页使用-->
<!--趋势图组件-->
<!--传参type 0:小标题 1:大标题-->
<template lang="pug">
div.line-chart(:class="lineChartClass")
  div.chart-title(:class="titleClass") {{title}}
  div.chart-legend
    div.up-icon.legend-icon
    div.legend-text 最高值
    div.down-icon.legend-icon
    div.legend-text 最低值
  div.chart-content(:id="id")
</template>

<script>
export default {
  name: 'line-chart',
  props: {
    id: String,
    title: String,
    infos: {
      type: Array,
      default () {
        return [{}]
      }
    },
    type: String
  },
  data () {
    return {
      pointColor: [],
      maxValue: null,
      minValue: null
    }
  },
  computed: {
    lineChartClass () {
      if (this.type == 1) { return 'big-line-chart' } else {
        return null
      }
    },
    titleClass () {
      if (this.type == 1) { return 'big-title' } else {
        return null
      }
    },
    chartData () {
      return this.infos.map((item) => {
        if (item.value.indexOf('%') >= 0) { // 有百分号
          return {
            name: item.name,
            value: Number(item.value.replace('%', '')),
            type: 1 // 值类型   0:值,1:百分数
          }
        } else {
          return {
            name: item.name,
            value: Number(item.value),
            type: 0 // 值类型   0:值,1:百分数
          }
        }
      })
    }
  },
  watch: {
    infos (val) {
      if (!this.$chart) {
        this.initChart()
      } else {
        this.$chart.destroy()
        this.initChart()
      }
    }
  },
  mounted () {
    this.initChart()
  },
  methods: {
    initChart () {
      this.calMinMax()
      this.creatChart()
    },
    calMinMax () {
      let valueArray = this.chartData.map((item) => {
        return item.value
      })
      valueArray.sort((a, b) => {
        return a - b
      })
      this.minValue = valueArray[0]
      this.maxValue = valueArray[valueArray.length - 1]
    },
    creatChart () {
      this.$chart = new window.G2.Chart({
        container: this.id,
        forceFit: true,
        height: 200,
        width: 450
      })
      this.$chart.source(this.chartData)
      // this.$chart.tooltip({
      //   crosshairs: {
      //     type: 'line'
      //   }
      // })
      this.$chart.legend(false)// 不要legend
      this.$chart.tooltip(false)
      this.$chart.axis('value', false)// 不要y轴
      this.$chart.axis('name', {
        line: {
          stroke: '#EEEEEE'
        },
        label: {
          textStyle: {
            textAlign: 'center', // 文本对齐方向,可取值为: start center end
            fill: '#666666', // 文本的颜色
            fontSize: '12' // 文本大小
          }
        },
        tickLine: null
      })
      this.$chart.line().position('name*value').shape('smooth')// 曲线图
      this.$chart.point().position('name*value').size(3).color('value', (value) => { // 多个参数,通过回调函数
        if (value === this.minValue) {
          return '#389E0D'
        } else if (value === this.maxValue) {
          return '#F5212D'
        } else {
          return '#666666'
        }
      }).shape('circle').style({
        // stroke: '#fff',
        // lineWidth: 1
      }).label('name*value', {
        htmlTemplate: (name, value) => {
          let color
          const pretext = '<div style="background-color: '
          const midtext = `;color:#FFFFFF;
                border-radius: 2px; margin-top: 12px;
                font-size:10px; font-family:PingFangSC-Medium;
                padding: 2px 4px 2px 4px; transform: scale(.9);">
                    <span style="display: block; transform: scale(.95)">`
          const suftext = '</span></div>'
          if (value.point.value == this.minValue) {
            color = '#389E0D'
            if (value.point.type == 1) { // 百分数时
              return `${pretext}${color}${midtext}${value.point.value}%${suftext}`
            } else { // 数值时
              return `${pretext}${color}${midtext}${value.point.value}${suftext}`
            }
          } else if (value.point.value == this.maxValue) {
            color = '#F5212D'
            if (value.point.type == 1) {
              return `${pretext}${color}${midtext}${value.point.value}%${suftext}`
            } else {
              return `${pretext}${color}${midtext}${value.point.value}${suftext}`
            }
          } else {
            color = '#666'
            if (value.point.type == 1) {
              return `${pretext}${color}${midtext}${value.point.value}%${suftext}`
            } else {
              return `${pretext}${color}${midtext}${value.point.value}${suftext}`
            }
          }
        } })
      this.$chart.render()
    }
  }
}
</script>
<style scoped lang="scss">
.big-line-chart{
  height: 380px!important;
}
.big-title{
  color: #222222!important;
  font-size: 32px!important;
  font-family: PingFangSC-Medium!important;
  line-height: 32px!important;
}
.line-chart{
  height: 370px;
  background-color: white;
  width: 690px;
  padding-bottom: 20px;
  .chart-title {
    color: #666666;
    font-size: 20px;
    text-align: left;
    margin-left: 24px;
    padding-top: 24px;
  }
  .chart-legend{
    margin-left: 24px;
    display: flex;
    align-items: center;
    justify-content: left;
    margin-top: 20px;
    margin-bottom: 14px;
    .legend-icon{
      display: inline-block;
      width: 10px;
      height: 10px;
      border-radius: 5px;
    }
    .legend-text{
      display: inline-block;
      color: #999999;
      font-size: 20px;
    }
    .up-icon{
      background-color: #F5212D;
      margin-right: 10px;
    }
    .down-icon{
      background-color: #389E0D;
      margin: 0 10px 0 10px;
    }
  }

  .max-color{
    color: #F5212D;
  }
  .min-color{
    color: #389E0D;
  }
  .chart-content{
    margin-left: -124px;
  }
}
</style>

猜你喜欢

转载自blog.csdn.net/qq_33712668/article/details/96995556