前端自适应方案

前端自适应方案

  • 基于rem的适配方案

    • rem: 指相对于根元素的字体大小的单位,在日常开发过程中我们通常把根元素(html/body)的字体设置为10px,方便于我们计算(此时子元素的1rem就相当于10px)

    • 适用场景不固定宽高比的Web应用,适用于绝大部分业务场景

    • 使用方式

      • 安装依赖
      npm i postcss-pxtorem autoprefixer amfe-flexible --save-dev
      

      注:postcss-pxtorem 是PostCSS的插件,用于将像素单元生成rem单位 autoprefixer 浏览器前缀处理插件 amfe-flexible 可伸缩布局方案 替代了原先的lib-flexible 选用了当前众多浏览器兼容的viewport

      • 项目根目录创建 postcss.config.js 文件
      module.exports = {
       plugins: {
        autoprefixer: {
         overrideBrowserslist: [
          "Android 4.1",
          "iOS 7.1",
          "Chrome > 31",
          "ff > 31",
          "ie >= 8",
          "last 10 versions", // 所有主流浏览器最近10版本用
         ],
         grid: true,
        },
        "postcss-pxtorem": {
         rootValue: 192, // 设计稿宽度的1/ 10 例如设计稿按照 1920设计 此处就为192
         propList: ["*", "!border"], // 除 border 外所有px 转 rem
         selectorBlackList: [".el-"], // 过滤掉.el-开头的class,不进行rem转换
        },
       },
      };
      
      • main.ts/js 文件中导入依赖
      import "amfe-flexible/index.js";
      
      • 项目重启即可
      • **建议:**vscode安装 px to rem & rpx & vw (cssrem)插件,同时在vscode左上角的文件 – 首选项 – 设置(左下角管理 – 设置) – 输入框输入“root”,找到 "基准font-size "更改为192,然后在就能够根据视觉稿中的像素值进行自动转化rem值。
  • 基于scale的适配方案

    • 在CSS3中,我们可以使用transform属性的scale()方法来实现元素的缩放效果。缩放,指的是“缩小”和“放大”的意思。

    • transform: scaleX(x); / 沿x轴方向缩放/

    • transform: scaleY(y); / 沿y轴方向缩放/

    • transform: scale(); / 同时沿x轴和y轴缩放/

    • 适用场景固定宽高比的Web应用,如大屏或者固定窗口业务应用

    • 使用方式(Vue2)

      • 新建resize.ts/js文件
      // * 设计稿尺寸(px)
      export const w = 1920;
      export const h = 1080;
      
      export default {
        data() {
          return {
            screenRef: null,
            scale: 1,
            timer: null,
            delay: 200,
          };
        },
        methods: {
          resize() {
            // 浏览器宽高
            const clientWidth = document.body.clientWidth;
            const clientHeight = document.body.clientHeight;
      
            // 计算宽高缩放比例
            const scaleW = clientWidth / w;
            const scaleH = clientHeight / h;
      
            if (clientWidth / clientHeight > w / h) {
              // 如果浏览器的宽高比大于设计稿的宽高比,就取浏览器高度和设计稿高度之比
              this.scale = scaleH;
            } else {
              // 如果浏览器的宽高比小于设计稿的宽高比,就取浏览器宽度和设计稿宽度之比
              this.scale = scaleW;
            }
            this.screenRef.style.transform = "scale(" + this.scale + ")";
          },
          resizeDelay() {
              clearTimeout(this.timer);
              this.timer = window.setTimeout(() => {
                  this.resize();
              }, this.delay);
            
          },
          setRef(ele, delay) {
              this.screenRef = ele;
              this.delay = delay;
              this.resize();
          },
        },
        mounted() {
          window.addEventListener("resize", this.resizeDelay);
        },
        beforeDestroy() {
          clearTimeout(this.timer);
          this.timer = null;
          window.removeEventListener("resize", this.resizeDelay);
        },
      };
      
      • 相关界面引入resize.ts/js

        <template>
          <div class="visualization">
            <div class="es-screen" ref="screenRef"></div>
          </div>
        </template>
        <script>
          import windowResize from './minxins/resize';
          export default {
          name: 'App',
          components: {},
          mixins: [windowResize],
          data() {
            return {}
          },
          mounted() {
            this.$nextTick(() => {
              this.setRef(this.$refs.screenRef, 200);
            });
          },
        }
        </script>
        <style lang="less" scoped>
        .visualization {
          --es-screen-width: 1920px;
          --es-screen-height: 1080px;
          --es-header-height: 72px;
          --es-block-bg: #222733;
          --es-screen-bg: rgb(22, 21, 34);
          --es-screen-text-color: #fff;
          position: relative;
          margin: 0;
          width: 100%;
          height: 100%;
          background-size: 100% 100%;
          overflow: hidden;
          background: var(--es-screen-bg);
          color: var(--es-screen-text-color);
          .es-screen {
            position: absolute;
            user-select: none;
            top: 50%;
            left: 50%;
            width: var(--es-screen-width);
            height: var(--es-screen-height);
            margin-left: calc(var(--es-screen-width) * 0.5 - var(--es-screen-width));
            margin-top: calc(var(--es-screen-height) * 0.5 - var(--es-screen-height));
            background-size: 100% 100%;
            padding: 0 20px;
            background-color: pink;
          }
        }
        </style>
        
    • 注意:如果是通过mixins的方法引入,需要在main.js文件加入下面代码:

      import minxins from './minxins/resize';
      
      Vue.use(minxins);
      
    • 使用方式(Vue3)

      • 新建resize.ts/js文件

        import { ref, onMounted, onBeforeUnmount } from 'vue'
        
        // 默认适配宽高
        export const width = 1920
        export const height = 1080
        
        type ResizeType = {
        	w?: number
        	h?: number
        	fullScreen?: boolean
        	delay?: number
        }
        
        export const useResize = (options: ResizeType = {}) => {
        	const {
        		w = width,
        		h = height,
        		fullScreen = false,
        		delay = 100
        	} = options
        	// 缩放元素
        	const screenRef = ref()
          const scale = ref(1)
          function resize() {
            // 浏览器宽高
            const clientWidth = document.body.clientWidth
            const clientHeight = document.body.clientHeight
        
            // 计算宽高缩放比例
        		const scaleW = clientWidth / w
        		const scaleH = clientHeight / h
        
            if (clientWidth / clientHeight > w / h) {
        			// 如果浏览器的宽高比大于设计稿的宽高比,就取浏览器高度和设计稿高度之比
              scale.value = scaleH
            } else {
        			// 如果浏览器的宽高比小于设计稿的宽高比,就取浏览器宽度和设计稿宽度之比
              scale.value = scaleW
            }
        
        		if (fullScreen) {
        			// 如果不在乎缩放失真的情况,可以设置全屏
        			screenRef.value.style.transform = `scale(${scaleW}, ${scaleH})`
        		} else {
        			// 否则选择适配比例缩放
        			screenRef.value.style.transform = 'scale(' + scale.value + ')'
        		}
        }
        
        const resizeDelay = debounce(resize, delay)
          onMounted(() => {
          	if (screenRef.value) {
        			resize()
            	window.addEventListener('resize', resizeDelay)
        		}
          })
        
          onBeforeUnmount(() => {
            window.removeEventListener('resize', resizeDelay)
          })
        
          return {
            scale,
        		screenRef
          }
        }
        
        /*
        用来返回防抖函数的工具函数
        */
        function debounce(callback, delay) {
          let timerId
        	return function (event) {
          	// 如果上次事件还没有真正处理, 清除
        		if (timerId) {
          		clearTimeout(timerId)
        		}
        
        		// 发事件发生指定事件后才调用处理事件的回调函数
        		// 启动定时器, 只是准备真正处理
        		timerId = setTimeout(() => {
        			// 正在处理事件
        			callback.call(null, event)
        			// 删除准备处理的标记
        			timerId = null
        		}, delay)
        	}
        }
        
      • 相关界面引入resize.ts/js

      <template>
          <div class="screen-container">
              <div class="screen-content" ref="screenRef"></div>
          </div>
      </template>
      
      <script setup lang='ts'>
      import { useResize } from '@/utils/useResize'
          
      const { screenRef } = useResize()
      
      </script>
      
      <style lang='scss' scoped>
      .es-screen-container {
      	--es-screen-width: 1920px;
          --es-screen-height: 1080px;
      	--es-header-height: 72px;
      	--es-block-bg: #222733;
      	--es-screen-bg: rgb(22, 21, 34);
      	--es-screen-text-color: #fff;
      	position: relative;
      	margin: 0;
      	width: 100%;
      	height: 100%;
      	background-size: 100% 100%;
      	overflow: hidden;
      	background: var(--es-screen-bg);
      	color: var(--es-screen-text-color);
      }
      .es-screen {
          position: absolute;
          user-select: none;
          top: 50%;
        left: 50%;
          width: var(--es-screen-width);
          height: var(--es-screen-height);
          margin-left: calc(var(--es-screen-width) * 0.5 - var(--es-screen-width));
          margin-top: calc(var(--es-screen-height) * 0.5 - var(--es-screen-height));
          background-size: 100% 100%;
          padding: 0 20px;
      }
      </style>
      
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值