页面适配,高度撑满

有的页面是整屏显示的,需要高度撑满来适配,一般设计稿的尺寸是360*800

 * 适配规则:
  - 横屏时(宽度 > 高度),按高度撑满适配:1rem = 屏幕高度 / 100
  - 竖屏时:
    - 当屏幕高度 >= 800px 时,按高度撑满适配:1rem = 屏幕高度 / 100
    - 当屏幕高度 < 800px 时,按宽度撑满适配:1rem = 屏幕宽度 / 45(宽度360px对应45rem)
1、安装postcss-pxtorem插件
2、screenAdapter.js
/**
 * 屏幕高度适配工具
 * 设计稿基准:360px * 800px
 * 根据屏幕高度动态设置rem基准值,使页面内容随高度缩放
 * 
 * 原理:设计稿800px对应100rem,所以1rem = 屏幕高度 / 100
 */

/**
 * 设置根元素字体大小(rem基准值)
 * 1rem = (屏幕高度 / 设计稿高度) * 8px
 * 这样设计稿中的800px对应100rem,360px对应45rem
 * 
 * 适配规则:
 * - 横屏时(宽度 > 高度),按高度适配:1rem = 屏幕高度 / 100
 * - 竖屏时:
 *   - 当屏幕高度 >= 800px 时,按高度适配:1rem = 屏幕高度 / 100
 *   - 当屏幕高度 < 800px 时,按宽度适配:1rem = 屏幕宽度 / 45(宽度360px对应45rem)
 */
function setRootFontSize() {
  const screenHeight = window.innerHeight || document.documentElement.clientHeight
  const screenWidth = window.innerWidth || document.documentElement.clientWidth
  
  let baseFontSize
  
  // 判断是否为横屏
  const isLandscape = screenWidth > screenHeight
  
  // 横屏时,按高度适配
  if (isLandscape) {
    // 设计稿800px对应100rem,所以1rem = 屏幕高度 / 100
    baseFontSize = screenHeight / 100
  } else {
    // 竖屏时,高度小于800时,按照宽度撑满360去适配
    if (screenHeight < 800) {
      // 设计稿宽度360px对应45rem,所以1rem = 屏幕宽度 / 45
      baseFontSize = screenWidth / 45
    } else {
      // 高度 >= 800px 时,按高度适配
      // 设计稿800px对应100rem,所以1rem = 屏幕高度 / 100
      baseFontSize = screenHeight / 100
    }
  }
  
  // 设置根元素字体大小
  document.documentElement.style.fontSize = `${baseFontSize}px`
}

/**
 * 防抖函数
 */
function debounce(func, wait) {
  let timeout
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout)
      func(...args)
    }
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
  }
}

/**
 * 使用requestAnimationFrame优化的resize处理
 */
let rafId = null
let lastHeight = window.innerHeight

function handleResize() {
  if (rafId) {
    cancelAnimationFrame(rafId)
  }
  
  rafId = requestAnimationFrame(() => {
    const currentHeight = window.innerHeight || document.documentElement.clientHeight
    const currentWidth = window.innerWidth || document.documentElement.clientWidth
    const isLandscape = currentWidth > currentHeight
    
    // 横屏时,宽度和高度变化都需要更新;竖屏时,高度小于800时宽度变化也需要更新;高度>=800时,只在高度变化时更新
    const needUpdate = isLandscape 
      ? true // 横屏时,宽度和高度变化都需要更新
      : currentHeight < 800 
        ? true // 竖屏且高度小于800时,宽度变化也需要更新
        : Math.abs(currentHeight - lastHeight) > 1 // 竖屏且高度>=800时,只在高度变化时更新
    
    if (needUpdate) {
      lastHeight = currentHeight
      setRootFontSize()
    }
    
    rafId = null
  })
}

/**
 * 初始化适配
 */
function initScreenAdapter() {
  // 初始设置
  setRootFontSize()
  
  // 监听窗口大小变化(使用防抖优化)
  const debouncedResize = debounce(handleResize, 100)
  window.addEventListener('resize', debouncedResize)
  
  // 监听屏幕方向变化
  window.addEventListener('orientationchange', () => {
    // 延迟执行,等待屏幕方向变化完成
    setTimeout(() => {
      setRootFontSize()
    }, 100)
  })
  
  // 监听页面可见性变化(处理浏览器窗口切换)
  document.addEventListener('visibilitychange', () => {
    if (!document.hidden) {
      setTimeout(() => {
        setRootFontSize()
      }, 100)
    }
  })
}

export default initScreenAdapter

3、在main.js中引入:

// 引入屏幕适配工具
import initScreenAdapter from '@/utils/screenAdapter'
// 初始化屏幕适配
initScreenAdapter()

4、postcss.config.js

module.exports = {
  plugins: {
    'postcss-pxtorem': {
      rootValue: 8, // 设计稿800px对应100rem,所以1rem=8px
      unitPrecision: 3, // 保留3位小数
      propList: ['*'], // 所有属性都转换
      selectorBlackList: [], // 不排除任何选择器
      replace: true, // 替换而不是添加
      mediaQuery: false, // 不转换媒体查询中的px
      minPixelValue: 1, // 最小转换值,小于1px的不转换
      exclude: /node_modules/i // 排除node_modules中的文件
    }
  }
}

5、在vue文件中直接使用设计稿上的尺寸(单位是px)即可

 

posted @ 2025-12-02 15:21  chicidol  阅读(3)  评论(0)    收藏  举报