echarts+vue2实战(一)

目录

一、项目准备

二、(横向分页)柱状图

2.1、动态刷新

2.2、UI调整

2.3、分辨率适配

三、(竖向平移)柱状图

3.1、平移动画

3.2、不同数值显示不同颜色

四、(下拉切换)折线图

4.1、切换图表和分辨率适配

4.2、UI调整

五、(三级分类)饼图

5.1、数据切换

六、圆环饼图

6.1、切换动画

七、地图+散点图

7.1、地图上显示散点

7.2、点击出现单个省份,双击复原

一、项目准备

服务器数据获取链接:电商: 电商数据可视化配套素材

B站链接:57_前端项目_销量趋势图表_通用代码结构_哔哩哔哩_bilibili

  下载下来的文件里面用‘第三天=>代码’项目启动:cmd进入文件夹下npm init -y,然后npm i koa(koa是基于node.js的另一个框架,和Express差不多),直接node app.js即可,终端没有响应就代表启动正常了,在浏览器上输入"http://127.0.0.1:8888/api/seller"可以看到数据.

vue2项目的main.js里:

import './assets/less/global.less';//引入全局的样式文件
import './assets/font/iconfont.css';//引入字体的样式文件
import axios from 'axios'
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/';
Vue.prototype.$http = axios;
import echarts from "echarts";
Vue.prototype.$echarts = echarts;//挂载到原型,可以在全局使用

核心功能:屏幕适配【screenAdapter()】、全屏切换、实时监测【WebSocket】

二、(横向分页)柱状图

代码如下:


<template>
  <div class="com-container">
    <div class="com-chart" ref="seller_ref"></div>
  </div>
</template>
<script>
import * as ets from "echarts";
import chalk from "../../../../public/static/theme/chalk.json";//自己下载
export default {
  data() {
    return {
      chartInstance: null,
      allData: null,
      currentPage: 1,
      totalPage: 0, //一共多少页
      timeId: null, //定时器标识
    };
  },
  mounted() {
    this.initChart();
    this.getData();
    window.addEventListener("resize", this.screenAdapter);
    this.screenAdapter(); //得先主动适配屏幕
    //最原始的Option现在被拆分为initOption、dataOption、adapterOption三部分,各司其职
  },
  destroyed() {
    clearInterval(this.timeId);
    window.removeEventListener("resize", this.screenAdapter);
  },
  methods: {
    // 初始化echartsInstance对象
    initChart() {
      ets.registerTheme("chalk", chalk);
      this.chartInstance = ets.init(this.$refs.seller_ref, "chalk");//主题
      //   对图表初始化配置的控制
      const initOption = {
        //' ▎'这个标记在搜狗输入法上右键,里面的“符号大全”里有
        title: {
          text: "▎商家销售统计",
          left: 20,
          top: 20,
        },
        grid: {
          top: "20%",
          left: "3%",
          right: "6%",
          bottom: "3%",
          containLabel: true, //距离是包含坐标轴上的文字
        },
        xAxis: {
          type: "value",
        },
        yAxis: {
          type: "category",
        },
        tooltip: {
          //划过提示
          trigger: "axis",
          axisPointer: {
            type: "line",
            z: 0,
            lineStyle: {
              color: "#314055",
            },
          },
        },
        series: [
          {
            type: "bar",
            label: {
              show: true,
              position: "right",
              textStyle: {
                color: "white",
              },
            },
            itemStyle: {
            //   barBorderRadius: [0, 33, 33, 0],
              // 指明颜色渐变的方向和不同百分比之下颜色的值
              color: new this.$echarts.graphic.LinearGradient(0, 0, 1, 0, [
                {
                  offset: 0,
                  color: "#5052EE",
                },
                {
                  offset: 1,
                  color: "#AB6EE5",
                },
              ]),
            },
          },
        ],
      };
      this.chartInstance.setOption(initOption);
      //   鼠标移入图表中停止更新,移出则继续更新
      this.chartInstance.on("mouseover", () => {
        clearInterval(this.timeId);
      });
      this.chartInstance.on("mouseout", () => {
        this.startInterval();
      });
    },
    // 获取服务器数据
    async getData() {
      const { data: ret } = await this.$http.get("seller");//axios调接口
      this.allData = ret;
      this.allData.sort((a, b) => {
        return a.value - b.value; //从小到大进行排序
      });
      this.totalPage =
        this.allData.length % 5 == 0
          ? this.allData.length / 5
          : this.allData.length / 5 + 1; //5个元素一页
      this.updateChart();
      this.startInterval();
    },
    // 更新图表
    updateChart() {
      const start = (this.currentPage - 1) * 5;
      const end = this.currentPage * 5;
      const showData = this.allData.slice(start, end);
      const sellerNames = showData.map((item) => {
        return item.name;
      });
      const sellerValues = showData.map((item) => {
        return item.value;
      });
      const dataOption = {
        yAxis: {
          data: sellerNames,
        },
        series: [
          {
            data: sellerValues,
          },
        ],
      };
      this.chartInstance.setOption(dataOption);
    },
    // 动态刷新
    startInterval() {
      if (this.timeId) {
        clearInterval(this.timeId);
      }
      this.timeId = setInterval(() => {
        this.currentPage++;
        if (this.currentPage > this.totalPage) {
          //边界值判断
          this.currentPage = 1;
        }
        this.updateChart();
      }, 3000);
    },
    // 当浏览器大小发生变化时,会进行分辨率适配
    screenAdapter() {
      const titleFontSize = (this.$refs.seller_ref.offsetWidth / 100) * 3.6;
      const adapterOption = {
        title: {
          textStyle: {
            fontSize: titleFontSize,
          },
        },
        tooltip: {
          axisPointer: {
            lineStyle: {
              width: titleFontSize,
            },
          },
        },
        series: [
          {
            barWidth: titleFontSize,
            itemStyle: {
              barBorderRadius: [0, titleFontSize / 2, titleFontSize / 2, 0],
            },
          },
        ],
      };
      this.chartInstance.setOption(adapterOption);
      this.chartInstance.resize(); //手动调用图表对象的resize()才能生效
    },
  },
};
</script>

