echarts 实现数据大屏效果

这个也是工作中已经实现过了,拿出来讲解一下,因为是公司项目,所以项目源代码就不分享了,现在看一下实现过程和echarts各配置

正式效果:

动态效果:(点击下面图片新窗口查看gif效果)

1、实时统计动画效果实现方法:

主要是使用了NPM插件,因为有成熟的,就不必在这个上面浪费时间了

npm i vue-count-to

然后使用页面给予起始值和结束值,每次接口更新时,只需更新结束值即可

import countTo from “vue-count-to”;
<countTo :startVal=’起始值’ :endVal=’结束值’></countTo>

2、保费收入占比动画效果实现方法:

这里主要是利用了echarts的饼状图,通过各属性设置达到该效果,配置如下


  timePie = null;
  // 构建饼状
  myChartPie: any;
  drawLine_pie(item: any, list: any) {
    let _data: any = [];
    let colors = [
      { color: "#ff0000" },
      { color: "#ff9c00" },
      { color: "#ffd200" },
      { color: "#00b4ff" },
      { color: "#0066ff" },
    ];
    list.forEach((item: any, index: number) => {
      _data.unshift({
        value: item.ratio,
        name: item.scope,
        itemStyle: { color: colors[index].color },
      });
    });
    this.myChartPie = echarts.init(item as HTMLDivElement);
    let _myChart = this.myChartPie;
    let _option = {
      top: {
        bottom: "20px",
        containLabel: true,
      },
      legend: {
        bottom: -5,
        itemWidth: 10,
        itemHeight: 10,
        selectedMode: false,
        textStyle: {
          color: "#6381AE",
          fontSize: "12px",
        },
      },
      series: [
        {
          name: "保费收入占比",
          type: "pie",
          radius: ["45%", "68%"],
          height: "98%",
          labelLine: {
            length2: 5,
          },
          label: {
            color: "auto",
            formatter: "{d}%\n",
          },
          labelLayout: function (params) {
            const isLeft = params.labelRect.x < _myChart.getWidth() / 2;
            const points = params.labelLinePoints;
            // Update the end point.
            points[2][0] = isLeft
              ? params.labelRect.x
              : params.labelRect.x + params.labelRect.width;
            return {
              labelLinePoints: points,
            };
          },
          emphasis: {
            label: {
              show: true,
              fontSize: "13px",
            },
          },
          data: _data,
        },
      ],
    };
    _myChart.setOption(_option);
}

3、订单排行效果实现方法:

这里主要是利用了echarts的柱状图,通过各属性设置达到该效果,配置如下

myChartBar: any;
drawLine_bar(item: any, list: any) {
    let _y: any = [];
    let _s: any = [];
    const colors = [
      { color: "#ff0000" },
      { color: "#ff9c00" },
      { color: "#ffd200" },
      { color: "#afff48" },
      { color: "#00b4ff" },
      { color: "#0066ff" },
    ];
    list.forEach((item: any, index: number) => {
      _y.unshift({
        value: item.org_name,
        textStyle: {
          color: "#81ACD2",
        },
      });
      _s.unshift({
        value: item.ratio,
        itemStyle: { color: colors[index].color },
      });
    });
    this.myChartBar = echarts.init(item as HTMLDivElement);
    let _myChart = this.myChartBar;
    let _option = {
      grid: {
        top: "20px",
        left: "50px",
        right: "50px",
        bottom: "20px",
        containLabel: true,
      },
      xAxis: {
        show: false,
      },
      yAxis: {
        type: "category",
        inverse: true,
        data: _y,
        axisLabel: {
          formatter: function (params: any) {
            if (params.length > 4) {
              return params.substr(0, 4);
            } else {
              return params;
            }
          },
        },
        axisTick: {
          show: false,
        },
        axisLine: {
          lineStyle: {
            color: "#1C68DA",
          },
        },
        animationDuration: 300,
        animationDurationUpdate: 300,
      },
      series: [
        {
          realtimeSort: true,
          type: "bar",
          label: {
            show: true,
            position: "right",
            color: "#B9B4B4",
            formatter: "{c}",
          },
          barWidth: 10,
          data: _s,
        },
      ],
      animationDuration: 0,
      animationDurationUpdate: 2500,
      animationEasing: "linear",
      animationEasingUpdate: "linear",
    };
    _myChart.setOption(_option);

}

4、地图和金币飞行效果实现方法:

金币是利用了echarts的航线效果,地图背景是设计师给的一张图,然后做到和我echarts控件地图一样大,一开始也是想用echarts的控件绘制,后来发现就算是绘制两层,也无法实现设计师的效果,所以干脆用一样大的图片做背景,然后echarts地图组件只需构造坐标和航线即可,然后金币进钱的声音更加简单了,增加一个是否播放按钮,开启后如果有单进执行播放即可,默认不播放(因为需要手动触发才会有声音)

