vue大屏中对echarts基础模板的封装

13 篇文章 11 订阅

 

目录

 

一、下载echarts 、vue-awesome(icon图标)、@jiaminghi/data-view(DataV组件)、lib-flexible(屏幕适配)

二、在main.js中引入

三、封装echarts

四、父子组件传值

五、div包装

六、引用模板

七、使用

八、示例


一、下载echarts 、vue-awesome(icon图标)、@jiaminghi/data-view(DataV组件)、lib-flexible(屏幕适配)

cnpm i -S echart@4.9.0 vue-awesome @jiaminghi/data-view lib-flexible

二、在main.js中引入

import dataV from '@jiaminghi/data-view';
Vue.use(dataV);

// 按需引入vue-awesome图标
import Icon from 'vue-awesome/components/Icon';
import 'vue-awesome/icons/chart-bar.js';
import 'vue-awesome/icons/chart-area.js';
import 'vue-awesome/icons/chart-pie.js';
import 'vue-awesome/icons/chart-line.js';
import 'vue-awesome/icons/align-left.js';

// 全局注册图标
Vue.component('icon', Icon);

// 适配flex
import 'flexible.js';

//引入echart
import echarts from 'echarts'
Vue.prototype.$echarts = echarts

修改flexible.js:

  function refreshRem() {
    var width = docEl.getBoundingClientRect().width;
    // 最小1366px,最大适配2560px
    if (width / dpr < 1366) {
      width = 1366 * dpr;
    } else if (width / dpr > 2560) {
      width = 2560 * dpr;
    }
    // 设置成24等份,设计稿时1920px的,这样1rem就是80px
    var rem = width / 24;
    docEl.style.fontSize = rem + "px";
    flexible.rem = win.rem = rem;
  }

三、封装echarts

echarts/index.vue:

<template>
  <div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>

<script>
import tdTheme from './theme.json' // 引入默认主题
import resizeMixins from "@/utils/resizeMixins";

export default {
  name: 'echart',
  mixins: [resizeMixins],
  props: {
    className: {
      type: String,
      default: 'chart'
    },
    id: {
      type: String,
      default: 'chart'
    },
    width: {
      type: String,
      default: '100%'
    },
    height: {
      type: String,
      default: '2.5rem'
    },
    options: {
      type: Object,
      default: ()=>({})
    }
  },
  data () {
    return {
      chart: null
    }
  },
  watch: {
    options: {
      handler (options) {
        // 设置true清空echart缓存
        this.chart.setOption(options, true)
      },
      deep: true
    }
  },
  mounted () {
    this.$echarts.registerTheme('tdTheme', tdTheme); // 覆盖默认主题
    this.initChart();
  },
  methods: {
    initChart () {
      // 初始化echart
      this.chart = this.$echarts.init(this.$el, 'tdTheme')
      this.chart.setOption(this.options, true)
    }
  }
}
</script>

<style>
</style>

其中的theme.json自己去echarts官网下载。

utils / resizeMixins.js:

// 混入代码 resize-mixins.js
import { debounce } from '@/utils/index.js';
const resizeChartMethod = '$__resizeChartMethod';

export default {
    data() {
        // 在组件内部将图表 init 的引用映射到 chart 属性上
        return {
            chart: null,
        };
    },
    created() {
        window.addEventListener('resize', this[resizeChartMethod], false);
    },
    activated() {
        // 防止 keep-alive 之后图表变形
        if (this.chart) {
            this.chart.resize()
        }
    },
    beforeDestroy() {
        window.removeEventListener('resize', this[resizeChartMethod]);
    },
    methods: {
        // 防抖函数来控制 resize 的频率
        [resizeChartMethod]: debounce(function() {
            if (this.chart) {
                this.chart.resize();
            }
        }, 300)
    },
};

utils/index.js:(防抖函数)

/**
 * @param {Function} fn 防抖函数
 * @param {Number} delay 延迟时间
 */
export function debounce(fn, delay) {
    var timer;
    return function() {
        var context = this;
        var args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function() {
            fn.apply(context, args);
        }, delay);
    };
}

四、父子组件传值

components/bottomLeftChart/chart.vue:

<template>
<!-- 每一个图表都要设置height高度,如下 -->
    <Echart
      :options="options"
      height="4.7rem"
    ></Echart>