代码讲解:

2.1、动态刷新

(1)、处理数据:接口返回的数据共15条,每5个元素为一页,通过定时器让currentPage++来实现数据的变化;

(2)、触发时机:echarts自带的事件mouseover、mouseout来开启/停止定时器;

(3)、边界值处理:当currentPage > totalPage时就是边界了,此时currentPage = 1;

2.2、UI调整

  柱子宽度:barWidth、柱子上的文字:label、柱子圆角:itemStyle.barBorderRadius;颜色渐变:itemStyle.colorLinearGradient、柱子划过提示:tooltip

横向渐变原理图:

2.3、分辨率适配

(1)、监听浏览器窗口变化 window.addEventListener("resize", this.screenAdapter);

(2)、根据原始窗口宽度计算一个变化值this.$refs.seller_ref.offsetWidth,将配置(fontSize、width、barWidth、barBorderRadius等)里的具体数字改为适配值

(3)、手动调用图表对象的resize()就OK了

三、(竖向平移)柱状图

代码如下:


<template>
  <div class="com-container">
    <div class="com-chart" ref="rank_ref"></div>
  </div>
</template>
<script>
import * as ets from "echarts";
import chalk from "../../../../public/static/theme/chalk.json"; //自己下载
export default {
  data() {
    return {
      chartInstance: null,
      allData: null,
      startValue: 0, //区域缩放的起点值
      endValue: 9, //区域缩放的终点值
      timeId: null,
    };
  },
  mounted() {
    this.initChart();
    this.getData();
    window.addEventListener("resize", this.screenAdapter);
    this.screenAdapter();
  },
  destroyed() {
    clearInterval(this.timeId);
    window.removeEventListener("resize", this.screenAdapter);
  },
  methods: {
    // 初始化echartsInstance对象
    initChart() {
      ets.registerTheme("chalk", chalk);
      this.chartInstance = ets.init(this.$refs.rank_ref, "chalk");
      const initOption = {
        title: {
          text: "▎地区销售排行",
          left: 20,
          top: 20,
        },
        grid: {
          top: "40%",
          left: "5%",
          right: "5%",
          bottom: "5%",
          containLabel: true, //文字在位置范围内
        },
        tooltip: {
          show: true,
        },
        xAxis: {
          type: "category",
        },
        yAxis: {
          type: "value",
        },
        series: [
          {
            type: "bar",
          },
        ],
      };
      this.chartInstance.setOption(initOption);
      //   鼠标移入图表中动画停止,移出则动画继续
      this.chartInstance.on("mouseover", () => {
        clearInterval(this.timeId);
      });
      this.chartInstance.on("mouseout", () => {
        this.startInterval();
      });
    },
    // 获取服务器数据
    async getData() {
      const { data: ret } = await this.$http.get("rank");
      this.allData = ret;
      this.allData.sort((a, b) => {
        return b.value - a.value; //从大到小进行排序
      });
      this.updateChart();
      this.startInterval();
    },
    // 更新图表
    updateChart() {
      const colorArr = [
        ["#0BA82C", "#4FF778"],
        ["#2E72BF", "#23E5E5"],
        ["#5052EE", "#AB6EE5"],
      ];
      const provinceArr = this.allData.map((item) => {
        return item.name;
      });
      const valueArr = this.allData.map((item) => {
        return item.value;
      });
      const dataOption = {
        xAxis: {
          data: provinceArr,
        },
        dataZoom: {
          show: false,
          startValue: this.startValue,
          endValue: this.endValue,
        },
        series: [
          {
            data: valueArr,
            itemStyle: {
              color: (arg) => {
                //不同数值显示不同颜色
                let targetColorArr = null;
                if (arg.value > 230) {
                  targetColorArr = colorArr[0];
                } else if (arg.value > 200) {
                  targetColorArr = colorArr[1];
                } else {
                  targetColorArr = colorArr[2];
                }
                return new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  {
                    offset: 0,
                    color: targetColorArr[0],
                  },
                  {
                    offset: 1,
                    color: targetColorArr[1],
                  },
                ]);
              },
            },
          },
        ],
      };
      this.chartInstance.setOption(dataOption);
    },
    // 平移动画效果
    startInterval() {
      if (this.timeId) {
        clearInterval(this.timeId);
      }
      this.timeId = setInterval(() => {
        this.startValue++;
        this.endValue++;
        if (this.endValue > this.allData.length - 1) {
          this.startValue = 0;
          this.endValue = 9;
        }
        this.updateChart();
      }, 2000);
    },
    // 当浏览器大小发生变化时,会进行分辨率适配
    screenAdapter() {
      const titleFontSize = (this.$refs.rank_ref.offsetWidth / 100) * 3.6;
      const adapterOption = {
        title: {
          textStyle: {
            fontSize: titleFontSize,
          },
        },
        series: [
          {
            barWidth: titleFontSize,
            itemStyle: {
              barBorderRadius: [titleFontSize / 2, titleFontSize / 2, 0, 0],
            },
          },
        ],
      };
      this.chartInstance.setOption(adapterOption);
      this.chartInstance.resize();
    },
  },
};
</script>

