echarts+vue2实战(一)

news2024/11/25 6:30:10

目录

一、项目准备

二、(横向分页)柱状图

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.coloradmin.cn/o/1846035.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于卷积神经网络的目标检测

卷积神经网络基础知识 1.什么是filter 通常一个6x6的灰度图像&#xff0c;构造一个3*3的矩阵&#xff0c;在卷积神经网络中称之为filter,对&#xff16;x6的图像进行卷积运算。 2.什么是padding 假设输出图像大小为nn与过滤器大小为ff&#xff0c;输出图像大小则为(n−f1)∗(…

qt经典界面框架

目的 其实就是一个简单的界面显示&#xff0c;是很常用的形式。 说起来简单也是简单&#xff0c;但当初&#xff0c;刚开始做时&#xff0c;感觉非常的复杂&#xff0c;不知如何下手。 现在感觉简单多了。 这个框架利用了QT的现成的MainWindow与QDockWidget&#xff0c;这样就…

Android SurfaceFlinger——SF与HWC交互流程(六)

在上一篇 HWC2On1Adapter 初始化完成后&#xff0c;调用 initWithDevice() 实例化 HwcHal 对象&#xff0c;然后创建高级接口&#xff08;IComposer&#xff09;&#xff0c;使得调用者能够通过这个接口与硬件进行交互。这里我们就来看一下 HwcHal 和 IComposer 的初始化流程。…

超级ai 必须有个,超级大的词表,必须是个向量库 faiss is all you need

说明优点图像表示流程代码实现如下全部代码 说明 使用极其庞大的词表在模型压缩和图像token化方面带来了显著优势。由于词表巨大&#xff0c;我们不得不利用向量数据库对词表进行搜索&#xff0c;以找到最匹配的token。预测出的token会再次通过嵌入矩阵&#xff08;em&#xf…

短剧片源授权,类目丰富优惠多,抢先一步更新你的短剧系统片库!

前言 如今的短剧作为一种新兴的视听艺术形式&#xff0c;正以其独特的魅力迅速占领市场高地。为了满足广大短剧爱好者和从业者的需求&#xff0c;我们提供短剧片源授权服务&#xff0c;凭借剧场独家提供的丰富片源&#xff0c;助力您轻松更新短剧系统片库&#xff0c;抢占市场…

不见五陵高管墓,无花无酒锄做田

不见五陵高管墓&#xff0c;无花无酒锄做田 Golang 通用代码生成器仙童 2.4.0 电音仙女尝鲜版七已发布&#xff0c;此版本测试修复了 PostgreSQL 数据库自动反射功能。此版本更新修复了前端代码生成器&#xff0c;并修复了前端多对多界面的缺陷。PostgreSQL 的数据库反射功能刚…

安装TensorFlow报错问题ERROR: Failed building wheel for h5py解决

安装TensorFlow报错问题&#xff1a; 安装命令: pip install tensorflow2.12.0 -i https://pypi.tuna.tsinghua.edu.cn/simple Building wheel for h5py (PEP 517) ... error ERROR: Command errored out with exit status 1: command: /usr/bin/python3 /tmp/tmpz0y9yg…

代码生成器技术乱弹五十三,人工智能和通用代码生成器的共同点:Token

代码生成器技术乱弹五十三&#xff0c;人工智能和通用代码生成器的共同点&#xff1a;Token 现在&#xff0c;随着人工智能的快速发展&#xff0c;特别是生成式人工智能的爆火&#xff0c;大家逐渐熟悉了一个概念&#xff0c;Token。我称之为字牌。在生成式人工智能的语境下&a…

【每日刷题】Day72

【每日刷题】Day72 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 1287. 有序数组中出现次数超过25%的元素 - 力扣&#xff08;LeetCode&#xff09; 2. 993. 二叉树的…

视创云展为企业虚拟展厅搭建,提供哪些功能?

在当下数字化浪潮中&#xff0c;如何为用户创造更富生动性和真实感的展示体验&#xff0c;已成为企业营销策略的核心。借助视创云展的线上虚拟3D企业展厅搭建服务&#xff0c;利用3D空间漫游和VR技术的融合&#xff0c;可以为用户呈现出一个既真实又充满想象力的全景图或三维模…

