• 使用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: ""
        },
        "yMax": {
          type: Number,
          default: undefined
        }
      },
      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",
              //  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 left = 45;
          if (this.yMax && (this.yMax + '').length <= 3) {
            left = 30;
          } else if (this.yMax && (this.yMax + '').length <= 4) {
            left = 40;
          } else if (this.yMax && (this.yMax + '').length <= 6) {
            left = 55;
          } 
          
          var option = {
            grid: {top: "30", bottom: '25', right: '30', left: left},
            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 += '<div><span class="blue-dot middle" style="background: ' + cl + ';"></span><span>' + sn + '' + val + units + '</span></div>'; 
                }
                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.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: {
          deep: true,  //true为进行深度监听,false为不进行深度监听
          handler() {
            this.initChart();
          }
        },
      },
    };
    </script>
    
    <style lang="less" scoped></style>
    View Code

    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: { 
              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: { // 仅折线图生效    非必填
                  //   //  1,
                  //   // color 与 colors 参看 itemStyle 中的说明
                  //   color: '#EB9C06',
                  //   // colors: {}
                  // },
                  // areaStyle: {  // 进折线图生效   折线图扫过的面积的样式     非必填
                  //   // color 与 colors 参看 itemStyle 中的说明
                  //   // color: '',
                  //   colors: {}
                  // }
                }
              ]
            }
        };
      },
      methods:{
          btnClick(val) {
            this.active = val;
            this.loadData();
          },
          loadData() {
            let params = {
              type: this.active
            };
            this.content = JSON.stringify(params)
            // 随机数数组 赋值 生成echarts图
            this.chartData.seriesData[0].data = this.$options.filters['randomNums'](0, 300, 12);
            this.chartData.seriesData[1].data = this.$options.filters['randomNums'](0, 600, 12);
          }
      },
      mounted() {
        this.loadData();
        // 定时器  模拟动态加载数据  实时渲染echarts  实现 实时动态echarts
        const interval = setInterval(() => {
          this.loadData();
        }, 2000);
    
        // 通过$once来监听定时器,在beforeDestroy钩子可以被清除。
        this.$once('hook:beforeDestroy', () => {         
          clearInterval(interval);                                    
        });
      },
    };
    </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中的调色与透明度:https://www.cnblogs.com/jindao3691/p/16093404.html

    vue中随机数、随机数数组过滤器方法以及在methods中调用:https://www.cnblogs.com/jindao3691/p/16122622.html

    vue组件-echarts圆环图以及legend多列展示 和 legend分页展示:https://www.cnblogs.com/jindao3691/p/16093592.html

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

    以此做个记录,

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

  • 相关阅读:
    分布式锁原理及实现方式
    【FAQ】Maven 本地仓库明明有jar包,pom文件还是报错解决办法
    【FAQ】tomcat启动jdk版本不一致
    【Map,HashMap,Vector,List】资料汇总
    【FAQ】调用接口序列化问题
    【docker】docker下安装mysql
    linux tcpdump抓包Post请求
    Springboot 在@Configuration注解的勒种 使用@Autowired或者@value注解 读取.yml属性失败
    Springboot使用Shiro-整合Redis作为缓存 解决定时刷新问题
    CentOS yum 安装nginx
  • 原文地址:https://www.cnblogs.com/jindao3691/p/16093535.html
Copyright © 2020-2023  润新知