使用vue开发echarts柱状图和折线图基础组件 以及 自定义 tooltips


开发背景就不过多赘述了,直接先来几张效果图吧

1.首先在 package.json 中添加echarts:

{
  "dependencies": {
    "echarts": "^5.0.0",
  }
}

2.然后执行 npm install;

3.接下来就开始编写相关组件文件,代码量较大,建议直接复制下来按步骤运行: 

3.1.创建组件文件  barLineChartPY.vue 代码如下:

<template>
  
  <div style="with: 100%; height: 100%;" :id="id">div>
template>

<script>
export default {
  props: {
    "id": {
      type: String,
      default: "myChart"
    }, 
    "title": {
      type: String,
      default: ""
    }, 
    "color": {
      type: String,
      default: ""
    }, 
    "chartData": {
      type: Object,
      default: undefined
    }, 
    "units": {
      type: String,
      default: ""
    }
  },
  data() {
    return {
      myChart: {},
      colors: ['#3769C9', '#EB9C06', '#80FFA5', '#00DDFF', '#FF0087'],
      xData: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
      // 柱状图的 基础 series  本组件中的默认 series
      seriesBar: {
        name: '',
        type: 'bar',
        // barWidth: 10,
        // stack: 'total',
        // label: {show: false},
        // itemStyle: {
          //这里设置柱形图圆角 [左上角,右上角,右下角,左下角]
          // barBorderRadius: 30,
          // 柱状图 柱子  渐变色  或 单色
          // 前4个参数用于配置渐变色的起止位置, 这4个参数依次对应右/下/左/上四个方位. 而0 0 0 1则代表渐变色从正上方开始
          // offset的范围是0 ~ 1, 用于表示位置
          // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{offset: 0, color: '#033BFF'}, {offset: 1, color: '#01B1FF'}])
        // },
        // emphasis: {
          // focus: 'series',
          // itemStyle: {
            // 柱状图 柱子  渐变色  或 单色
            // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{offset: 0, color: '#01B1FF'}, {offset: 1, color: '#033BFF'}])
          // }
        // },
        data: [123, 150, 100, 300, 500, 1000, 1300, 1100, 800, 600, 500, 350],
        data0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
      },

      // 折线图的 基础 series
      seriesLine: {
        name: '', //this.chartData.seriesName,
        type: "line",
        // smooth: true,  // 圆滑的拐点 默认false
        // showSymbol: true,
        data: [123, 150, 100, 300, 500, 1000, 1300, 1100, 800, 600, 500, 350], // this.chartData.dataArr,
        data0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        // lineStyle: {
          // color: "#00DDFF",
          // width: 1,
        // },
        // areaStyle: {  // color: "transparent",
          // 折线图 面积  渐变色  或 单色
          // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{offset: 0, color: "#00DDFFFF"}, {offset: 1, color: "#00DDFF00"}])
        // },
        // emphasis: {
          // focus: 'series'
        // }
      }
    }
  },
  methods: {
    initChart() {
      var echarts = require("echarts");
      // 基于准备好的dom,初始化echarts实例
      this.myChart = echarts.init(document.getElementById(this.id));
      // 绘制图表---横轴标识--xAxis.data=['1月','2月','3月']
      this.xData = this.chartData.xData && this.chartData.xData.length > 0 ? this.chartData.xData : this.xData;
      
      // debugger
      var flag = false;
      const units = this.units;
      const series = this.getSeries();
      for (var ii = 0, nn = series.length; ii < nn; ii++) {
        if (series[ii].type == 'bar') {
          flag = true;
          break;
        }
      }
      
      var option = {
        grid: {top: "30", bottom: '25', right: '30', left: "35"},
        tooltip: {
          trigger: "axis",
          formatter: function(params) { // 自定义 tooltip 
            // console.log(params);
            var txt = params[0].name;
            for (var i = 0, n = params.length; i < n; i++) {
              var sn = params[i].seriesName, 
                  cl = params[i].color, 
                  val = params[i].value;
                  
              txt += '
' + cl + ';">' + sn + '' + val + units + '
'; } return txt; } }, legend: { show: true, left: 'right', // icon: "circle", // 修改形状 itemHeight: 8, // 修改icon图形大小 itemWidth: 16, // 修改icon图形大小 itemGap: 8, // 修改间距 textStyle: {color: '#fff', fontSize: 12}// padding: [0, -5, 0, 0], // 修改文字和图标距离 }, xAxis: { type: "category", data: this.xData, axisTick: {show: true}, axisLine: {show: true, lineStyle: {color: "#4e9bdf"}}, axisLabel: {textStyle: {color: "#365787"}, margin: 10, rotate: 0}, // rotate x轴标识 旋转角度 boundaryGap: flag, //false:x轴文字贴紧俩边 }, yAxis: { name: (this.units ? ("单位:" + this.units) : ""), type: "value", max: this.chartData.yMax, axisLabel: {textStyle: {color: "#ffffff"}}, //// margin: 10, axisLine: {show: true, lineStyle: {color: "#4e9bdf"}}, splitLine: {lineStyle: {color: "#4e9bdf", type: 'dashed'}}, // dashed-虚线 min: 0, }, series: series }; // console.log(`id -> ${this.id}\noption -> ${JSON.stringify(option)}`); this.myChart.setOption(option); //自适应屏幕 this.updateRsize(this.myChart); }, getSeries() { // 折线图折线数据 --- series[0].name-折线的名称 // series[0].data - 折线的数据 var optSeries = []; const seriesData = this.chartData.seriesData; // console.log(`seriesData.length -> ${seriesData.length}\nseriesData -> ${JSON.stringify(seriesData)}`); if (seriesData && seriesData.length > 0) { for (var i = 0, n = seriesData.length; i < n; i++) { // 判断传递过来的 seriesData[i] 中的要展示的echarts图类型 默认为 bar 类型 柱状图 const type = seriesData[i].type || 'bar'; var series = JSON.parse(JSON.stringify(this.seriesBar)); // 克隆对象 this.seriesBar 赋值给 series if ("bar" != type) series = JSON.parse(JSON.stringify(this.seriesLine)); // 克隆对象 this.seriesLine 赋值给 series // 判断并设置 series.name series.name = seriesData[i].name || series.name; // 判断并处理传递过来的 seriesData[i].data 并设置进 series 中 const tmpSeries = seriesData[i]; if (tmpSeries.data && tmpSeries.data.length > 0) { series.data = tmpSeries.data; // 当数据长度小于 x轴要展示的数据长度时 使用 0 进行补充 if (tmpSeries.data.length < this.xData.length) { for (var j = tmpSeries.data.length, m = this.xData.length; j < m; j++) { series.data.push(0); } } } // 判断并设置 series.stack 独立模式 留空不设置 或 堆叠模式 stack:'total' if (seriesData[i].stack) series.stack = seriesData[i].stack; // bar 类型的 if ('bar' == type) { // 判断并设置柱子宽度 series.barWidth if (seriesData[i].barWidth) series.barWidth = seriesData[i].barWidth; // 判断并设置 series.itemStyle. if (seriesData[i].itemStyle) { // 判断并设置 series.itemStyle.barBorderRadius if (seriesData[i].itemStyle.radius) { if (!series.itemStyle) series.itemStyle = {}; series["itemStyle"]["barBorderRadius"] = seriesData[i].itemStyle.radius } // 判断并设置 series.itemStyle.color const res = this.getItemStyleColor(seriesData[i].itemStyle.color, seriesData[i].itemStyle.colors); if (res) { if (!series.itemStyle) series.itemStyle = {}; series["itemStyle"]["color"] = res; } } } else { // line类型的 // 判断并设置 series.smooth 圆润拐点 series.smooth = seriesData[i].smooth || false; if (seriesData[i].color) series.color = seriesData[i].color // 判断并设置 series.lineStyle if (seriesData[i].lineStyle) { // 判断并设置 series.lineStyle.width if (seriesData[i].lineStyle.width) { if (!series.lineStyle) series.lineStyle = {}; series["lineStyle"]["width"] = seriesData[i].lineStyle.width; } // 判断并设置 series.lineStyle.color const res = this.getItemStyleColor(seriesData[i].lineStyle.color, seriesData[i].lineStyle.colors); if (res) { if (!series.lineStyle) series.lineStyle = {}; series["lineStyle"]["color"] = res; } } // 判断并设置 series.areaStyle if (seriesData[i].areaStyle) { // 判断并设置 series.areaStyle.color const res = this.getItemStyleColor(seriesData[i].areaStyle.color, seriesData[i].areaStyle.colors); if (res) { if (!series.areaStyle) series.areaStyle = {}; series["areaStyle"]["color"] = res; } } } // 判断并设置 series.emphasis if (seriesData[i].emphasis) { if (seriesData[i].emphasis.focus) { if (!series.emphasis) series.emphasis = {}; series["emphasis"]["focus"] = seriesData[i].emphasis.focus; } // 判断并设置 series.emphasis.color const res = this.getItemStyleColor(seriesData[i].emphasis.color, seriesData[i].emphasis.colors); if (res) { if (!series.emphasis) series.emphasis = {}; series["emphasis"]["color"] = res; } } optSeries.push(series); // console.log(`i -> ${i}\nseries -> ${JSON.stringify(series)}\noptSeries -> ${JSON.stringify(optSeries)}`); } } else { // this.seriesBar.data = this.seriesBar.data0; optSeries[0] = this.seriesBar; } // console.log(`optSeries -> ${JSON.stringify(optSeries)}`); return optSeries; }, getItemStyleColor(color, colors) { if (color) { return color; } else if (colors) { const cok = Object.keys(colors); const fx = colors.fx; var cos = []; for (var ii = 0, nn = cok.length; ii < nn; ii++) { if ('fx' != cok[ii] && 0 <= cok[ii] <= 1) cos.push({offset: cok[ii], color: colors[cok[ii]]}); } if (fx && fx.length == 4) { return new echarts.graphic.LinearGradient(fx[0], fx[1], fx[2], fx[3], cos); } else { return new echarts.graphic.LinearGradient(0, 0, 0, 1, cos); } } return undefined; } }, mounted() { // this.initChart(); }, watch: { //动态监听数据是否变化 chartData:function() { this.initChart(); }, }, }; script> <style lang="less" scoped>style>

3.2.创建文件 maintenancefundsChart.vue  并引入刚创建的组件, 代码如下:

<template>
  <div class="cloud_wrap">
    <border-tem-py :width="'100%'">
      
      <div class="title" slot="title">柱状折线图统计div>
      <div class="content-box" slot="content">
        <div class="layui-row layui-col-space10">
          <div class="layui-col-md12">
            <bar-line-chart-py :id="'mfChart'" :chartData="chartData" :units="'万元'" />
          div>
        div>
      div>
    border-tem-py>
  div>
template>
<script>
import barLineChartPy from '../../../../common/barLineChartPY.vue'; // 路径根据自己实际项目中的进行修改
export default {
  components: { barLineChartPy },
  data() {
    return {
      active: 'y',
      chartData: {}
    };
  },
  methods:{
      btnClick(val) {
        this.active = val;
        this.loadData();
      },
      loadData() {
        let params = {
          type: this.active
        };
        this.content = JSON.stringify(params)
        this.chartData = { 
          xData: [], 
          seriesData: [
            {
              name: '统计',  // 必填
              data: [123, 330, 236.5, 500, 360.6,188.8,669.0,115,188,55],   // 必填
              type: 'bar', // 非必填  默认  bar  柱状图
              // stack: 'total',  // 柱状图或折线图展示模式   独立模式 留空不设置  或 堆叠模式 stack:'total'  非必填
              barWidth: 15, // 柱子宽度    非必填
              itemStyle: { // 仅柱状图生效  非必填
              //   // radius: 30, // 柱状图圆角 数字 或 数字数组 [20, 20, 0, 0] [左上角,右上角,右下角,左下角]
              //   // 柱子颜色  color 单色   colors 渐变色 (color / colors 二选一)
              //   // fx 渐变方向 右/下/左/上四个方位. 而0 0 0 1则代表渐变色从正上方开始
              //   // 0、1 渐变的位置 以及 相应位置的颜色  取值范围 0~1
              //   // color: '',
                colors: {'fx': [0, 0, 0, 1], /* 渐变的方向 */ 0: '#2D96F3', 1: '#0B40C3'}
              },
              // // 鼠标移动到柱条上时的样式
              // emphasis: {  // 柱状图 和 折线图均可   非必填
              //   focus: 'series',
              //   // color 与 colors 参看 itemStyle 中的说明
              //   // color: '',
              //   colors: {}
              // }
            },
            {
              name: '统计2',  // 必填
              data: [230, 136, 500, 360, 288, 569, 315, 288, 155],  // 必填
              type: 'line', // 非必填  默认  bar  柱状图
              // smooth: true, // 折线图 转折点是否圆润 默认false    非必填
              // lineStyle: { // 仅折线图生效    非必填
              //   // width: 1,
              //   // color 与 colors 参看 itemStyle 中的说明
              //   color: '#EB9C06',
              //   // colors: {}
              // },
              // areaStyle: {  // 进折线图生效   折线图扫过的面积的样式     非必填
              //   // color 与 colors 参看 itemStyle 中的说明
              //   // color: '',
              //   colors: {}
              // }
            }
          ]
        };
      }
  },
  mounted() {
    this.loadData();
  },
};
script>

<style scoped>
* {
  font-family: MicrosoftYaHei;
}

.cloud_wrap{
  z-index: 1;
  position: relative;
  cursor: pointer;
}

.cloud_wrap .layui-col-md12 {
  min-width: 175px;
  height: 230px;
}
style>

3.3.然后再相关页面中再引入 maintenancefundsChart.vue 并使用即可;

小贴士:

百度Echarts官网:https://echarts.apache.org/examples/zh/index.html

html中的调色与透明度:

vue组件-echarts圆环图以及legend多列展示 和 legend分页展示:

每天进步一点点,点滴记录,积少成多。

以此做个记录,

如有不足之处还望多多留言指教!