大屏自适应/适配方案

1,013 阅读2分钟

大屏自适应的核心目标有:

  1. 字体大小随屏幕尺寸自适应变化
  2. 自动撑满全屏
  3. 弹性布局(使用 css 的布局)

不会留白,但是部分分辨率下部分屏幕会有拉伸的情况

var _el = this.$refs.appContain
var hScale = window.innerHeight / 1080
var wScale = window.innerWidth / 1920
_el.style.transform = 'scale(' + wScale + ',' + hScale + ') translateX(-50%)'

设置系统缩放比,适配各分辨率,这种方式会导致在不同分辨率下会有留白的情况

export function refreshScale(){
  let baseWidth = document.documentElement.clientWidth;
  let baseHeight = document.documentElement.clientHeight;
  let appStyle = document.getElementById('app').style;
  let realRatio = baseWidth/baseHeight
  let designRatio = 16/9
  let scaleRate =  baseWidth/1920
  if(realRatio>designRatio){
    scaleRate = baseHeight/1080
  }
  appStyle.transformOrigin = 'left top';
  appStyle.transform=`scale(${scaleRate}) translateX(-50%)`;
  appStyle.width = `${baseWidth/scaleRate}px`
}
  • 可不使用

export const echartsSize = function (size,defalteWidth = 1920) {
  let docEl = document.documentElement,
    clientWidth = window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;
  if (!clientWidth) return;
  let fontSize = (clientWidth / defalteWidth);
  return Number((size*fontSize).toFixed(3));
}

完整代码

  • 新建mix.js文件,复制进去后,直接包裹外层容器,需注意:app样式直接设置成100vw,100vh
  • 包裹所有内容的容器需要设置为以下样式
.scale-container {
 /*父级宽100vw,高100vh。子盒子宽高1920*1080可以做大屏显示居中缩放 */
 width: 1920px;
 height: 1080px;
 /* 根据父级定位,配合transform用来居中 */
 position: absolute;
 left: 50%;
 /* 更改转换元素的位置 */
 transform-origin: left top;
 /* 超出隐藏 */
 overflow: hidden;
}

完整代码

// 屏幕适配 mixin 函数

// * 默认缩放值
const scale = {
  width: '1',
  height: '1',
}

// * 设计稿尺寸(px)
var baseWidth = 1920
var baseHeight = 1080
// * 需保持的比例(默认1.77778)
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))

export default {
  data() {
    return {
      // * 定时函数
      drawTiming: null,
    }
  },
  mounted() {
    //加载后先计算一遍缩放比例
    this.calcRate()
    //生成一个监听器:窗口发生变化从新计算计算一遍缩放比例
    window.addEventListener('resize', this.resize)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.resize)
  },
  methods: {
    calcRate() {
    // 直接暴力铺满,一劳永逸
      var _el = this.$refs.appContain
      var hScale = window.innerHeight / 1080
      var wScale = window.innerWidth / 1920
      _el.style.transform = 'scale(' + wScale + ',' + hScale + ') translateX(-50%)'

      return
      // 设置系统缩放比,适配各分辨率,但是会留白
      const baseWidth = document.documentElement.clientWidth
      const baseHeight = document.documentElement.clientHeight
      const appStyle = this.$refs.appContain.style
      const realRatio = baseWidth / baseHeight
      const designRatio = 16 / 9
      let scaleRate = baseWidth / 1920
      if (realRatio > designRatio) {
        scaleRate = baseHeight / 1080
      }
      appStyle.transformOrigin = 'left top'
      appStyle.transform = `scale(${scaleRate}) translateX(-50%)`
      appStyle.width = `${baseWidth / scaleRate}px`
    },
    resize() {
      //先清除计时器
      clearTimeout(this.drawTiming)
      //开启计时器
      this.drawTiming = setTimeout(() => {
        this.calcRate()
      }, 200)
    },
  },
}

使用rem进行自适应,自动铺满全屏,部分分辨率会出现布局混乱

  • 在入口如添加修改字体大小的代码
cnpm i postcss-plugin-px2rem
;(function (designWidth, minWidth) {
  const docEle = document.documentElement
  const screenRatioByDesign = 16 / 9
  function setHtmlFontSize() {
    var screenRatio = docEle.clientWidth / docEle.clientHeight
    var fontSize =
      ((screenRatio > screenRatioByDesign ? screenRatioByDesign / screenRatio : 1) * docEle.clientWidth) / 10

    docEle.style.fontSize = fontSize.toFixed(3) + 'px'
  }

  setHtmlFontSize()

  window.addEventListener('resize', setHtmlFontSize)
})(1920, 1024)

接着在vue.config.js中配置

css: {
  extract: false,
  sourceMap: false,
  // css预设器配置项
  loaderOptions: {
    postcss: {
      plugins: [
        require('postcss-plugin-px2rem')({
// 换算基数, 默认100  ,这样的话把根标签的字体规定为1rem为50px,这样就从设计稿上量出多少个px直接在代码中写多上px了。
          rootValue: 192, 
//允许REM单位增长到的十进制数字。
          unitPrecision: 5,
//默认值是一个空数组,这意味着禁用白名单并启用所有属性。
          //propWhiteList: [],
          // propBlackList: [], //黑名单
//默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)/ 。如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值
          exclude: /(node_module)/,
          // selectorBlackList: [], //要忽略并保留为px的选择器
//(boolean/string)忽略单个属性的方法,启用ignoreidentifier后,replace将自动设置为true。
          // ignoreIdentifier: false,
          replace: false, // (布尔值)替换包含REM的规则,而不是添加回退。
          mediaQuery: false, //(布尔值)允许在媒体查询中转换px。
          minPixelValue: 3, //设置要替换的最小像素值(3px会被转rem)。 默认 0
        }),
      ],
    },
    less: {
      lessOptions: {
        javascriptEnabled: true,
      },
    },
  },
},