ECharts封装及常用配置整理

23 篇文章 0 订阅
20 篇文章 0 订阅

1 认识ECharts

ECharts,一个基于 JavaScript 的开源可视化图表库

ECharts官网

国内Echarts使用手册网站:
https://www.w3cschool.cn/echarts_tutorial/echarts_tutorial-d5b128yu.html

示例网站:
https://www.isqqw.com/
http://chart.majh.top/
https://www.ppchart.com/#/

2 为什么需要封装echarts

  • 每个开发者在制作图表时都需要从头到尾书写一遍完整的option配置,十分冗余
  • 在同一个项目中,各类图表设计十分相似,甚至是相同,没必要一直做重复工作
  • 可能有一些开发者忘记考虑echarts更新数据的特性,以及窗口缩放时的适应问题。这样导致数据更新了echarts视图却没有更新,窗口缩放引起echarts图形变形问题
2.0 Echarts/mixins/resize.js
export default {
  mounted() {
    window.addEventListener('resize', this.resizeHandler)
  },
  activated() {
    this.resizeHandler()
  },
  methods: {
    resizeHandler() {
      if (this['myChart' + this.domId]) {
        this['myChart' + this.domId].resize()
      }
    }
  }
}
2.1 封装柱状/折线 一体图(1网格)
<!--柱状/折线 一体图(1grid)-->
<template>
  <div
    :id="domId"
    :key="domId"
    :style="{ height: height, width: width,backgroundColor: backgroundColor }"
  />
</template>
<script>
import * as echarts from 'echarts'
import resize from './mixins/resize'
import 'echarts/lib/component/dataZoom'

export default {
  mixins: [resize],
  props: {
    domId: { type: String, default: 'chartId' },
    height: { type: String, default: '300px' },
    width: { type: String, default: '100%' },
    backgroundColor: { type: String, default: '#fff' },
    data: { type: Object, default: null }
  },
  watch: {
    data: {
      handler(val) {
        // 这里使用nextTick解决Error: Initialize failed: invalid dom
        this.$nextTick(() => {
          this.initChart(val)
        })
      },
      deep: true
    }
  },
  mounted() {
    this.initChart(this.data)
  },
  methods: {
    initChart(data) {
      if (!data) {
        return false
      }

      // const yAxis = this.setInterval(data.yAxis, data.series)
      this['myChart' + this.domId] = echarts.init(
        document.getElementById(this.domId)
      )

      this['myChart' + this.domId].clear() // 清空画布,防止缓存

      this['myChart' + this.domId].setOption({
        grid: data.grid || {
          left: '10%',
          top: '15%',
          right: '10%',
          bottom: '25%'
        },
        toolbox: data.toolbox,
        axisPointer: data.axisPointer || null,
        title: data.title
          ? data.title
          : {
            text: null,
            textStyle: {
              fontSize: 10,
              color: '#666666'
            },
            left: '5%'
          },
        legend: data.legend
          ? data.legend
          : {
            data: data.legendData,
            top: 0,
            textStyle: {
              fontSize: 9,
              color: '#666666'
            },
            formatter: function(name) {
              return name.length > 12 ? name.substr(0, 12) + '...' : name
            }
          },
        tooltip: data.tooltip
          ? data.tooltip
          : {
            trigger: 'axis'
          },
        xAxis: data.xAxis,
        // yAxis: yAxis,
        yAxis: data.yAxis,
        dataZoom: data.dataZoom,
        visualMap: data.visualMap,
        series: data.series
      })
    }
    // 根据data来判断y轴的间隔
    // setInterval(yAxis, series) {
    //   let types = new Set()
    //   series.forEach((el) => {
    //     types.add(el.type)
    //   })
    //   types = Array.from(types)
    //   const maxArray = []
    //   const minArray = []
    //   types.forEach((m) => {
    //     let data = []
    //     series.forEach((n) => {
    //       if (m === n.type) {
    //         data = [...data, ...n.data]
    //       }
    //     })
    //     let max = Math.max(...data)
    //     const min = Math.min(...data)
    //     if (max > 0) {
    //       max = parseInt(Math.ceil(max))
    //     } else {
    //       max = parseInt(Math.floor(max))
    //     }
    //     if (max.toString().length === 1) {
    //       // 个位数
    //       if (max > 5) {
    //         max = 10
    //       }
    //       // else {
    //       //   max = 5
    //       // }
    //     } else if (max < 1) {
    //       max = 1
    //     } else {
    //       // 两位以上
    //       let first = ('' + max)[0]
    //       const second = ('' + max)[1]
    //       if (second > 5) {
    //         first = parseInt(first) + 1
    //         for (let i = 0; i < max.toString().length - 1; i++) {
    //           first = first + '0'
    //         }
    //       } else {
    //         first = first + '5'
    //         for (let i = 0; i < max.toString().length - 2; i++) {
    //           first = first + '0'
    //         }
    //       }
    //       max = parseInt(first)
    //     }
    //     maxArray.push(max)
    //     minArray.push(min)
    //   })
    //   yAxis.map((v, i) => {
    //     v.max = Math.ceil(maxArray[i]) // 向上取整
    //     v.min = Math.floor(minArray[i]) // 向下取整
    //     if (v.min > 0) {
    //       v.min = 0
    //     }
    //     if (v.max < 0) {
    //       v.max = 0
    //     }
    //     v.interval = (v.max - v.min) / 5
    //   })
    //   return yAxis
    // }
  }
}
</script>