3.1、平移动画

  共21条数据,一次性展示10条数据,借助定时器,每间隔一段时间向左移动一天数据,本质就是控制dataZoomstartValueendValue

3.2、不同数值显示不同颜色

  在itemStyle.color回调函数里可以依次拿到所有结果,根据自己的需求返回不同颜色即可,渐变色就自定义二维数组即可

四、(下拉切换)折线图

代码如下:


<template>
  <div class="com-container">
    <div
      class="title"
      :style="{
        fontSize: `${titleFontSize}px`,
      }"
    >
      <span>{{ "▎" + showTitle }}</span>
      <!-- 下拉箭头 -->
      <span
        class="iconfont title-icon"
        :style="{
          fontSize: `${titleFontSize}px`,
        }"
        @click="showChoice = !showChoice"
        >&#xe6eb;</span
      >
      <div class="select-con" v-show="showChoice" :style="marginStyle">
        <div
          class="select-item"
          v-for="item in selectType"
          :key="item.key"
          @click="handleSelect(item.key)"
        >
          {{ item.text }}
        </div>
      </div>
    </div>
    <div class="com-chart" ref="trend_ref"></div>
  </div>
</template>
<script>
import * as ets from "echarts";
import chalk from "../../../../public/static/theme/chalk.json";
export default {
  data() {
    return {
      chartInstance: null,
      allData: null,
      showChoice: false, //是否显示可选项
      choiceType: "map", //显示的后台数据类型(map、seller、commodity等)
      titleFontSize: 0, //指明标题的字体大小
    };
  },
  computed: {
    selectType() {
      if (!this.allData) {
        return [];
      } else {
        return this.allData.type.filter((item) => {
          return item.key != this.choiceType;
        });
      }
    },
    showTitle() {
      if (!this.allData) {
        return "";
      } else {
        return this.allData[this.choiceType].title;
      }
    },
    marginStyle() {
      return {
        marginLeft: this.titleFontSize / 2 + "px",
      };
    },
  },
  mounted() {
    this.initChart();
    this.getData();
    window.addEventListener("resize", this.screenAdapter);
    this.screenAdapter();
  },
  destroyed() {
    clearInterval(this.timeId);
    window.removeEventListener("resize", this.screenAdapter);
  },
  methods: {
    // 初始化echartsInstance对象
    initChart() {
      ets.registerTheme("chalk", chalk);
      this.chartInstance = ets.init(this.$refs.trend_ref, "chalk");
      const initOption = {
        grid: {
          left: "3%",
          top: "35%",
          right: "4%",
          bottom: "1%",
          containLabel: true, //文字在位置范围内
        },
        tooltip: {
          trigger: "axis", //工具提示
        },
        legend: { right: 20, top: "15%", icon: "circle" }, //图例位置和形状
        xAxis: {
          type: "category",
          boundaryGap: false, //紧挨边缘
        },
        yAxis: {
          type: "value",
        },
      };
      this.chartInstance.setOption(initOption);
    },
    // 获取服务器数据
    async getData() {
      const { data: ret } = await this.$http.get("trend");
      this.allData = ret;
      this.updateChart();
    },
    // 更新图表
    updateChart() {
      const colorArr1 = [
        "rgba(255,151,175,0.5)",
        "rgba(126,248,209,0.5)",
        "rgba(244,247,157,0.5)",
        "rgba(116,201,251,0.5)",
        "rgba(247,199,164,0.5)",
      ]; //半透明颜色值
      const colorArr2 = [
        "rgba(255,151,175,0)",
        "rgba(126,248,209,0)",
        "rgba(244,247,157,0)",
        "rgba(116,201,251,0)",
        "rgba(247,199,164,0)",
      ]; //全透明颜色值
      const timeArr = this.allData.common.month; //类目轴数据
      const valueArr = this.allData[this.choiceType].data;
      const seriesArr = valueArr.map((item, index) => {
        return {
          name: item.name,
          type: "line",
          data: item.data,
          stack: this.choiceType, //堆叠图
          areaStyle: {
            //区域面积、颜色渐变
            color: new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
              {
                offset: 0,
                color: colorArr1[index],
              },
              {
                offset: 1,
                color: colorArr2[index],
              },
            ]),
          },
        };
      }); //y轴数据
      const legendArr = valueArr.map((item) => {
        return item.name;
      }); //图例数据
      const dataOption = {
        xAxis: {
          data: timeArr,
        },
        legend: {
          data: legendArr,
        },
        series: seriesArr,
      };
      this.chartInstance.setOption(dataOption);
    },
    // 当浏览器大小发生变化时,会进行分辨率适配
    screenAdapter() {
      this.titleFontSize = (this.$refs.trend_ref.offsetWidth / 100) * 3.6;
      const adapterOption = {
        legend: {
          //图例和文字大小适配
          itemWidth: this.titleFontSize,
          itemHeight: this.titleFontSize,
          itemFap: this.titleFontSize,
          textStyle: {
            fontSize: this.titleFontSize / 2,
          },
        },
      };
      this.chartInstance.setOption(adapterOption);
      this.chartInstance.resize();
    },
    handleSelect(currentType) {
      this.choiceType = currentType;
      this.updateChart();
      this.showChoice = false;
    },
  },
};
</script>
<style lang='less' scoped>
.title {
  position: absolute;
  left: 240px;
  top: 20px;
  z-index: 10;
  color: white;
  .title-icon {
    margin-left: 10px;
    cursor: pointer;
  }
  .select-on {
    background-color: #222733;
  }
}
</style>

