【PC端web移植到ipad端web项目落地经验】-移动端的web适配

3,362 阅读5分钟

背景:pc端项目原本都是固定写死的宽高,没做适配效果。需求:将pc端的web改造支持ipad显示,保持布局正常。

一、PC端到ipad端的web适配方案

考虑方案有如下几种:

  1. 动态计算meta标签大小的initial-scale值,进行缩放,默认为1。效果相当于把整个页面缩放 (实验可行,简单暴力)

通过设置缩放比例达到缩放效果,缺点是无法控制不缩放的元素,因为他是整个项目进行缩放。据说易企秀使用这种方案,因为它们是通过拖拽开发生成手机端web页面,做适配这种最快。

 function setScale() {
  const viewportWidth = 1920;  // 设计稿的宽度
  const clientWidth = document.documentElement.clientWidth;
  const viewport = document.querySelector('meta[name="viewport"]');
  const viewportScale = clientWidth / viewportWidth;
  viewport.setAttribute('content', 'width=' + viewportWidth + ', initial-scale=' + viewportScale + ', minimum-scale=' + viewportScale + ', maximum-scale=' + viewportScale + ', user-scalable=0');

  if (document.addEventListener) {
    const resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize'
    window.addEventListener(resizeEvt, setRem, false)
    document.addEventListener('DOMContentLoaded', setRem, false)
  }
}
  1. postcss-px-to-viewport (未实践)
  2. pxtorem (当前方案)

二、采用pxtorem方案实现流程

知识点:em是根据父级的字体大小来计算,rem是根据root根节点大小来计算(即HTML标签的font-size),web默认为16px,即1rem=16px。

所以,为了保证移动端多种屏幕分辨率下能自适应缩放到合理效果(视觉窗口),就要先计算在不同像素屏幕下的根节点字体大小,然后rem会再根据这个根节点字体大小在自动适配宽高字体大小边距等。这是实现的思路的解析。

看如下代码实现:

1、 在项目启动时设置html的font-size大小

// 设计稿宽度
const DESIGN_WIDTH = 1920  // 以你的基础设计图宽度为标准,手机端可能是750或是其他标准

export default function setRem(designWidth = DESIGN_WIDTH) {
  const docEl = document.documentElement
  const resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize'
  const reCalc = function () {
    const clientWidth = docEl.clientWidth
    if (!clientWidth) return
    // 这里的默认值 100 也可以设置其他值,但需要与第二步的rootValue相同
    docEl.style.fontSize = 100 * (clientWidth / designWidth) + 'px' 
  }
  reCalc()
  if (document.addEventListener) {
    window.addEventListener(resizeEvt, reCalc, false)
    document.addEventListener('DOMContentLoaded', reCalc, false)
  }
}

2、 安装 npm install postcss-pxtorem。在vue.config.js文件中使用pxtorem插件,该插件会自动把px转化为rem(修改完需要重启项目)

module.exports = {
   // 在css下添加引用这个插件
  css: {
    loaderOptions: {
      postcss: {
        plugins: [
          require('postcss-pxtorem')({
            rootValue: 100, // 这个值表示根节点的基础值大小,随意设置,但一定要与第一步的值相同
            unitPrecision: 5,
            propList: ['*'],
            selectorBlackList: [],
            replace: true,
            mediaQuery: true,
            minPixelValue: 0,
            // 是否排除转换node_modules下的px,一般不排除,因为使用的ui组件是px为单位也需要转换
            // exclude: /node_modules/i
          })
        ]
      }
    }
  },
}

3、 添加meta标签,一般默认都会有的

<meta name="viewport" content="width=device-width,initial-scale=1">

三、遇到的问题,最佳实践解决方案

1、雪碧图怎么适配缩放?

添加background-size属性,必须和当前的图片宽高大小相等,原理是pxtorem也会同步转换它的背景大小。

2、img标签图片大小怎么适配缩放?

使用css给img添加宽高属性,不写行内样式,因为行内样式pxtorem无法转换

3、页面内嵌套iframe怎么适配当前页面 缩放?

  1. 使用meta强制通过设置initial-scale缩放会有跨域问题 (不推荐)
  2. 嵌套的页面也使用pxtorem做转换(不推荐,工作量大;且可能iframe还有iframe;子页面可能是其他网站改不了)
  3. 使用transform缩放iframe来解决 (推荐)
.mydiv {
    position:relative;
    width: 500px;
    height: 500px;
 }

#iframeA {
        position: absolute;
        transform: scale(.5, .5) translate(-50%, -50%); // 缩放0.5width: 200%;
        height: 200%;
        top: 0;
        left: 0
    }
 
<div class="mydiv">
    <iframe id="iframeA" src="http://www.baidu.com" frameborder="0"> </iframe>
</div>

可以js动态计算transform: scale的比例来控制缩放大小,即设计稿宽度 / document.documentElement.clientWidth来设置缩放的准确比例。

4、如何处理1px问题?

画一条1px的线条:

.wrap_div {
  height: 1px;
  overflow: hidden;
  background: #000;
}

@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  .wrap_div:before {
    transform: scaleY(0.5);
  }
}

@media only screen and (-webkit-min-device-pixel-ratio: 3) {
  .wrap_div:before {
    transform: scaleY(0.33);
  }
}

<div className={styles.wrap_div}>   

</div>

四、关于调试

知识点:PC端最小字体是12px,移动端则没有限制。所以在电脑上模拟调试ipad效果时候可能会有点不同,字体的显示效果。

五、响应式和固定排版有些区别要注意下(附图)

1、响应式适配:

实现:使用 @media + 百分比% + 动态calc() + rem来写,实现到不同设备屏幕不同布局的不同效果。rem是必须,因为设计移动端的字体大小,布局则用百分比%和@media来控制。

2022.10.10_59326346f2fe7646d3c3ad6bf8ab998.png

展示效果预览:data.gov.mo/ 切换不同分辨率可查看,根据不同的屏幕大小情况下展示不同的布局,这是响应式布局。

2、固定排版的适配(如在手机端时候):

目的,为了实现不同移动端,假设是手机端,都显示相同的布局相同的效果,即排版不变,看下面图例。 2022.10.10_&25fdf0b33c75f67009af822362ebbadc.png

实现:使用固定像素px(rem),即固定宽高,或vw、vh来写。最好不要用百分比%配合px来写宽高边距等。

因为,可能在A机型上面正常,B机型上宽度不够,出现塌缩了。如左右两个div,左边div 300px,右边50%(或是50vw),这种情况容易造成宽度不够影响布局效果;或是里面有文字时宽度不够被压缩出现省略号或者换行的效果(假设我们不想要这种效果)。

请看下面的错误例子:❌ 2022.10.10_&5ad3c11784d730d931367957a5768d27.png