2.2 封装饼图
<!--饼图-->
<template>
  <div :id="domId" :key="domId" :style="{ height: height, width: '100%',backgroundColor:'#fff' }" />
</template>
<script>
import * as echarts from 'echarts'
import resize from './mixins/resize'
import 'echarts/lib/component/dataZoom'

export default {
  mixins: [resize],
  props: {
    domId: { type: String, default: 'chartId' },
    height: { type: String, default: '300px' },
    data: { type: Object, default: null }
  },
  watch: {
    data: {
      handler(val) {
        // 这里使用nextTick解决Error: Initialize failed: invalid dom
        this.$nextTick(() => {
          this.initChart(val)
        })
      },
      deep: true
    }
  },
  mounted() {
    this.initChart(this.data)
  },
  methods: {
    initChart(data) {
      if (!data) {
        return false
      }
      const that = this
      this['myChart' + this.domId] = echarts.init(
        document.getElementById(this.domId)
      )
      this['myChart' + this.domId].setOption({
        grid: {
          left: '10%',
          top: '15%',
          right: '10%',
          bottom: '25%'
        },
        toolbox: data.toolbox,
        title: {
          text: data.title ? data.title : null,
          textStyle: {
            fontSize: 10,
            color: '#666666'
          },
          left: '5%'
        },
        legend: data.legend ? data.legend : {
          data: data.legendData,
          top: 0,
          textStyle: {
            fontSize: 9,
            color: '#666666'
          },
          formatter: (name) => {
            if (!name) return ''
            return that.getEqualNewlineString(name, 10) // 根据需求修改参数
          }
        },
        tooltip: data.tooltip ? data.tooltip : {
          trigger: 'axis'
        },
        series: data.series
      })
    },
    /**
     * 超出换行的方法
     * @param {String} params 要处理的字符串
     * @param {Number} length 每行显示长度
     * @returns {String}
    */
    getEqualNewlineString(params, length) {
      let text = ''
      const count = Math.ceil(params.length / length) // 向上取整数
      // 一行展示length个
      if (count > 1) {
        for (let z = 1; z <= count; z++) {
          text += params.substr((z - 1) * length, length)
          if (z < count) {
            text += '\n'
          }
        }
      } else {
        text += params.substr(0, length)
      }
      return text
    }
  }
}
</script>

2.3柱状/折线 一体图(2网格)
<!--柱状/折线 一体图(2grid)-->
<template>
  <div :id="domId" :key="domId" :style="{ height: height, width: '100%',backgroundColor:'#fff' }" />
</template>
<script>
import * as echarts from 'echarts'
import resize from './mixins/resize'
import 'echarts/lib/component/dataZoom'