代码讲解:

4.1、切换图表和分辨率适配

(1)、可选项:下拉出现列表,列表过滤掉已选择数据,选中后更新数据,列表消失;

(2)、通过全局变量this.titleFontSize给图例、标题、下拉选择项的字体大小进行设置,视图里的样式适配:fontSize: `${titleFontSize}px`

4.2、UI调整

  坐标轴设置:grid、紧挨边缘:xAxis.boundaryGap、图例位置和形状:legend、区域面积和颜色渐变:itemStyle.colorLinearGradient、工具提示:tooltip

区域面积颜色渐变原理图:

图例注意事项:

五、(三级分类)饼图

代码如下:


<template>
  <div class="com-container">
    <div class="com-chart" ref="hot_ref"></div>
    <!-- 左右箭头 -->
    <span class="iconfont arr-left" @click="toLeft" :style="comStyle">&#xe6ef;</span>
    <span class="iconfont arr-right" @click="toRight" :style="comStyle">&#xe6ed;</span>
    <!-- 一级标题 -->
    <span class="cat-name" :style="comStyle">{{ catName }}系列</span>
  </div>
</template>
<script>
import * as ets from "echarts";
import chalk from "../../../../public/static/theme/chalk.json"; //自己下载
export default {
  data() {
    return {
      chartInstance: null,
      allData: null,
      currentIndex: 0, //一级分类的下标
      titleFontSize: 0,
    };
  },
  computed: {
    catName() {
      if (!this.allData) {
        return "";
      } else {
        return this.allData[this.currentIndex].name;
      }
    },
    comStyle() {
      return {
        fontSize: `${this.titleFontSize}px`,
      };
    },
  },
  mounted() {
    this.initChart();
    this.getData();
    window.addEventListener("resize", this.screenAdapter);
    this.screenAdapter();
  },
  destroyed() {
    window.removeEventListener("resize", this.screenAdapter);
  },
  methods: {
    // 初始化echartsInstance对象
    initChart() {
      ets.registerTheme("chalk", chalk);
      this.chartInstance = ets.init(this.$refs.hot_ref, "chalk");
      const initOption = {
        title: {
          text: "▎热销商品销售金额占比统计",
          left: 20,
          top: 20,
        },
        legend: {
          //图例位置和文字
          top: "10%",
          right: "5%",
          icon: "cicle",
        },
        tooltip: {
          show: true,
          formatter: (arg) => {
            const thirdCategory = arg.data.children;
            let total = 0;
            thirdCategory.forEach((item) => {
              total += item.value;
            });
            let retSrt = "";
            thirdCategory.forEach((item) => {
              retSrt += `${item.name}:${
                parseInt((item.value / total) * 100) + "%"
              }<br/>`;
            });
            return retSrt;
          },
        }, //划过显示该二级模块对应的三级类别
        series: [
          {
            type: "pie",
            label: {
              show: false,
            },
            emphasis: {
              //默认不显示文字,高亮状态下才显示文字
              label: {
                show: true,
              },
              labelLine: {
                show: false,
              },
            },
          },
        ],
      };
      this.chartInstance.setOption(initOption);
    },
    // 获取服务器数据
    async getData() {
      const { data: ret } = await this.$http.get("hotproduct");
      this.allData = ret;
      this.allData.sort((a, b) => {
        return b.value - a.value;
      });
      this.updateChart();
    },
    // 更新图表
    updateChart() {
      const legendData = this.allData[this.currentIndex].children.map(
        (item) => {
          return item.name;
        }
      );
      const seriesData = this.allData[this.currentIndex].children.map(
        (item) => {
          return {
            name: item.name,
            value: item.value,
            children: item.children, //为了在tooltip中的回调函数中拿到对应的三级类别
          };
        }
      );
      const dataOption = {
        legend: {
          data: legendData,
        },
        series: [
          {
            data: seriesData,
          },
        ],
      };
      this.chartInstance.setOption(dataOption);
    },
    // 当浏览器大小发生变化时,会进行分辨率适配
    screenAdapter() {
      this.titleFontSize = (this.$refs.hot_ref.offsetWidth / 100) * 3.6;
      const adapterOption = {
        title: {
          textStyle: {
            fontSize: this.titleFontSize,
          },
        },
        legend: {
          itemWidth: this.titleFontSize / 2,
          itemHeight: this.titleFontSize / 2,
          itemGap: this.titleFontSize / 2,
          textStyle: {
            fontSize: this.titleFontSize / 2,
          },
        },
        series: [
          {
            radius: this.titleFontSize * 4.5,
            center: ["50%", "50%"],
          },
        ],
      };
      this.chartInstance.setOption(adapterOption);
      this.chartInstance.resize();
    },
    toLeft() {
      this.currentIndex--;
      if (this.currentIndex < 0) {
        this.currentIndex = this.allData.length - 1;
      }
      this.updateChart();
    },
    toRight() {
      this.currentIndex++;
      if (this.currentIndex > this.allData.length - 1) {
        this.currentIndex = 0;
      }
      this.updateChart();
    },
  },
};
</script>
<style lang='less' scoped>
.arr-left {
  position: absolute;
  left: 20%;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
  color: white;
}
.arr-right {
  position: absolute;
  right: 10%;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
  color: white;
}
.cat-name {
  position: absolute;
  right: 10%;
  bottom: 10%;
  color: white;
}
</style>

