大屏适配方案(vw、vh)

开发大屏主要是两方面的工作:

  • 大屏之关键-前期的自适应适配
  • 根据 ui 稿绘制图表,调细节
方案 实现方式 优点 缺点
vw vh 1.按照设计稿的尺寸,将px按比例计算转为vwvh 1.可以动态计算图表的宽高,字体等,灵活性较高
2.当屏幕比例跟 ui 稿不一致时,不会出现两边留白情况
1.每个图表都需要单独做字体、间距、位移的适配,比较麻烦

 

 

 

实现思路

按照设计稿的尺寸,将px按比例计算转为vwvh,转换公式如下

假设设计稿尺寸为 1920*1080(做之前一定问清楚 ui 设计稿的尺寸)

即:
网页宽度=1920px
网页高度=1080px

我们都知道
网页宽度=100vw
网页宽度=100vh

所以,在 1920px*1080px 的屏幕分辨率下

1920px = 100vw

1080px = 100vh

这样一来,以一个宽 300px 和 200px 的 div 来说,其所占的宽高,以 vw 和 vh 为单位,计算方式如下:

vwDiv = (300px / 1920px ) * 100vw
vhDiv = (200px / 1080px ) * 100vh

所以,就在 1920*1080 的屏幕分辨率下,计算出了单个 div 的宽高

当屏幕放大或者缩小时,div 还是以 vw 和 vh 作为宽高的,就会自动适应不同分辨率的屏幕


css 方案 - sass

util.scss

// 使用 scss 的 math 函数,https://sass-lang.com/documentation/breaking-changes/slash-div
@use "sass:math";

// 默认设计稿的宽度
$designWidth: 1920;
// 默认设计稿的高度
$designHeight: 1080;

// px 转为 vw 的函数
@function vw($px) {
  @return math.div($px, $designWidth) * 100vw;
}

// px 转为 vh 的函数
@function vh($px) {
  @return math.div($px, $designHeight) * 100vh;
}


在 .vue 中使用

<template>
    <div class="box">			
    </div>
</template>

<script>
export default{
    name: "Box",
}
</script>

<style lang="scss" scoped="scoped">
@import '@/assets/scss/util.scss';
/* 
 直接使用 vw 和 vh 函数,将像素值传进去,得到的就是具体的 vw vh 单位		 
 */
.box{
    width: vw(300);
    height: vh(100);
    font-size: vh(16);
    background-color: black;
    margin-left: vw(10);
    margin-top: vh(10);
    border: vh(2) solid red;
}
</style>


屏幕变化后,图表自动调整

这种使用方式有个弊端,就是屏幕尺寸发生变化后,需要手动刷新一下才能完成自适应调整

为了解决这个问题,你需要在各个图表中监听页面尺寸变化,重新调整图表,在 vue 项目中,最好封装个 resize 的指令,在各图表中就只要使用该指令就可以了。

  1. 封装 directive
    // 在directives目录下创建resizeObserver.js文件
    // 监听元素大小变化的指令
    const map = new WeakMap()
    const ob = new ResizeObserver((entries) => {
        for (const entry of entries) {
            // 获取dom元素的回调
            const handler = map.get(entry.target)
            //存在回调函数
            if (handler) {
                // 将监听的值给回调函数
                handler({
                    width: entry.borderBoxSize[0].inlineSize,
                    height: entry.borderBoxSize[0].blockSize
                })
            }
        }
    })
    
    
    export const Resize = {
    
        mounted(el, binding) {
            //将dom与回调的关系塞入map
            map.set(el, binding.value)
            //监听el元素的变化
            ob.observe(el)
        },
        unmounted(el) {
            //取消监听
            ob.unobserve(el)
        }
    }
    
    export default Resize
  2. 在directives目录下创建index.js文件
    
    import Resize from "./resizeObserver"; // 监听dom宽高变化
    
    const directivesList = {
        Resize
    };
    
    const directives = {
      install: function (app) {
        Object.keys(directivesList).forEach((key) => {
          app.directive(key, directivesList[key]); // 注册
        });
      }
    };
    
    export default directives;// 抛出
  3. 在vue中使用

    <!-- vue3 -->
    <template>
      <div class="content">
        <div class="bar-content" id="bar-content" v-resize="onResize">
    
        </div>
        <div class="bar-content" id="pie-content" v-resize="onResize">
    
        </div>
      </div>
      
      
    </template>
    <script>
    const onResize = (width,height)=>{
      nextTick(()=>{
        myChart.resize()
        myPieChart.resize()
        
        myPieChart.clear();//消除当前实例
        pieInit()//重新渲染echart
        // myPieChart.setOption(options,true);//重新渲染echart
      })
      
    }
    onMounted(()=>{
      barInit()
      pieInit()
    })
    
    </script>
    图表字体、间距、位移等尺寸自适应

    echarts 的字体大小只支持具体数值(像素),不能用百分比或者 vw 等尺寸,一般字体不会去做自适应,当宽高比跟 ui 稿比例出入太大时,会出现文字跟图表重叠的情况

 