export default {
  mixins: [resize],
  props: {
    domId: { type: String, default: 'chartId' },
    height: { type: String, default: '300px' },
    data: { type: Object, default: null }
  },
  watch: {
    data: {
      handler(val) {
        // 这里使用nextTick解决Error: Initialize failed: invalid dom
        this.$nextTick(() => {
          this.initChart(val)
        })
      },
      deep: true
    }
  },
  mounted() {
    this.initChart(this.data)
  },
  methods: {
    initChart(data) {
      if (!data) {
        return false
      }
      this['myChart' + this.domId] = echarts.init(
        document.getElementById(this.domId)
      )

      this['myChart' + this.domId].clear() // 清空画布,防止缓存

      this['myChart' + this.domId].setOption({
        grid: data.grid
          ? data.grid
          : [
            {
              left: '10%',
              top: '15%',
              right: '10%',
              height: '35%'
            },
            {
              left: '10%',
              top: '50%',
              right: '10%',
              height: '35%'
            }
          ],
        toolbox: data.toolbox,
        title: {
          text: data.title ? data.title : null,
          textStyle: {
            fontSize: 10,
            color: '#666666'
          },
          left: '5%'
        },
        legend: data.legend
          ? data.legend
          : {
            data: data.legendData,
            top: 0,
            textStyle: {
              fontSize: 9,
              color: '#666666'
            },
            formatter: function(name) {
              return name.length > 12 ? name.substr(0, 12) + '...' : name
            }
          },
        tooltip: data.tooltip
          ? data.tooltip
          : {
            trigger: 'axis'
          },
        xAxis: data.xAxis,
        yAxis: data.yAxis,
        dataZoom: data.dataZoom,
        series: data.series
      })
    }
  }
}
</script>

3 ECharts常用配置整理

例子参考

热力图参考例子:https://www.isqqw.com/viewer?id=31895