中央空调水系统安装

冷热水管&#xff1a; 空调冷热水管道的材质应由业主或使用方明确&#xff1a; 1、普通焊接钢管&#xff1b; 2、无缝钢管&#xff1b; 3、镀锌钢管&#xff1b; 4、PP-R管&#xff1b; 5、紫铜管&#xff1b; 6、水管内外表面应光洁、无疵孔、裂缝、结疤、层裂或气泡。…

Python12 列表推导式

1.什么是列表推导式 Python的列表推导式&#xff08;list comprehension&#xff09;是一种简洁的构建列表&#xff08;list&#xff09;的方法&#xff0c;它可以从一个现有的列表中根据某种指定的规则快速创建一个新列表。这种方法不仅代码更加简洁&#xff0c;执行效率也很…

【总线】AXI4第四课时:信号描述

大家好,欢迎来到今天的总线学习时间!如果你对电子设计、特别是FPGA和SoC设计感兴趣&#xff0c;那你绝对不能错过我们今天的主角——AXI4总线。作为ARM公司AMBA总线家族中的佼佼者&#xff0c;AXI4以其高性能和高度可扩展性&#xff0c;成为了现代电子系统中不可或缺的通信桥梁…

05 Pytorch 数据读取 + 二分类模型

05 Pytorch 数据读取 二分类模型05 Pytorch 数据读取 二分类模型05 Pytorch 数据读取 二分类模型 01 数据读取 DataLoader&#xff08;set作为参数&#xff09; 02 Dataset 从哪读&#xff0c;怎么读&#xff1f; 功能&#xff1a;数据从哪里读取&#xff1f; 如何读取…

BEV端到端视觉论文合集|从不同的视角解析BEV感知技术

随着自动驾驶技术的不断发展&#xff0c;基于摄像头的感知系统已成为关键&#xff0c;而Bird’s Eye View (BEV)大模型在其中发挥着重要作用。BEV大模型是一种将摄像头捕捉到的2D图像转换为自上而下视角的3D感知的技术&#xff0c;使得车辆能够更好地理解周围环境。 BEV大模型…

吴恩达机器学习 第三课 week1 无监督机器学习(下)

目录 01 学习目标 02 异常检测算法 2.1 异常检测算法的概念 2.2 基于高斯模型的异常检测 03 利用异常检测算法检测网络服务器的故障 3.1 问题描述 3.2 算法实现 3.3 问题升级 04 总结 01 学习目标 &#xff08;1&#xff09;理解异常检测算法&#xff08;Anomaly Det…

编程精粹—— Microsoft 编写优质无错 C 程序秘诀 06:危险的行业

这是一本老书&#xff0c;作者 Steve Maguire 在微软工作期间写了这本书&#xff0c;英文版于 1993 年发布。2013 年推出了 20 周年纪念第二版。我们看到的标题是中译版名字&#xff0c;英文版的名字是《Writing Clean Code ─── Microsoft’s Techniques for Developing》&a…

Mac安装多个jdk环境(jdk8+jdk17)保姆级

Mac安装多个jdk环境&#xff08;jdk8jdk17&#xff09;保姆级 背景&#xff1a;新机安装开发环境发现需要找很多文章&#xff0c;&#xff0c;&#xff0c;&#xff0c;这里一篇文章安装所有环境 文章目录 Mac安装多个jdk环境&#xff08;jdk8jdk17&#xff09;保姆级&#x1f…

基于springboot实现火车票订票系统项目【项目源码+论文说明】

基于springboot实现火车票订票系统演示 摘要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装火车票订票系统软件来…

【SpringCloud】Eureka的简单使用

本文使用的是jdk17&#xff0c;mysql8。 以下用两个服务做演示&#xff1a; 订单服务&#xff1a;提供订单ID&#xff0c;获取订单详细信息。 商品服务&#xff1a;提供商品ID&#xff0c;获取商品详细信息。 对于上篇http://t.csdnimg.cn/vcWpo 订单服务调用商品服务的时候&a…