这里我们就需要封装一个工具函数,来处理图表中文字自适应了👇

  • 默认情况下,这里以你的设计稿是 1920*1080 为例,即网页宽度是 1920px (做之前一定问清楚 ui 设计稿的尺寸)

  • 把这个函数写在一个单独的工具文件dataUtil.js里面,在需要的时候调用

  • 其原理是计算出当前屏幕宽度和默认设计宽度的比值,将原始的尺寸乘以该值

  • 另外,其它 echarts 的配置项,比如间距、定位、边距也可以用该函数

  1. 编写 dataUtil.js 工具函数
    // Echarts图表字体、间距自适应
    export const fitChartSize = (size,defalteWidth = 1920) => {
      let clientWidth = window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;
      if (!clientWidth) return size;
      let scale = (clientWidth / defalteWidth);
      return Number((size*scale).toFixed(3));
    }
    
    
    
  2. 在vue文件中import
    import { fitChartSize } from '@/assets/js/utils.js'
  3. 调用fitChartSize
    <template>
      <div class="chartsdom" ref="chart" v-chart-resize></div>
    </template>
    
    // 饼状图
    let myPieChart = {}
    let options = {}
    const pieInit = ()=>{
      // 基于准备好的dom,初始化echarts实例
      myPieChart = echarts.init(document.getElementById('pie-content'));
      options = {
          // backgroundColor: 'rgb(43, 51, 59)',
          toolbox: {
              show: true,
              feature: {
                  mark: {
                      show: true
                  },
                  dataView: {
                      show: true,
                      readOnly: false
                  },
                  magicType: {
                      show: true,
                      type: ['pie', 'funnel']
                  },
                  restore: {
                      show: true
                  },
                  saveAsImage: {
                      show: true
                  }
              }
          },
          calculable: true,
          "tooltip": {
              "trigger": "item",
              "formatter": "{a}<br/>{b}:{c}千万元"
          },
          "title": {
              "text": "南丁格尔玫瑰图--PieHalfRose",
              "left": "center",
              "top": fitChartSize(20),
              "textStyle": {
                  "color": "#ccc",
                  "fontSize": fitChartSize(18)
              }
          },
          "calculable": true,
          "legend": {
              "icon": "circle",
              "x": "center",
              "y": "15%",
              "data": [
                  "义乌市1",
                  "义乌市2",
                  "义乌市3",
                  "义乌市4",
                  "义乌市5",
                  "义乌市6",
                  "义乌市7",
                  "义乌市8",
                  "义乌市9"
              ],
              "textStyle": {
                  "color": "#fff",
                  "fontSize": fitChartSize(12)
              }
          },
          "series": [{
              "name": "XX线索",
              "type": "pie",
              "radius": [
                fitChartSize(30),
                fitChartSize(70) 
              ],
              "avoidLabelOverlap": false,
              "startAngle": 0,
              "center": [
                  "50%",
                  "60%"
              ],
              "roseType": "area",
              "selectedMode": "single",
              "label": {
                  
                  "normal": {
                      "show": true,
                      "formatter": "{c}千万元",
                      "color": '#fff',
                      fontSize: fitChartSize(12)
                  },
                  "emphasis": {
                      "show": true
                  }
              },
              "labelLine": {
                  "normal": {
                      "show": true,
                      "smooth": false,
                      "length": fitChartSize(20),
                      "length2": fitChartSize(10)
                  },
                  "emphasis": {
                      "show": true
                  }
              },
              "data": [{
                      "value": 600.58,
                      "name": "义乌市1",
                      "itemStyle": {
                          "normal": {
                              "color": "#f845f1"
                          }
                      }
                  },
                  {
                      "value": 1100.58,
                      "name": "义乌市2",
                      "itemStyle": {
                          "normal": {
                              "color": "#ad46f3"
                          }
                      }
                  },
                  {
                      "value": 1200.58,
                      "name": "义乌市3",
                      "itemStyle": {
                          "normal": {
                              "color": "#5045f6"
                          }
                      }
                  },
                  {
                      "value": 1300.58,
                      "name": "义乌市4",
                      "itemStyle": {
                          "normal": {
                              "color": "#4777f5"
                          }
                      }
                  },
                  {
                      "value": 1400.58,
                      "name": "义乌市5",
                      "itemStyle": {
                          "normal": {
                              "color": "#44aff0"
                          }
                      }
                  },
                  {
                      "value": 1500.58,
                      "name": "义乌市6",
                      "itemStyle": {
                          "normal": {
                              "color": "#45dbf7"
                          }
                      }
                  },
                  {
                      "value": 1500.58,
                      "name": "义乌市7",
                      "itemStyle": {
                          "normal": {
                              "color": "#f6d54a"
                          }
                      }
                  },
                  {
                      "value": 1600.58,
                      "name": "义乌市8",
                      "itemStyle": {
                          "normal": {
                              "color": "#f69846"
                          }
                      }
                  },
                  {
                      "value": 1800,
                      "name": "义乌市9",
                      "itemStyle": {
                          "normal": {
                              "color": "#ff4343"
                          }
                      }
                  },
                  {
                      "value": 0,
                      "name": "",
                      "itemStyle": {
                          "normal": {
                              "label": {
                                  "show": false
                              },
                              "labelLine": {
                                  "show": false
                              }
                          }
                      }
                  },
                  {
                      "value": 0,
                      "name": "",
                      "itemStyle": {
                          "normal": {
                              "label": {
                                  "show": false
                              },
                              "labelLine": {
                                  "show": false
                              }
                          }
                      }
                  },
                  {
                      "value": 0,
                      "name": "",
                      "itemStyle": {
                          "normal": {
                              "label": {
                                  "show": false
                              },
                              "labelLine": {
                                  "show": false
                              }
                          }
                      }
                  },
                  {
                      "value": 0,
                      "name": "",
                      "itemStyle": {
                          "normal": {
                              "label": {
                                  "show": false
                              },
                              "labelLine": {
                                  "show": false
                              }
                          }
                      }
                  },
                  {
                      "value": 0,
                      "name": "",
                      "itemStyle": {
                          "normal": {
                              "label": {
                                  "show": false
                              },
                              "labelLine": {
                                  "show": false
                              }
                          }
                      }
                  },
                  {
                      "value": 0,
                      "name": "",
                      "itemStyle": {
                          "normal": {
                              "label": {
                                  "show": false
                              },
                              "labelLine": {
                                  "show": false
                              }
                          }
                      }
                  },
                  {
                      "value": 0,
                      "name": "",
                      "itemStyle": {
                          "normal": {
                              "label": {
                                  "show": false
                              },
                              "labelLine": {
                                  "show": false
                              }
                          }
                      }
                  },
                  {
                      "value": 0,
                      "name": "",
                      "itemStyle": {
                          "normal": {
                              "label": {
                                  "show": false
                              },
                              "labelLine": {
                                  "show": false
                              }
                          }
                      }
                  },
                  {
                      "value": 0,
                      "name": "",
                      "itemStyle": {
                          "normal": {
                              "label": {
                                  "show": false
                              },
                              "labelLine": {
                                  "show": false
                              }
                          }
                      }
                  }
              ]
          }]
      }
      // 绘制图表
      myPieChart.setOption(options);
    }

相关推荐

  1. 方案(vw、vh)

    2023-12-07 10:50:02       54 阅读
  2. 关于可视化

    2023-12-07 10:50:02       37 阅读
  3. 移动端方案

    2023-12-07 10:50:02       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-07 10:50:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-07 10:50:02       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-07 10:50:02       82 阅读
  4. Python语言-面向对象

    2023-12-07 10:50:02       91 阅读

热门阅读

  1. 字符个数统计

    2023-12-07 10:50:02       55 阅读
  2. stm32 RTC时钟设置能不能用毫秒

    2023-12-07 10:50:02       53 阅读
  3. uniapp长按图片识别二维码

    2023-12-07 10:50:02       63 阅读
  4. uni-app实现返回刷新上一页

    2023-12-07 10:50:02       61 阅读
  5. Android 新增系统Apk/Service总结

    2023-12-07 10:50:02       57 阅读
  6. go-zero 开发之安装 goctl 及 go-zero 开发依赖

    2023-12-07 10:50:02       40 阅读
  7. [linux] 输出文本文件的最后一列并去重

    2023-12-07 10:50:02       60 阅读
  8. dockerdesktop 导出镜像,导入镜像

    2023-12-07 10:50:02       54 阅读