• Web移动端 自适应缩放界面


    在开发App端的网页时,要适配iphone、ipad、ipod、安卓等各种机型,一般是直接使用em、px转em、界面缩放。

    本章是通过将界面缩放,等比例显示在各机型上。过程中遇到了些问题和大坑~

    然后下面是具体的自适应尝试~

    方案一 设置tranform/scale

    首先设置内容固定宽度、自动高度(以下举例)

       375px;
      height: auto;
    通过获取窗口的宽度与固定宽度相除,获得缩放比例
    const scaleValue=window.innerWidth / 375
    在html层,添加一段script:
     1 <script dangerouslySetInnerHTML={{ __html: this.getScript() }}></script> 

    添加一段设置zoom值的函数:

    1   getScript() {
    2     return `
    3       const zoomValue=window.innerWidth / 375;
    4       document.documentElement.style.transform="scale("+zoomValue+")";
    5       document.documentElement.style.transformOrigin="left top";
    6     `;
    7   }

    注:

    以上也可以直接写script,我上面返回一段html是因为项目是通过服务端渲染的。

    样式的设置必须在界面加载之前,否则会因界面显示变更出现闪现问题。

    因为添加了服务端渲染,所以无法在界面一开始初始时,无法获取window、document等对象。而上面html的注入,对服务端渲染机制的一个黑科技~

    上面的方案完成后,看看效果。然后坑出来了:

    1. 项目设置的absolue元素width 100%失效了 -- 可以设置固定的宽度解决
    2. 弹框position=fixed位置飞到天边去了 -- 这个无法规避

    网上找到了一篇文章 CSS3 transform对普通元素的N多渲染影响 ,介绍了transform的一堆坑。

    我这个项目一些布局需要position=fixed,所以tranform不适合~放弃

    这个坑的其它介绍可以参考下:

    总结:

    1. position:fixed不支持,所以想做标题栏置顶,上面方案是无法实现的。
    2. ipad有遗留问题:微信浏览器,横竖屏切换时,有些机型在打开一瞬间,横向拖动有空白问题。这个问题无法处理~
    3. 以上方案因为使用了scale,同时窗口的宽高window.innerHeight无法准确获取,需要除以比例,比如: window.innerHeight / (window.innerWidth / 375)

    方案二 设置zoom

    在上一个方案的基础上,尝试zoom缩放:

    1   getScript() {
    2     return `
    3       const zoomValue=window.innerWidth / 375;
    4       document.documentElement.style.zoom = zoomValue;
    5     `;
    6   }

    emmm,很简单,调试效果看起来很不错。模拟机上,看起来都正常~

    但是坑来了:真机有问题,发现在ipad的safari上,页面是放大了,但是字段根本就没变化!

    原因竟然是:苹果在ipad的网页,改动渲染方面的相关规则。有点坑~

    https://apple.stackexchange.com/questions/377216/css-zoom-does-not-work-ipad-os-v13-latest-safari

    https://stackoverflow.com/questions/7907760/why-the-font-size-wont-change-with-browser-zoom-in

    实现没办法,我后面尝试,通过userAgent对ipad机型(ipad、macintosh)特殊处理,直接获取所有包含了文字的div、p、span等元素,放大font-size。

    发现可以处理,没毛病!但是也有些缺陷,没办法在一开始处理字体,因为元素还没有初始化,而等界面加载后再刷字体大小,界面会闪现一次。

    方案三 设置viewport-scare

    在html中添加默认viewport:

    1 <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1,user-scalable=no, minimal-ui"></meta>

    ps:minimal-ui 与本文无关,它可以在safari加载网页时隐藏地址栏与导航栏

    添加viewport更新:

    1   getScript() {
    2     return `
    3       const zoomValue=window.innerWidth / 375;
    4       var viewport = document.querySelector("meta[name=viewport]");
    5       viewport.content="width=device-width,initial-scale="+zoomValue+", maximum-scale="+zoomValue+", minimum-scale="+zoomValue+",user-scalable=no, minimal-ui"
    6     `;
    7   }

    运行代码,emmm,有一些小问题。

    • margin:auto,在某些布局下会让页面偏移 -- 删除就好
    • 设置background-image的区域,背景图片并没有填充满 -- 添加width:100%解决
    • position:fixed,宽高显示有问题 -- 设置固定宽度,比如375px,固定高度;如果需要全屏,可以使用height: 100vh

    fixed布局建议:以弹框为例

    添加fixed布局的容器,水平竖直方向靠边距离分别设置一个就行了,left:0,bottom:0。

    然后添加absolute布局的内容容器.如果需要居中,可以在js中设置bottom=window.innerHeight / 2 - 元素的高度/2

    总结:

    1. 以上方案不支持fixed布局,修改完成后,ipad的水平滚动条依然存在,无法解决

    兼容适配

    采用第二个zoom缩放方案,同时对ipad机型特殊处理,另外采用scale缩放方案。

    完整代码如下:

    1. 初始化适配(支持服务端渲染)

    html-header添加script

    1    {/* app contentAutoFit */}
    2    <script dangerouslySetInnerHTML={{ __html: this.getZoomScript() }}></script>

    自适应可执行代码文本

     1 //返回自适应html字符串
     2 getZoomScript() {
     3   return `
     4     const zoomValue = window.innerWidth / 375;
     5     const userAgentInfo = window.clientInformation.appVersion;
     6     //如果是ipad
     7     if (userAgentInfo.indexOf("iPad") != -1 || userAgentInfo.indexOf("Macintosh") != -1) {
     8       //内容自适应 - 设置transform-scale。
     9       //fixed布局时需要修改下left/margin-left等,同时窗口的宽高无法准确获取,需要除以比例,详见windowSizeWithScaleHelper
    10       //ipad有遗留问题:微信浏览器加载时,横竖屏切换一瞬间,有空白问题。不过可以忽略~
    11       document.documentElement.style.transform = "scale(" + zoomValue + "," + (zoomValue < 1 ? 1 : zoomValue) + ")";
    12       document.documentElement.style.transformOrigin = "left top";
    13       var html = document.querySelector("html");
    14       html.style.width = '375px';
    15       html.style.overflow = 'hidden';
    16       html.style.overflowY = 'auto';
    17     } else {
    18       //内容自适应 - 设置zoom。通过zoom来缩放界面,在ipad的safari浏览器等会存在字体无法缩放的兼容问题。
    19       document.documentElement.style.zoom = zoomValue;
    20     }
    21     // 内容自适应 - 设置viewport,整体okay。但是ipad的水平滚动条无法解决
    22     // var viewport = document.querySelector("meta[name=viewport]");
    23     // viewport.content = "width=device-width,initial-scale=" + zoomValue + ", maximum-scale=" + zoomValue + ", minimum-scale=" + zoomValue + ",user-scalable=no, minimal-ui"
    24    `;
    25 }

    2. 添加加载及界面变更刷新机制

    • 微信浏览器横竖屏切换时,某些机型不会触发窗口大小变更,所以需要额外添加orientationchange监听
    • 加载过程中,微信浏览器切换横竖屏会有显示问题,需要加载完成后适配
     1   componentDidMount() {
     2     //window.onresize = this.adjustContentAutoFit;
     3     //解决微信横竖屏问题
     4     window.addEventListener("orientationchange", this.adjustContentAutoFit);
     5     //解决加载过程中,切换横竖屏,导致界面没有适配的问题
     6     this.adjustContentAutoFit();
     7   }
     8   componentWillUnmount() {
     9     window.removeEventListener("orientationchange", this.adjustContentAutoFit);
    10   }
    11   //监听窗口尺寸变更,刷新自适应
    12   adjustContentAutoFit() {
    13     const zoomValue = window.innerWidth / 375;
    14     const userAgentInfo = window.clientInformation.appVersion;
    15     //如果是ipad
    16     if (userAgentInfo.indexOf("iPad") != -1 || userAgentInfo.indexOf("Macintosh") != -1) {
    17       //内容自适应 - 设置transform-scale。
    18       //fixed布局时需要修改下left/margin-left等,同时窗口的宽高无法准确获取,需要除以比例,详见windowSizeWithScaleHelper
    19       //ipad有遗留问题:微信浏览器,横竖屏切换时,有些机型在打开一瞬间,有空白问题。不过可以忽略~
    20       document.documentElement.style.transform = "scale(" + zoomValue + "," + (zoomValue < 1 ? 1 : zoomValue) + ")";
    21       document.documentElement.style.transformOrigin = "left top";
    22       var html = document.querySelector("html") as HTMLElement;
    23       html.style.width = '375px';
    24       html.style.overflow = 'hidden';
    25       html.style.overflowY = 'auto';
    26     } else {
    27       // 内容自适应 - 设置zoom。通过zoom来缩放界面,在ipad的safari浏览器等会存在字体无法缩放的兼容问题。
    28       document.documentElement.style.zoom = zoomValue;
    29     }
    30     // 内容自适应 - 设置viewport,整体okay。但是ipad的水平滚动条无法解决
    31     // var viewport = document.querySelector("meta[name=viewport]");
    32     // viewport.content = "width=device-width,initial-scale=" + zoomValue + ", maximum-scale=" + zoomValue + ", minimum-scale=" + zoomValue + ",user-scalable=no, minimal-ui"
    33   }

    此方案的一些小遗留问题:

    1. ipad不支持position:fixed,所以无法实现标题栏置顶等功能

    2. 微信浏览器,横竖屏切换时,有些机型在打开一瞬间,有空白问题

    参考:

    1. IOS环境下固定定位position:fixed带来的问题与解决方案
    2. 小技巧css解决移动端ios不兼容position:fixed属性,无需插件
    3. 踩坑路上——IOS Safari浏览器下固定定位position:fixed带来的问题与解决方案
    4. iphone safari不支持position fixed的解决办法
    5. orientationchange事件、监测微信移动端横竖屏
  • 相关阅读:
    Js获取时间,当前,一周前,一月前的时间,时间戳转换,时间格式化,日期格式化
    echarts图随窗口大小的变化而变化
    Vue中使用Google地图插件
    element el-progress渐变色进度条
    Vue中使用mixins
    CSS3 使用 calc() 计算高度 vh px
    element-ui饿了么框架中导航菜单中箭头方向问题
    Vue中使用QRcode.js生成二维码---qrcodejs2
    鼠标经过时显示样式的两种方法
    element 按钮样式:确认按钮发布后样式发生改变
  • 原文地址:https://www.cnblogs.com/kybs0/p/13228133.html
Copyright © 2020-2023  润新知