大屏自适应之前有用过postcss-pxtorem之类的插件,但是插件只针对css样式,在js和vue模板中的样式,还有echarts的属性值都不能经过插件直接转换。要手动分装方法再次调用,就会比较麻烦,而且有时候写着写着就忘加了,开发就一个分辨率的显示器,最多就是f12打开挤兑挤兑测测。

解决方案 ------- 缩放 + scrollbar(非全屏)

可以使用transform: scale(${this.scale})来设置当前屏幕的缩放比例,以视觉稿为基数1,等比例缩放页面。一般来说大屏设计都是1920*1080的大小,但是浏览器的地址栏标签栏等会占掉一定的高度,所以不是全屏的时候,是显示不全的。所以当比这个比例小的时候,增加竖向滚动条,当全屏的时候,就是正常显示。有些大屏可能还会内嵌到其他框架里边,也可以给大屏增加全屏按钮。

非全屏:出滚动条,全屏: 正常显示
内嵌进其他框架,比如qiankun框架,可以给大屏自己增加全屏和取消全屏按钮,而不是使用键盘的f11

目前的问题:
1. 缩放css属性没有设置在body上,而是在body的子标签上,所以对于一些自动插入到body的元素,缩放不生效(可以试试直接将缩放属性设置在body上,因为这个问题是我用的时候才遇到的,还莫得时间去改)
2. 放大2倍之后,echarts可能看着有点糊。。。。。。。。。没有在特别大的屏上试过,只是有个功能正好做了点击再放大2倍图表,看着是有点糊。。。。。

vue2

这里我使用了ResizeObserverIns来监听dom的变化,也可以使用window的resize方法

<template>
  <div class="page-screen" ref="fullScreen">
    <el-scrollbar>
      <div class="bg" :style="computedStyle">
		...
	  </div>
    </el-scrollbar>
  </div>
</template>
<script>
let ResizeObserverIns = null
export default {
data() {
    return {
      scale: 1
    }
  },
  computed: {
    computedStyle() {
      return {
        transform: `scale(${this.scale})`,
        'transform-origin': '0 0',
      }
    },
  },
  mounted() {
    this.screenResize()
    ResizeObserverIns = new ResizeObserver(() => {
      this.screenResize()
    })
    ResizeObserverIns.observe(this.$refs.fullScreen)
  },
  beforeDestroy() {
    ResizeObserverIns && ResizeObserverIns.disconnect()
  },
   methods: {
    screenResize() {
      this.scale = this.$refs.fullScreen.offsetWidth / 1920
    },
  }
}
</script>
<style lang="scss" scoped>
.page-screen {
  width: 100%;
  height: 100%;
  background: rgb(4, 16, 44);
  overflow: hidden;
  ::v-deep .el-scrollbar__wrap{
    height: calc(100% + 10px);
  }
  ::v-deep .el-scrollbar__view {
    height: 100%;
  }
}
.bg {
  width: 1920px;
  height: 1080px;
  // background-image: url('@/assets/bg.png'); // 一般大屏会有背景
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  overflow: hidden;
  position: relative;
}

vue3

vue3只是在script写法上与vue2不一样

import { computed, ref, onMounted } from 'vue'
import { throttle } from '@/utils'
import { useScaleStore } from '@/store/scale'  // 这个是pinia全局存值,类似vuex,没有用到可以忽略
const store = useScaleStore()
let ResizeObserverIns = null
let scale = ref(1)
let fullScreen = ref()
const computedStyle = computed(() => {
  return {
    transform: `scale(${scale.value})`,
    'transform-origin': '0 0'
  }
})
onMounted(() => {
  screenResize()
  ResizeObserverIns = new ResizeObserver(() => {
    screenResize()
  })
  ResizeObserverIns.observe(fullScreen.value)
})
const screenResize = throttle(function () {  // 增加节流,之前vue2上项目比较赶,后来也懒得加
  scale.value = fullScreen.value.offsetWidth / 1920
  store.changeScale(scale.value)
}, 60)

全屏 / 取消全屏

screenClick() {
  const fullarea = this.$refs.fullScreen
   if (this.fullScreen) {
     cancelScreen()
   } else {
     fullScreen(fullarea)
   }
   this.fullScreen = !this.fullScreen
 }
// 工具方法
// 全屏
export const fullScreen = (fullarea) => {
  if (fullarea.requestFullscreen) {
    fullarea.requestFullscreen();
  } else if (fullarea.webkitRequestFullScreen) {
    fullarea.webkitRequestFullScreen();
  } else if (fullarea.mozRequestFullScreen) {
    fullarea.mozRequestFullScreen();
  } else if (fullarea.msRequestFullscreen) {
    // IE11
    fullarea.msRequestFullscreen();
  }
}
// 取消全屏
export const cancelScreen = () => {
  if (document.exitFullscreen) {
    document.exitFullscreen();
  } else if (document.webkitCancelFullScreen) {
    document.webkitCancelFullScreen();
  } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen();
  } else if (document.msExitFullscreen) {
    document.msExitFullscreen();
  }
}

总结

大屏方案现在使用下来还是scale好用,写代码的时候完全不用操心,而且其他人写的时候也不会出问题