zoukankan      html  css  js  c++  java
  • 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事件、监测微信移动端横竖屏
  • 相关阅读:
    【BZOJ 4581】【Usaco2016 Open】Field Reduction
    【BZOJ 4582】【Usaco2016 Open】Diamond Collector
    【BZOJ 4580】【Usaco2016 Open】248
    【BZOJ 3754】Tree之最小方差树
    【51Nod 1501】【算法马拉松 19D】石头剪刀布威力加强版
    【51Nod 1622】【算法马拉松 19C】集合对
    【51Nod 1616】【算法马拉松 19B】最小集合
    【51Nod 1674】【算法马拉松 19A】区间的价值 V2
    【BZOJ 2541】【Vijos 1366】【CTSC 2000】冰原探险
    【BZOJ 1065】【Vijos 1826】【NOI 2008】奥运物流
  • 原文地址:https://www.cnblogs.com/kybs0/p/13228133.html
Copyright © 2011-2022 走看看