5.1、数据切换

    左右箭头类似轮播图,依靠currentIndex的变化展示一级类别数据,饼图模块对应二级数据,鼠标划到该模块,会展示三级类别的占比,这个需要在组装数据时将三级数据追加进去

六、圆环饼图

代码如下:


<template>
  <div class="com-container">
    <div class="com-chart" ref="stock_ref"></div>
  </div>
</template>
<script>
import * as ets from "echarts";
import chalk from "../../../../public/static/theme/chalk.json"; //自己下载
export default {
  data() {
    return {
      chartInstance: null,
      allData: null,
      currentIndex: 0, //当前显示的数据
      timerId: null, //定时器标识
    };
  },
  mounted() {
    this.initChart();
    this.getData();
    window.addEventListener("resize", this.screenAdapter);
    this.screenAdapter();
  },
  destroyed() {
    window.removeEventListener("resize", this.screenAdapter);
    clearInterval(this.timerId);
  },
  methods: {
    // 初始化echartsInstance对象
    initChart() {
      ets.registerTheme("chalk", chalk);
      this.chartInstance = ets.init(this.$refs.stock_ref, "chalk");
      const initOption = {
        title: {
          text: "▎库存和销量分析",
          left: 20,
          top: 20,
        },
        series: [
          {
            type: "pie",
          },
        ],
      };
      this.chartInstance.setOption(initOption);
      this.chartInstance.on("mouseover", () => {
        clearInterval(this.timerId);
      });
      this.chartInstance.on("mouseout", () => {
        this.startInterval();
      });
    },
    // 获取服务器数据
    async getData() {
      const { data: ret } = await this.$http.get("stock");
      this.allData = ret;
      this.updateChart();
      this.startInterval();
    },
    // 更新图表
    updateChart() {
      const centerArr = [
        ["18%", "40%"],
        ["50%", "40%"],
        ["82%", "40%"],
        ["34%", "75%"],
        ["66%", "75%"],
      ];
      const colorArr = [
        ["#4FF778", "#0BA82C"],
        ["#E5DD45", "#E8B11C"],
        ["#E8821C", "#E55445"],
        ["#5052EE", "#AB6EE5"],
        ["#23E5E5", "#2E72BF"],
      ];
      const start = this.currentIndex * 5;
      const end = (this.currentIndex + 1) * 5;
      const showData = this.allData.slice(start, end);
      const seriesArr = showData.map((item, index) => {
        return {
          type: "pie",
          radius: [110, 100],
          center: centerArr[index],
          hoverAnimation: false, //关闭鼠标移入到饼图时的动画效果
          labelLine: {
            show: false, //隐藏模块指示线
          },
          label: {
            position: "center",
            color: colorArr[index][0],
          },
          data: [
            {
              name: item.name + "\n" + item.sales, //圆环内文字
              value: item.sales,
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0, [
                  {
                    offset: 0,
                    color: colorArr[index][0],
                  },
                  {
                    offset: 1,
                    color: colorArr[index][1],
                  },
                ]),
              },
            }, //圆环渐变颜色
            {
              value: item.stock,
              itemStyle: {
                color: "#313743",
              },
            },
          ],
        };
      });
      const dataOption = {
        series: seriesArr,
      };
      this.chartInstance.setOption(dataOption);
    },
    // 当浏览器大小发生变化时,会进行分辨率适配
    screenAdapter() {
      let titleFontSize = (this.$refs.stock_ref.offsetWidth / 100) * 3.6;
      const innerRadius = titleFontSize * 2;
      const outterRadius = innerRadius * 1.125;
      const adapterOption = {
        title: {
          textStyle: {
            fontSize: titleFontSize,
          },
        },
        series: [
          {
            type: "pie",
            radius: [outterRadius, innerRadius],
            label: {
              fontSize: titleFontSize / 2,
            },
          },
          {
            type: "pie",
            radius: [outterRadius, innerRadius],
            label: {
              fontSize: titleFontSize / 2,
            },
          },
          {
            type: "pie",
            radius: [outterRadius, innerRadius],
            label: {
              fontSize: titleFontSize / 2,
            },
          },
          {
            type: "pie",
            radius: [outterRadius, innerRadius],
            label: {
              fontSize: titleFontSize / 2,
            },
          },
          {
            type: "pie",
            radius: [outterRadius, innerRadius],
            label: {
              fontSize: titleFontSize / 2,
            },
          },
        ],
      };
      this.chartInstance.setOption(adapterOption);
      this.chartInstance.resize();
    },
    startInterval() {
      if (this.timerId) {
        clearInterval(this.timerId);
      }
      this.timerId = setInterval(() => {
        this.currentIndex++;
        if (this.currentIndex > 1) {
          this.currentIndex = 0;
        }
        this.updateChart(); //currentIndex更改后,刷新界面
      }, 5000);
    },
  },
};
</script>

