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

文章目录

    • 引言
    • 效果
    • 需求
    • 使用代码
    • 数据格式
    • 组件代码

引言

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

效果

AntV曲线图实例代码(vue组件)_第1张图片

需求

  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 = '
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);"> ` const suftext = '
'
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>

你可能感兴趣的:(移动端前端开发,AntV,移动端,图表库)