x轴 / y轴
xAxis: {
	show: true, // 是否显示x轴
	type: 'category', // 坐标轴类型,值category(类目轴)/value(数值轴),与y轴呼应,若x轴配置category则y轴配置value
	inverse: false, // 是否是反向坐标轴
	boundaryGap: ['20%', '20%'],    // 坐标轴两边留白策略,也可以使用布尔值,默认true居中
    axisLine: {
       show: true,    // 是否显示坐标轴轴线
    },
    axisTick: {
       show: true,    // 是否显示坐标轴刻度
       alignWithLabel: true,   //设置x轴刻度线与x轴文字对齐的
    },
    axisLabel: {
        show: true,     // 是否显示刻度标签
        interval: '0',    // 坐标轴刻度标签的显示间隔,在类目轴中有效.0显示所有
        rotate: 90,   // 刻度标签旋转的角度,在类目轴的类目标签显示不下的时候可以通过旋转防止标签之间重叠;旋转的角度从-90度到90度
        margin: 10,    // 刻度标签与轴线之间的距离
        // formatter 刻度标签的内容格式器,支持字符串模板和回调函数两种形式
        formatter: function (params) {
             // 横坐标超长处理
             let newParamsName = ''
             const paramsNameNumber = params.length
             const provideNumber = 15
             const rowNumber = Math.ceil(paramsNameNumber / provideNumber)
             if (paramsNameNumber > provideNumber) {
               for (let p = 0; p < rowNumber; p++) {
                 let tempStr = ''
                 const start = p * provideNumber
                 const end = start + provideNumber
                 if (p == rowNumber - 1) {
                   tempStr = params.substring(start, paramsNameNumber)
                 } else {
                   tempStr = params.substring(start, end) + '\n'
                 }
                 newParamsName += tempStr
               }
             } else {
               newParamsName = params
             }
             return newParamsName
         },
        color: '#FFF',     // 刻度标签文字的颜色
        fontStyle: 'normal',    // 字体的风格(normal无样式;italic斜体;oblique倾斜字体) 
        // 字体的粗细(normal无样式;bold加粗;bolder加粗再加粗;lighter变细;数字定义粗细也可以取值范围100至700)
        fontWeight: 'normal',    
        fontSize: '20',    // 文字字体大小
        align: 'left',     // 文字水平对齐方式,默认自动(left/center/right)
        verticalAlign: 'left',    // 文字垂直对齐方式,默认自动(top/middle/bottom)
        lineHeight: '50',    // 行高
        backgroundColor: 'red', // 文字块背景色,例:#123234, red, rgba(0,23,11,0.3)
    },
    splitLine: {
        show: false // 是否显示网格线
    }
},
legend 图例
legend: {
	show: false
}
tooltip 提示框
tooltip: {
    show: true,  //是否显示提示框组件
    trigger: 'axis',  //触发类型,属性值:item数据项触发/axis坐标轴触发/none不触发
    triggerOn: 'mousemove', //提示框触发条件,mousemove/click/mousemove|click/none。none时可通过action.tooltip.showTip和action.tooltip.hideTip来手动触发和隐藏。也可通过axisPointer.handle来触发或隐藏
    axisPointer: { // 坐标轴指示器,坐标轴触发有效
        type: 'shadow' // 默认为直线,属性值:line直线/shadow阴影/none/cross十字准星
    },
    padding: [5, 10],// 5
    formatter: ()=>{},  //提示框浮层内容格式器,用这个可以修改提示框默认内容/
    // formatter: '{a} <br/>{b} : {c} ({d}%)',
     // formatter: (array) => {
     //   let str = ''
     //   if (array.length > 0) {
     //     array.forEach((v) => {
     //       str = `<span style="color:${v.color}">${str}${v.seriesName}: ${v.value}%</span><br />`
     //     })
     //     str = `${array[0].name}<br />${str}`
     //   }
     //   return str
     // }
     valueFormatter: (value: number | string) => string,  //数值显示部分的格式化回调函数
     // valueFormatter(value) {
     //   return `${value}%`
     // },
}
series 数据项
series: [{
    data: [820, 932, 901, 934, 1290, 1330, 1320],
    type: 'line', // 'bar'
    symbol: 'none',  //取消折点圆圈
    smooth: true,
    color: '#87a9d4',
    tooltip: {
      show: true,
      valueFormatter(value) {
        return `${value}%`
      },
      trigger: 'axis',
      triggerOn: 'mousemove'
     },
    itemStyle: { color: '#c0e5ed' },//图形上的文本标签,可用于说明图形的一些数据信息
    lineStyle: { // 线条样式
        opacity: 0
    },
    markArea: { // 图表标域,常用于标记图表中某个范围的数据
        itemStyle: {
           color: '#c0e5ed'
         },
         data: [
           {
              xAxis: productStart,
              itemStyle: { color: '#f9dec4' }
           },
           {
              xAxis: productEnd
           }
         ]
    },
    markPoint: { //标注打点
       data: [
        //  {
        //        type: 'min',
        //        name: this.$t('maximumDrawdown'),
        //        label: {
        //          show: true,
        //          formatter: '{b}: {c}%'
        //        }
        //  }  
        {
            xAxis: item.tradeDate,
            yAxis: math.multiply(item.yield, 100),
            label: {
              name: this.$t('buyingAndSellingSignals'),
              value: item.tradeDate,
              show: true
            },
            itemStyle: {
               color: item.adjustType === '1' ? '#ee6666' : '#91cc75'
            }
        }
      ],
       symbolSize: 25,
       itemStyle: {
         // color: 'red'
       },
       tooltip: {}
	// tooltip: {
	//   show: true,
	//   trigger: 'item', // 设置item才生效
	//   formatter(params) {
	//   	if (buyDateArr.includes(params.data.xAxis)) {
	//     	  return params.data.xAxis + '</br>' + that.$t('signalBuy')
	//   	} else if (sellDateArr.includes(params.data.xAxis)) {
	//        return params.data.xAxis + '</br>' + that.$t('signalSell')
	//      }
	//   }
	// }
    }
}]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ECharts封装配置项可以通过以下步骤实现: 1. 首先,在Vue项目中安装ECharts依赖。可以使用npm或者cnpm安装,例如:npm install echarts -S 或者 cnpm install echarts -S。\[3\] 2. 在需要使用ECharts的组件中引入ECharts库。可以使用import语句引入echarts,例如:import echarts from 'echarts'。\[3\] 3. 在组件的初始化方法中,使用echarts.init方法初始化ECharts实例,并传入需要绑定的DOM元素和主题(可选)。例如:this.myChart = echarts.init(this.$refs.myEchart, this.theme)。\[1\] 4. 可以设置一些点击回调函数,例如使用myChart.on方法监听点击事件,并在回调函数中触发自定义事件。例如:this.myChart.on('click', (params) => { this.$emit('chartInfo', params) })。\[1\] 5. 在绘制图表的方法中,使用myChart.clear方法清空图表,然后使用myChart.setOption方法设置图表的配置项。例如:this.myChart.clear() this.myChart.setOption(this.myOptions)。\[1\] 6. 如果需要在整个项目中使用ECharts图表盒子组件,可以在main.js中引入并注册为全局组件。例如:import EchartsBox from '@/components/EchartsBox' Vue.component('EchartsBox', EchartsBox)。\[2\] 通过以上步骤,你可以封装ECharts配置项,并在Vue项目中使用ECharts图表。 #### 引用[.reference_title] - *1* *2* [Echarts常用配置与组件封装](https://blog.csdn.net/qq_44209274/article/details/121086228)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [echarts封装配置项](https://blog.csdn.net/weixin_50561602/article/details/120259969)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值