首页 前端知识 echarts点击子组件放大的三种实现方式

echarts点击子组件放大的三种实现方式

2024-02-21 10:02:08 前端知识 前端哥 251 450 我要收藏

目录

1、图表全屏放大

2、dialog弹窗,传值放大

3、dialog弹窗,引入echarts组件放大


前置条件:基于v-scale-screen大屏适配插件,全局使用的单位为px,echarts属性对应的值为Number时,默认为px。

需求:因页面会拆分成n个子组件,每个子组件里内容的组合都不相同,我需要点击子组件时,对整个圈红的子组件放大显示。(类似下图,参考图为网图)

1、图表全屏放大

操作原理:利用echarts的.resize(),改变容器大小实现全屏变大。

优势:如果仅放大echarts,通用性蛮强的,因为api只是做的放大效果,所以当前页配置的属性全都生效。而且因为【点击放大】按钮是写在插件外的部分,不是用toolbox工具栏自定义事件,都不需要额外考虑“在全屏后如何隐藏掉放大按钮”。(不过就算考虑也没关系,操作方式可以参考【2dialog弹窗传值放大】)

具体实现参考这位大神的代码:

封装了一个echarts图全屏放大的功能_echarts怎么做到把图放大_外围前端吴彦祖的博客-CSDN博客

 说几个局限性。

1)因为我是用v-scale-screen第三方插件做的适配,所以需要将插件内的tootip、legend属性中涉及到的size做处理,要做的改动有点多。(下图,图很大,字没变)

不过要是有大神已经做了css和js的全局适配,并且放大的要求的【全屏显示】,那很推荐,因为真的很省事。

2)如果是在同一个子组件有n个不同的图表、n个遍历显示的echarts、或者还带有其他一些自定义的信息,是不适合使用的。(比如下图,图片来自网络。内容太多,封装的全屏无法使整个子组件全屏)

3)当使用echarts自定义的鼠标事件,比如绘制地图,点击【下图1】的区域【放大】,显示区域内详细内容(下图2)时,大屏后不支持切换整体地图和区域地图互相切换,只能整体地图放大(下图1)or区域地图放大(下图2)。

不过其实大神的标题已经写得很明确了,是为echarts图做的放大效果,只不过不符合我们的需求而已。 

2、dialog弹窗,传值放大

 和【1全屏放大】相似,封装的弹窗组件。

优势:自定义的放大事件是写在toolbox工具栏中的,如果是单一的echarts,统一在封装弹窗内将事件赋值为false,很方便。

 具体实现参考这位大神的代码:

echarts自定义全屏弹窗_echarts点击弹出窗口_禾子逸的博客-CSDN博客

但也存在局限性。

比如【1全屏放大__3)绘制地图】时,自定义的toolbox放大/返回事件在切换整体地图和局部地图不同图标的显示时,就不是那么友好了。

其余局限性和【1全屏放大】也是差不多的。

3、dialog弹窗,引入echarts组件放大

以上两种方式都不太符合前置需求,但是通过前两个链接,可以总结出一些使用经验:

1)封装共通组件;

2)需要支持子组件内所有内容一同显示在共通组件内,且样式正常;

3)需要支持共通组件内所有放大后的size自适应大小;

4)需要支持所有已定义的鼠标事件,例如 mapCharts.on('click',()={});

5)需要支持自定义【放大】、【返回】按钮在页面变化时的动态显示。

以上需求对应的实现思路:

1)封装仅做css处理的共通弹窗组件,背景色、图案等都处理好,引入圈红子组件。


2)圈红子组件被引入时,所有内容都会被显示出来,此时大概率在弹窗内左上的位置。(大概是下图这样)

3)不做任何处理时,因v-scale-screen的作用,在屏幕没有变化时,共通组件内所有的size都不会变化,和圈红子组件一致。不过可以给引入的子组件绑定ref,通过ref找到dom元素,做ref.style.transform = 'scale(2)'的倍数显示,就会所有内容都被放大且符合放大前的比例。