</template>

<script>
import Echart from '@/common/echart'
export default {
  data () {
    return {
      options: {},
    };
  },
  components: {
    Echart,
  },
  props: {
    cdata: {
      type: Object,
      default: () => ({})
    },
  },
  watch: {
    cdata: {
      handler (newData) {
        this.options = {
          //这里写options的配置。动态变化的数据从newData中获取
          title:{},
          legend:{},
          xAxis:{
              data:newData.xxx,
              axisLine:{} 
             },
          yAxis:{},
          series:[]
        }
      },
      immediate: true,
      deep: true
    },
  },
}
</script>

 components/bottomLeftChart/index.js:

<template>
  <Chart :cdata="cdata" />
</template>

<script>
import Chart from "./chart.vue";
export default {
  data() {
    return {
      //这里只需要把动态变化的数据传过去就行了。其他不变的option配置不用写。因为option是整合的关 
      //系,而不是替换的关系。
      cdata: {
        lineData:[xxx],
        barData:[xxx]
      }
    };
  },
  components: {
    Chart,
  },
  mounted() {
    this.setData();
  },
  methods: {
    // 根据自己的业务情况修改
    setData() {
      //这里动态注入数据。
      this.cdata={xxx}
    },
  },
};
</script>

五、div包装

card.vue:

<template>
  <div class="card">
    <div class="background">
      <div class="d-flex mb-2 pt-2 pl-2">
        <span class="icon-color">
          <slot name="icon">
              <icon name="chart-pie"></icon>
          </slot>
        </span>
          <span class="fs-md colorText mx-2">{{title}}</span>
           <div  style="width:1.25rem;height:.25rem; position:relative;top:-.0375rem;">
             <slot name="decoration">
             </slot>
          </div>
      </div>
      <div>
        <slot name="content">
            内容区域
        </slot>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  },
  props:{
    title:{
        type:String,
        default:"title"
    }
  },
  components: {
  },
  mounted() {},
  methods: {}
};
</script>

<style lang="scss">
.card {
  padding: 0.15rem ;
  height: 100%;
  min-width: 3.75rem;
  border-radius: 0.0625rem;
  .background {
    border-radius: 0.125rem;
    background-color: rgba(19, 25, 47, 0.6);
    height: 100%;
  }
}
</style>

六、引用模板

<template>
  <card id="bottomLeft" title="数据统计图">
    <icon name="chart-bar" slot="icon"></icon>
    <dv-decoration-1 slot="decoration" />
    <div slot="content">
      <BottomLeftChart />
    </div>
  </card>
</template>

<script>
import card from "@/components/card";
import BottomLeftChart from "@/components/bottomLeftChart";
export default {
  data() {
    return {};
  },
  components: {
    BottomLeftChart,
    card,
  },
  mounted() {},
  methods: {},
};
</script>

七、使用

注意:这里一定要设置父亲的宽和高,因为封装的组件里面的宽高全是100%,所以全由外层的父亲决定宽高。

下面的 <dv-border-box-13>可以更换,见:http://datav.jiaminghi.com/guide/borderBox.html#dv-border-box-1

 <div style="height: 5rem;width:10rem">
      <!-- 每一个板块的宽高由父亲决定 -->
      <dv-border-box-13>
        <bottomLeft />
      </dv-border-box-13>
    </div>

八、示例

效果图:

代码参考:https://blog.csdn.net/qq_40323256/article/details/114890628

components/bottomRightChart/chart.vue:

<template>
  <!-- 每一个图表都要设置height高度,如下 -->
  <Echart :options="options" height="4.7rem"></Echart>
</template>