// 地图构造
  myChartMap: any;
  async drawLine_map(item: any, list: any) {
    const res: any = await axios.get("/chinaMap.json");
    echarts.registerMap("china", res.data);
    this.myChartMap = echarts.init(item as HTMLDivElement, "none", {
      renderer: "svg",
    });
    let _myChart = this.myChartMap;
    const gb = "image://" + require("../assets/latlon.png");
    const jb = "image://" + require("../assets/jb.gif");
    const jb_dh = "image://" + require("../assets/jb_dh.png");

    const effect = {
      type: "effectScatter",
      coordinateSystem: "geo",
      animation: false, //坐标点是否显示动画
      symbol: gb,
      symbolSize: 14,
      data: list.map((item) => {
        return {
          name: item.name,
          value: item.value,
          itemStyle: {
            normal: {
              color: "#ffff00",
            },
          },
          label: {
            show: false,
            color: "rgb(255, 255, 0)",
            formatter: "{b}",
            offset: [20, 0],
            fontSize: "10",
          },
        };
      }),
    };
    let _option = {
      geo: {
        map: "china",
        zoom: 1.68,
        top: "31.5%",

        label: {
          show: true,
          fontSize: "8",
          color: "#28a7e1",
        },
        itemStyle: {
          borderColor: "#1085AC",
          areaColor: "#1a439a",
        },
        show: false,
        silent: true,
      },
      tooltip: {
        backgroundColor: "#0c1a4f",
        borderColor: "#2ca3ff",
        textStyle: {
          color: "#aaddff",
        },
        position: "right",
        className: "echarts-tooltip",
        triggerOn: "none",
        padding: [5, 10],
        fontSize: 12,
        formatter: function (params) {
          return params.name;
        },
      },
      series: [effect],
    };
    _myChart.setOption(_option);

    var index = 0;
    this.timeMap = setInterval(function () {
      _myChart.dispatchAction({
        type: "showTip",
        seriesIndex: 0,
        dataIndex: index,
      });
      index++;
      if (index > list.length) {
        index = 0;
      }
    }, 3000);

    let isOne = true;
    let gold = [];
    let changeMap = () => {
      let _kz = {};
      if (isOne) {
        isOne = false;
        api
          .post("A" + this.system + "010", { count: this.OrderNumber })
          .then((data) => {
            gold = data;
            _kz = {
              series: [
                effect,
                {
                  type: "scatter",
                  coordinateSystem: "geo",
                  symbol: jb,
                  symbolSize: 25,
                  data: gold.map((item) => {
                    return {
                      name: "1",
                      value: item,
                      itemStyle: {
                        normal: {
                          color: "#ffff00",
                          opacity: 1,
                        },
                      },
                    };
                  }),
                },
              ],
            };
            _myChart.setOption(_kz);
          }).finally(()=>{
            if (gold.length > 0) {
              this.timeMapOut = setTimeout(() => {
                changeMap();
              }, 3000);
            } else {
              isOne = true;
              this.timeMapOut = setTimeout(() => {
                changeMap();
              }, 5000);
            }
          });
      } else {
        isOne = true;
        this.changeMapData().then((data) => {
          _kz = {
            series: [
              effect,
              {
                type: "lines",
                symbolSize: 10,
                effect: {
                  show: true,
                  period: 1,
                  trailLength: 0,
                  symbol: jb_dh,
                  symbolSize: 25,
                  loop: false,
                },
                lineStyle: {
                  color: "#2d9df1", //航线的颜色
                  width: 1,
                  opacity: 0,
                  curveness: 0.2, //  弯曲程度
                },
                data: gold.map((item) => {
                  return {
                    fromName: "1",
                    toName: "金币",
                    coords: [item, [87.68, 51.77]],
                    value: [87.68, 51.77],
                  };
                }),
              },
            ],
          };
          _myChart.setOption(_kz);

          //更新计数
          setTimeout(() => {
            //播放音效
            if (this.isAudio) {
              this.audio.play();
            }
            this.OrderNumber = data;
            this.toOrderNum(this.OrderNumber);
            this.setNumberTransform();
          }, 1000);
        }).finally(()=>{
          this.timeMapOut = setTimeout(() => {
            changeMap();
          }, 5000);
        });
      }
    };
    this.timeMapOut = setTimeout(() => {
      changeMap();
    }, 5000);
  }

5、地图上的累计出函笔数计数效果实现:

这个效果就是手动实现的,没什么好的插件,

<li :class="{'number-item': !isNaN(item) }" v-for="(item,index) in orderNum" :key="index">
   <span v-if="!isNaN(item)">
    <i ref="numberItem">0123456789</i>
   </span>
   <span class="comma" v-else>{{item}}</span>
</li>


  // 订单滚动
  orderNum = ["0", "0", "0", "0", "0", "0"];
  OrderNumber = 823123;
  setNumberTransform() {
    let numberItems = this.$refs.numberItem; // 拿到数字的ref,计算元素数量
    let numberArr: any = this.orderNum.filter((item: any) => !isNaN(item));
    // 结合CSS 对数字字符进行滚动,显示订单数量
    for (let index = 0; index < (numberItems as any).length; index++) {
      const elem = numberItems[index];
      elem.style.transform = `translate(-50%, -${numberArr[index] * 10}%)`;
    }
  }

  // 处理总订单数字
  toOrderNum(num) {
    num = num.toString();
    // 把订单数变成字符串
    if (num.length < 6) {
      num = "0" + num; // 如未满八位数,添加"0"补位
      this.toOrderNum(num); // 递归添加"0"补位
    } else if (num.length === 6) {
      // 订单数中加入逗号
      this.orderNum = num.split(""); // 将其便变成数据,渲染至滚动数组
    }
  }

6、订单资讯这个用的是无缝滚动插件

npm i vue-seamless-scroll

7、成单率/活跃客户数量/近一年出函统计这些都是用的echarts现成的组件,改改颜色而已

总的来说,利用echarts实现难度不是很高,大部分效果都是echarts,吃透echarts就很简单

数据大屏这个看起来很难,实际操作没那么复杂,有一个设计师配合你,如果不是太酷炫的效果,都可以搞定