Rem适配大屏

221 阅读4分钟

大屏适配

大屏适配有多个解决方案,vw,rem,scale等等。

物理像素

我们可以这么理解,屏幕是由N多个小方块构成的,每个小方块都只能显示一个颜色,而一个小方块,就是一个物理像素。而在不同设备上,这个小格子的大小是不同的,所以**物理像素并不是一个固定大小的单位,他只代表一个显示器上的小格子**,格子到底多大,在显示器出厂前已经确定好了。

逻辑像素(px)

开发所用的像素

我们可以这么理解,物理像素是硬件开发相关的单位,是基于一个一个的硬件小方块,其大小由硬件厂家设定。而逻辑像素,则更像是软件开发相关的单位,软件相关的工作人员通过逻辑像素来表达软件相关的尺寸。前端css代码、浏览器显示给开发者的尺寸、UI设计师给出的UI稿,其尺寸单位都是逻辑像素。

比如前端工程师的代码如下,其中标注的14px、26px等值,px就是我们所说的逻辑像素。

像素比(DPR)

像素比 = 物理像素/逻辑像素

注意:这里的物理像素和逻辑像素,指的是像素的个数,即绘制相同区域所需的物理像素个数/绘制相同区域所需的逻辑像素个数

由公式可知,像素比就是物理像素与逻辑像素的比值,即当前设备将通过几个物理像素点来绘制一个逻辑像素点

举个例子:

前端工程师现在要画一个2px * 2px的正方形

设备1: 像素比为1,通过2*2个物理像素点来画的这个正方形

设备2: 像素比为2,通过2 * (2 * 2),一共8个物理像素点来画的这个正方形。

注意,设备2所绘制出的正方形其物理尺寸并不一定比设备1的大,因为我们前面提到过,物理像素并不是一个固定大小的单位,其大小由厂家指定。那么如果设备2和设备1所绘制出来的正方形物理面积相同,且设备2用了更多的物理像素点来绘制,很显然,设备2的显示将更为细腻。

通过js如何获取当前的像素比

window.devicePixelRatio

根据UI稿实现自适应页面

获取用户可视化窗口宽度 width: document.clientWidth(不包含border)

UI设计稿的逻辑像素 basicWidth

那么1rem=width/basicWidth 当然还可以额外除以宽高比1.5等等。

flexbile.js源码

// 首先是一个立即执行函数,执行时传入的参数是window和document
(function flexible (window, document) {
  var docEl = document.documentElement  // 返回文档的root元素
  var dpr = window.devicePixelRatio || 1 // 获取设备的dpr,即当前设置下物理像素与虚拟像素的比值

  // adjust body font size 设置默认字体大小,默认的字体大小继承自body
  function setBodyFontSize () {
    if (document.body) {
      document.body.style.fontSize = (12 * dpr) + 'px'
    }
    else {
      document.addEventListener('DOMContentLoaded', setBodyFontSize)
    }
  }
  setBodyFontSize();

  // set 1rem = viewWidth / 10  默认是10  可以根据UI搞修改
  function setRemUnit () {
    var rem = docEl.clientWidth / 10
    docEl.style.fontSize = rem + 'px'
  }

  setRemUnit()

  // reset rem unit on page resize
  window.addEventListener('resize', setRemUnit)
  window.addEventListener('pageshow', function (e) {
    if (e.persisted) {
      setRemUnit()
    }
  })

  // detect 0.5px supports  检测是否支持0.5像素,解决1px在高清屏多像素问题,需要css的配合。
  if (dpr >= 2) {
    var fakeBody = document.createElement('body')
    var testElement = document.createElement('div')
    testElement.style.border = '.5px solid transparent'
    fakeBody.appendChild(testElement)
    docEl.appendChild(fakeBody)
    if (testElement.offsetHeight === 1) {
      docEl.classList.add('hairlines')
    }
    docEl.removeChild(fakeBody)
  }
}(window, document))

案例:假如UI搞750 用户可视化窗口390

  • 导入flexible.js 配置对应的rem
  • vscode插件重新配置

1rem=390/750 1rem=0.52px 开发的时候只需要将对应的px转换成rem即可

 function setRemUnit () {
      var rem = docEl.clientWidth / 750;
      console.log('rem',rem);
      docEl.style.fontSize = rem + 'px'
 }
  

原来UI图是100px,到了用户窗口就是52px 就可以让布局不被破坏!!!

如果想要适配其他的屏幕比如1920的,那么

  • 首先需要让UI重新画图。

  • 然后找出当前1920的rem的大小

image-20230614163319907

  • 最后重新配置插件,通过媒体查询重新写一遍布局即可

    image-20230614163358647

大屏适配方法二

js获取当前屏幕宽高,然后动态设置类名

<template>
    <div :class="basicManageContainer">123123</div>
</template>

<script>
export default {
    mounted() {
        window.addEventListener('resize', this.updateScreenWidth)
    },
    beforeDestroy() {
        window.removeEventListener('resize', this.updateScreenWidth)
    },
    data() {
        return {
            screenWidth: window.innerWidth, // 获取屏幕宽度
        }
    },
    methods: {
        updateScreenWidth() {
            this.screenWidth = window.innerWidth
        },
    },

    computed: {
        basicManageContainer() {
            return {
                'basic-manage-container': true,
                'basic-manage-container-3840': this.screenWidth >= 1920 && this.screenWidth <= 3840,
            }
        },
    },
}
</script>

<style lang="scss" scoped>
.basic-manage-container {
    /* 共享的样式 */
    width: 800px;
    height: 300px;
    background-color: red;
    position: absolute;
    color: #fff;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    &-3840 {
        color: blue;
        background-color: #eee;
    }
}