<script>
import Echart from "@/common/echart";
export default {
  data() {
    return {
      options: {},
    };
  },
  components: {
    Echart,
  },
  props: {
    cdata: {
      type: Object,
      default: () => ({}),
    },
  },
  watch: {
    cdata: {
      handler(newData) {
        this.options = {
          tooltip: {
            show: true,
          },
          xAxis: {
            type: "category",
            data: newData.provinceInfo,
          },
          yAxis: {
            value: "value",
          },
          dataZoom: {
            // 区域缩放组件
            show: false,
            startValue: newData.startValue,
            endValue: newData.endValue,
          },
          series: [
            {
              type: "bar",
              label: {
                show: true,
                position: "top",
                color: "white",
                rotate: 30,
              },
              barWidth: 30,
              data: newData.valueArr,
              itemStyle: {
                barBorderRadius: [15, 15, 0, 0], //[左上角,右上角,左小角,右下角]
                color: (arg) => {
                  let targetColorArr = null;

                  if (arg.value > 300) {
                    targetColorArr = newData.colorArr[0];
                  } else if (arg.value > 200) {
                    targetColorArr = newData.colorArr[1];
                  } else {
                    targetColorArr = newData.colorArr[2];
                  }

                  return new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    // 0%
                    { offset: 0, color: targetColorArr[0] },
                    // 100%
                    { offset: 1, color: targetColorArr[1] },
                  ]);
                },
              },
            },
          ],
        };
      },
      immediate: true,
      deep: true,
    },
  },
};
</script>

components/bottomRightChart/index.vue:

<template>
  <Chart
    :cdata="cdata"
    @mouseover.native="handlerMouseOver()"
    @mouseout.native="handlerMouseOut()"
  />
</template>

<script>
import Chart from "./chart.vue";
export default {
  data() {
    return {
      cdata: {
        colorArr: [],
        provinceInfo: [],
        valueArr: [],
        // 柱形图 区域缩放起点值
        startValue: 0,
        // 柱形图结 区域缩放终点值
        endValue: 9,
      },
      // 定时器
      timerId: null,
    };
  },
  components: {
    Chart,
  },
  mounted() {
    this.updateChart();
    this.startInterval();
  },
  destroyed() {
    clearInterval(this.timerId);
  },
  methods: {
    // 鼠标经过关闭 动画效果
    handlerMouseOver() {
      clearInterval(this.timerId);
    },
    // 鼠标离开 开启动画效果
    handlerMouseOut() {
      this.startInterval();
    },
    // 根据自己的业务情况修改
    updateChart() {
      this.cdata.colorArr = [
        ["#b8e994", "#079992"],
        ["#82ccdd", "#0a3d62"],
        ["#f8c291", "#b71540"],
      ];
      this.cdata.provinceInfo = [
        "上海",
        "北京",
        "广州",
        "深圳",
        "四川",
        "重庆",
        "河北",
        "河南",
        "山东",
        "山西",
        "云南",
        "海南",
        "甘肃",
        "湖北",
        "湖南",
      ];
      this.cdata.valueArr = [
        100,
        200,
        300,
        400,
        123,
        234,
        345,
        456,
        124,
        241,
        134,
        241,
        123,
        111,
        245,
      ];
    },
    // 改变柱形图 区域缩放起始与终点值的函数
    startInterval() {
      // 如果存在则关闭
      this.timerId && clearInterval(this.timerId);

      this.timerId = setInterval(() => {
        this.cdata.startValue++;
        this.cdata.endValue++;
        if (this.cdata.endValue > this.cdata.provinceInfo.length - 1) {
          this.cdata.startValue = 0;
          this.cdata.endValue = 9;
        }
        this.updateChart();
      }, 2000);
    },
  },
};
</script>


views/bottomRight.vue:

<template>
  <card id="bottomRight" title="数据统计图">
    <icon name="chart-bar" slot="icon"></icon>
    <dv-decoration-1 slot="decoration" />
    <div slot="content">
      <BottomRightChart />
    </div>
  </card>
</template>

<script>
import card from "@/components/card";
import BottomRightChart from "@/components/bottomRightChart";
export default {
  data() {
    return {};
  },
  components: {
    BottomRightChart,
    card,
  },
  mounted() {},
  methods: {},
};
</script>

views/menu2/index.vue:

<!--menu2-->
<template>
  <div>
    <div style="height: 5rem; width: 10rem">
      <!-- 每一个板块的宽高由父亲决定 -->
      <dv-border-box-13>
        <bottomRight />
      </dv-border-box-13>
    </div>
  </div>
</template>

<script>
import bottomRight from "../bottomRight";

export default {
  name: "",
  components: { bottomRight },
  data() {
    return {};
  },
  props: {},
  created() {},
  mounted() {},
  computed: {},
  methods: {},
  watch: {},
};
</script>

<style lang="scss" scoped>
</style>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值