6.1、切换动画

currentIndex标识当前页数,每一页显示5个圆,每5秒更新一次start和end,达到动态切换

UI调整:

hoverAnimation: false, //关闭鼠标移入到饼图时的动画效果

labelLine: {show: false, },//隐藏模块指示线

七、地图+散点图

<template>
  <div class="com-container" @dblclick="revertMap">
    <div class="com-chart" ref="map_ref"></div>
  </div>
</template>
<script>
import * as ets from "echarts";
import axios from "axios";
import { getProvinceMapInfo } from "@/utils/map_utils";
import chalk from "../../../../public/static/theme/chalk.json"; //自己下载
export default {
  data() {
    return {
      chartInstance: null,
      allData: null,
      mapData: {}, //所获取的省份的地图矢量数据
    };
  },
  mounted() {
    this.initChart();
    this.getData();
    window.addEventListener("resize", this.screenAdapter);
    this.screenAdapter(); //得先主动适配屏幕
  },
  destroyed() {
    window.removeEventListener("resize", this.screenAdapter);
  },
  methods: {
    // 初始化echartsInstance对象
    async initChart() {
      ets.registerTheme("chalk", chalk);
      this.chartInstance = ets.init(this.$refs.map_ref, "chalk");
      // 使用axios获取本地json数据
      const res = await axios.get(
        "http://10.52.12.xx:8080/static/map/china.json"
      );
      this.$echarts.registerMap("china", res.data);
      const initOption = {
        title: {
          text: "▎商家分布",
          left: 20,
          top: 20,
        },
        geo: {
          type: "map",
          map: "china",
          top: "5%",
          bottom: "5%",
          itemStyle: {
            areaColor: "#2E72BF", //地图颜色
            borderColor: "#333", //地图分界线颜色
          },
        },
        legend: {
          left: "5%",
          bottom: "5%",
          orient: "vertical", //图例垂直摆放
        },
      };
      this.chartInstance.setOption(initOption);
      // 监听点击事件、获取所点击省份的矢量地图数据、显示省份、回到中国地图
      this.chartInstance.on("click", async (arg) => {
        const provinceInfo = getProvinceMapInfo(arg.name);
        // 判断当前所点击的这个省份的地图矢量数据在mapData中是否存在
        if (!this.mapData[provinceInfo.key]) {
          const ret = await axios.get(
            "http://10.52.12.xx:8080" + provinceInfo.path
          );
          this.mapData[provinceInfo.key] = ret.data;
          this.$echarts.registerMap(provinceInfo.key, ret.data);
        }
        const changeOption = {
          geo: {
            map: provinceInfo.key,
          },
        };
        this.chartInstance.setOption(changeOption);
      });
    },
    // 回到中国地图
    revertMap() {
      const revertOption = {
        geo: {
          map: "china",
        },
      };
      this.chartInstance.setOption(revertOption);
    },
    async getData() {
      const { data: ret } = await this.$http.get("map");
      this.allData = ret;
      this.updateChart();
    },
    // 更新图表
    updateChart() {
      // 图例数据
      const legendArr = this.allData.map((item) => {
        return item.name;
      });
      const seriesArr = this.allData.map((item) => {
        // 如果想在地图中显示散点数据,需要给散点的图表增加 coordinateSystem: "geo"  配置
        return {
          type: "effectScatter",
          rippleEffect: {
            scale: 5,
            brushType: "stroke", //空心涟漪效果
          },
          name: item.name,
          data: item.children,
          coordinateSystem: "geo",
        };
      });
      const dataOption = {
        legend: {
          data: legendArr,
        },
        series: seriesArr,
      };
      this.chartInstance.setOption(dataOption);
    },
    // 当浏览器大小发生变化时,会进行分辨率适配
    screenAdapter() {
      const titleFontSize = (this.$refs.map_ref.offsetWidth / 100) * 3.6;
      const adapterOption = {
        title: {
          textStyle: {
            fontSize: titleFontSize,
          },
        },
        legend: {
          itemWidth: titleFontSize / 2,
          itemHeight: titleFontSize / 2,
          itemGap: titleFontSize / 2, //图例间隔
          textStyle: {
            fontSize: titleFontSize / 2,
          },
        },
      };
      this.chartInstance.setOption(adapterOption);
      this.chartInstance.resize(); //手动调用图表对象的resize()才能生效
    },
  },
};
</script>