但也有些许缺陷,清晰度会有所降低……

4)因为是引入的子组件,鼠标事件都是生效的。

5)因为是引入的子组件,唯一需要注意的是,不要在toolbox工具栏中写自定义事件了,把它拿出来单独放子组件的页面里吧。方便在弹窗中做隐藏。(下图是写在toolbox中,【放大】子组件的显示,反向举例。)

弹窗参考代码:

<template>
  <!-- 区域整体+弹窗 -->
  <div class="all">
    <div class="center">
      <div class="title">
        <span class="text">{{ titleOne }}</span>
        <span class="close" @click="close">×</span>
      </div>
      <div class="log" ref="log">
       // :num=0  传值给echarts,因echarts注册时只允许存在1个id,可以做区分
        <Contrast :num="'0'" v-if="title === '第一工場'"></Contrast>
        <FactoryListTwo :num="'0'" v-if="title === '第二工場'"></FactoryListTwo>
        <StoreCharts :num="'0'" v-show="title === 'japan'"></StoreCharts>
      </div>
    </div>
  </div>
</template>
<script>
 // 引入echasrts组件
import Contrast from '@/views/components/Contrast'
import FactoryListTwo from '@/views/components/FactoryListTwo'
import StoreCharts from '@/views/components/storeCharts.vue'
export default {
  props: {
    show: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: 'dialog测试'
    },
    id: {
      type: String,
      default: ''
    },
    val: {
      type: Object,
      default: null
    }
  },
  components: {
    Contrast,
    FactoryListTwo,
    StoreCharts
  },
  data() {
    return {
      // 标题
      titleOne: this.title
    }
  },
  mounted() {
// 前期规划的不太好,所以不同的echarts子组件做放大效果时分开处理了。
    switch (this.title) {
      case '第一工場':
        this.contrastFun()
      case '第二工場':
        this.factoryListFun()
    }
  },
  methods: {
    // 第一工場时的css处理--多个echarts和其他标签组成的子组件
    contrastFun() {
      let divList = this.$refs.log.children[0].children
      // 图标+横向柱状图
      let div0 = divList[0]
      div0.style.transform = 'scale(2)'
      // 环形图
      let div1 = divList[1]
      div1.style.transform = 'scale(2)'
      div1.style.width = div0.offsetWidth + 'px'
      // 环形图循环 span
      div1.children[0].style.display = 'none'
    },
    // 调用第二工場的css处理--多个环状图组成的echarts子组件
    factoryListFun() {
      let factoryList = this.$refs.log.children[0]
      // 标题放大
      factoryList.children[0].style.transform = 'scale(2)'
      // 表格放大
      // 因echarts使用series创建多环形,绝对定位需要加一个top: 80px;
      factoryList.children[1].children[0].style.top = '80px'
      factoryList.children[1].style.transform = 'scale(2)'
    },
    // 关闭
    close() {
      this.$emit('close')
    }
  }
}
</script>
<style lang="scss" scoped>
.all {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  // display: none;
  background-color: rgba(0, 0, 0, 0.5);
  .center {
    width: 1500px;
    height: 900px;
    margin: 100px auto;
    .title {
      height: 50px;
      display: flex;
      justify-content: space-between;
      flex-direction: row;
      align-items: center;
      background: #ffffff;
      font-size: 25px;
      .text {
        margin-left: 20px;
      }
      .close {
        width: 40px;
        height: 40px;
        margin-right: 20px;
      }
    }
    .log {
      width: 100%;
      padding: 2% 15%;
      height: 750px;
      background-image: radial-gradient(
        circle at 50% 100%,
        $color134186,
        $color0850
      );
      background: -webkit-radial-gradient(bottom, $color134186, $color0850);
    }
  }
}
</style>

转载请注明出处或者链接地址:https://www.qianduange.cn//article/2428.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!