7.1、地图上显示散点

在地图上给散点图表增加 coordinateSystem: "geo"  配置

7.2、点击出现单个省份,双击复原

备注:getProvinceMapInfo是将汉字转为省份拼音,以便获取对应的本地省份数据

(1)、监听各个省份的点击事件,获取对应的arg.name(汉字);

(2)、根据getProvinceMapInfo()获取所点击省份的矢量地图数据,用mapData存下以获取数据,减少请求的二次发送;

(3)、根据this.$echarts.registerMap(“省份名”, "省份数据”)显示省份和对应的数据

(4)、双击页面,通过重新注册"china",回到中国地图。

下篇将分享全屏切换、实时监测【WebSocket】等功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/729402.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

dial tcp 10.96.0.1:443: connect: no route to host

1、创建Pod一直不成功&#xff0c;执行kubectl describe pod runtime-java-c8b465b98-47m82 查看报错 Warning FailedCreatePodSandBox 2m17s kubelet Failed to create pod sandbox: rpc error: code Unknown desc failed to setup network for…

java8 将对象list中的某一个属性取出组成一个list

实体类 public class Sp {String spdm;String spmc;public Sp() {}public Sp(String spdm, String spmc) {this.spdm spdm;this.spmc spmc;}public String getSpdm() {return spdm;}public void setSpdm(String spdm) {this.spdm spdm;}public String getSpmc() {return sp…

太爱这种数据可视化效果,零售行业的都看过来

在当今数字化浪潮下&#xff0c;数据可视化已成为零售行业洞察市场趋势、优化运营决策的关键技术。奥威BI零售数据分析方案凭借其卓越的数据可视化效果&#xff0c;成为零售企业的得力助手。接下来就通过BI节假日分析报表来简单地感受一下。 注&#xff1a;该BI节假日分析报表…

反激开关电源输出电解电容选型及计算

电容高频模型&#xff1a;ESRESLC的串联 1、耐压&#xff1a;根据输出的电压来取&#xff0c;需留一定余量&#xff0c;比如5V输出可以选6.3V或者10V的电解电容 2、容量 纹波电压 电容充放电引起的纹波电压&#xff08;与电容容量存在着直接因果关系&#xff09; ESR引起的纹…

校园任务平台系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;论坛管理&#xff0c;任务咨询管理&#xff0c;用户管理&#xff0c;基础数据管理 前台账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;任务资讯公告&#…

Springboot 实体类赋默认值 @Value 失效? 那怎么搞?

这是最近一个小伙找上来问的问题&#xff0c; 我初一看还没看出来啥猫腻&#xff0c;后面认真一想&#xff0c;决定也写下来记录下&#xff0c;给其他初学者也知道下。 原先思路错误代码&#xff1a; 这个小伙想利用 Value 注解&#xff0c; 给这个属性 赋值&#xff0c;defaul…

js 实现将后端请求来的 Blob 数据保存到用户选择的任意目录

js实现将后端请求来的 Blob 数据保存到用户选择的任意目录 实现方式 实现方式 实现方式是使用 window 的 showSaveFilePicker 方法。Window 接口的 showSaveFilePicker() 方法用于显示一个文件选择器&#xff0c;以允许用户保存一个文件。可以选择一个已有文件覆盖保存&#xf…

快手电商:618大促开启以来,短视频挂车GMV同增66%

日前&#xff0c;快手电商发布618大促阶段战报。数据显示&#xff0c;在5月20日-6月18日活动期间&#xff0c;平台动销商家数同比增长26%&#xff0c;动销中小商家数同比增长28%&#xff0c;动销中小商家订单量同比增长25%。 从经营场域来看&#xff0c;泛货架场已成为快手电商…

纯css星空动画

让大家实现一个这样的星空动画效果,大家会怎么做? js,不! 其实使用css就能写 我也不藏着掖着,源码直接放下面了 <script setup></script><template><div class"box"><div v-for"i in 5" :key"i" :class"layer…

PostgreSQL性能优化之分区表 #PG培训

在处理大规模数据时&#xff0c;PostgreSQL的性能优化是一个非常重要的话题&#xff0c;其中分区表&#xff08;Partitioned Tables&#xff09;是提高查询和数据管理效率的重要手段。本文将详细介绍PostgreSQL分区表的概念、优势、创建与管理方法以及一些常见的优化策略。 #P…

《广州化工》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问&#xff1a;《广州化工》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的正规学术期刊 问&#xff1a;《广州化工》级别&#xff1f; 答&#xff1a;省级。主办单位&#xff1a;广州化工集团有限公司 主管单位&#xff1a;广州化工…

【CSS in Depth2精译】1.1.1 样式表来源

您添加到网页的样式表并非浏览器呈现样式的唯一来源。样式表有三种不同的类型或来源。您添加到页面的样式称为 作者样式&#xff08;author styles&#xff09;&#xff1b;此外还有 用户样式&#xff08;user styles&#xff09;&#xff0c;即终端用户设置的自定义样式&#…

python-赏月

[题目描述] 在某个星球上看到的月亮大小有一个规律&#xff0c;月亮为每30天一个周期&#xff0c;在这30天的周期里&#xff0c;月亮的大小分别为 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1。 虽然天气很冷&#xff0c;但这个星球上的某个居民今…

Java中的do-while循环及其示例

Java中的do-while循环及其示例 在上一个教程中&#xff0c;我们讨论了while循环。在本教程中&#xff0c;我们将讨论java中的do-while循环。do-while循环类似于while循环&#xff0c;但它们之间有区别&#xff1a;在while循环中&#xff0c;条件是在执行循环体之前求值的&am…

虚拟3D沉浸式展会编辑平台降低了线上办展的门槛

在数字化浪潮的引领下&#xff0c;VR虚拟网上展会正逐渐成为企业展示品牌实力、吸引潜在客户的首选平台。我们与广交会携手走过三年多的时光&#xff0c;凭借优质的服务和丰富的经验&#xff0c;赢得了客户的广泛赞誉。 面对传统展会活动繁多、企业运营繁忙的挑战&#xff0c;许…

Springboot3.3 整合Cassandra 4.1.5

一、数据库搭建 -- 创建Keyspace CREATE KEYSPACE school WITH replication {class:SimpleStrategy, replication_factor : 1};-- 创建表 CREATE TABLE student(id int PRIMARY KEY, name text, age int, genders int, address text ,interest set<text>,phone lis…

大模型之-Seq2Seq介绍

大模型之-Seq2Seq介绍 1. Seq2Seq 模型概述 Seq2Seq&#xff08;Sequence to Sequence&#xff09;模型是一种用于处理序列数据的深度学习模型&#xff0c;常用于机器翻译、文本摘要和对话系统等任务。它的核心思想是将一个输入序列转换成一个输出序列。 Seq2Seq模型由两个主…

【计算机网络体系结构】计算机网络体系结构实验-DHCP实验

服务器ip地址 2. 服务器地址池 3. 客户端ip 4. ping Ipconfig

「五度易链」企业大数据API接口开放平台上线啦!

“五度易链”企业大数据API接口开放平台现已正式上线&#xff0c;旨在为广大企业、开发者及个人提供标准、安全、高效、便捷的企业数据API接口服务&#xff0c;帮您更轻松地构建应用、扩展功能&#xff0c;并基于用户应用场景提供专属接口定制服务&#xff0c;助力企业提升研发…

模式分解的概念(下)-无损连接分解的与保持函数依赖分解的定义和判断、损失分解

一、无损连接分解 1、定义 2、检验一个分解是否是无损连接分解的算法 输入与输出 输入&#xff1a; 关系模式R&#xff08;U&#xff0c;F&#xff09;&#xff0c;F是最小函数依赖集 R上的一个分解 输出&#xff1a; 判断分解是否为无损连接分解 &#xff08;1&#x…