前端知识

web移动端适配方案之rem适配

2019-08-01  本文已影响0人  CoderXLL

相关标签
remviewportmediaQueryvw,vh...

前言

最近空余时间,还是在找些react小项目练手。练手的项目不是别的,正好是目前在做的iOS项目,在边做iOS边写react的对比中,自然而然地牵扯到了webApp的适配问题。

一、移动端适配前期准备

meta标签设置ideal viewport

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">

meta viewport 标签首先是由苹果公司在其safari浏览器中引入的,目的就是解决移动设备的viewport问题。因为好用后面的各种浏览器都纷纷对此进行了兼容。这里就不解释viewport的方方面面了,这篇文章解释的很详细。移动前端开发之viewport的深入理解

二、理解rem是什么

“font size of the root element”,W3C官网是这样定义的。直白点说就是根节点元素,(一般为<html>标签)的fontSize
打个比方:

如果根节点的元素fontSize设为100px,意味着1rem=100px。那么我们如果有一个边距在UI标注中为200px,就可以写为2rem

嗯...很好理解。这也是我查看N多前端童鞋写的相关rem文章时他们主要提到的。问题是,这和传说中适配有什么关系?
别着急,耐心看下去~

三、先来谈一下iOS端的比例适配

直接看代码,以下是我在iOS端处理的适配方案:
OC代码:

/**
 *  375为UI标注采用的屏幕宽度标准
 *  实际屏幕宽 / 375,获取真实尺寸与UI尺寸比例
 */
#define BEI6 (MIN(Screen_Width, Screen_Height) / 375)
/**
 *  size为UI标准的期望值
 *  根据真实尺寸与UI尺寸的比例,计算出期望值的真实尺寸
 */
#define AutoSize(size) ((size) * BEI6)
/**
 *  根据UI标注的frame获取真实frame
 */
#define AutoFrame(frame) CGRectMake(frame.origin.x*BEI6,frame.origin.y*BEI6, frame.size.width*BEI6, frame.size.height*BEI6)

swift代码:

public func kBEI6() -> CGFloat {
    return min(kScreenWidth, kScreenHeight) / 375.0
}
public func kAutoSize(size: CGFloat) -> CGFloat {
    return kBEI6() * size
}
public func kAutoFrame(frame: CGRect) -> CGRect {
    return CGRect(x: (kBEI6() * frame.origin.x), y: (kBEI6() * frame.origin.y), width: (kBEI6() * frame.size.width), height: (kBEI6() * frame.size.height))
}

代码很简洁,很容易就能明白。
就是通过手机真实屏幕的宽度除以UI标注上的宽度尺寸,获得一个比例。再以这个比例为媒介获取每一个期望值在真实手机上的真实尺寸。

实际上rem适配的精髓和这种iOS适配方式如出一辙!

题外话:非移动端的童鞋可以忽略!!!
移动端原生控件的宽高其实并不是指单纯的像素,因为有retina屏的原因,所以原生中的1 有可能为2px或3px。这就导致了原生控件中假如给定宽为100,实际上在相同物理屏幕宽度下,其有可能是200像素,也有可能是300像素。移动端懂得自然懂。6s和6plus就是个极为典型的例子,其屏幕宽度都是414point。但其一个为2倍屏,即宽度为828像素;一个为3倍屏,宽度为1242像素。

三、rem是如何进行比例适配的

子标题这样说,细究起来是不对的。因为rem只是一个单位,1rem=根节点的fontSize值而已。其本身是不具备适配功能的。
但是其与根节点的fontSize有这种特殊关系,那我们大可以对根节点的fontSize做做手脚~通过动态设置根节点fontSize,即动态设置单位rem值,实现比例适配。
刚才说了rem适配其实与我那种iOS比例适配有异曲同工之妙iOS适配的比例因子是真实屏幕宽度与UI标注宽度的商。那在我们web端,如果获取到浏览器的真实宽度(webApp中就是webView宽度),通过其与UI标注的宽度进行除法运算,商就是我们需要的适配比例因子。再通过这个比例因子,动态比例地设置根标签的fontSize,从而达到1 rem值对应像素单位px的比例升降。
知道了步骤,我们编写代码如下:
请仔细阅读注释,句句精髓

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
    <title>rem适配</title>
    <!--因为是设置样式的js代码,所以写在head标签中了-->
    <script type="text/javascript">
        //自执行匿名函数
        (function (uiWidth, expectFontSize) {
            //获取浏览器真实宽度
            let deviceWidth = document.documentElement.clientWidth
            function setRemUnit() {
                //计算适配比例
                let scale = deviceWidth / uiWidth
                //乘以100的目的是,这样我们将UI标注的px值除以100,就是我们需要的rem值
                document.documentElement.style.fontSize = scale * expectFontSize + 'px'
            }
            //执行初始rem函数
            setRemUnit()
            //设置监听,当window重新resize的时候,重新初始rem
            window.addEventListener('resize', setRemUnit)
        })(375, 100)
    </script>
</head>

以上代码中的375,是假设的UI标注的标准宽度。依具体的UI标注进行替换。
核心思想就是设备屏幕宽度不同,比例因子不同。从而使得根标签的fontSize不同,也就是单位rem对应的px值不同。 1rem = 比例因子 * 默认期望值
我们根据上面的代码捋一下产生的结果:

四、媒体查询对特殊情况进行适配

做iOS开发的时候,使用上面我提到的比例适配方案,有时候并不能完美地去进行适配。比如处理刘海屏、适配iOS11等情况。这个时候命令式的iOS语法会单独地对这些情况去做处理。那么前端语言要怎么去解决这个问题呢?

@media 媒体类型 and (媒体特性: 600px) {
     选择器 {
       属性:属性值;
     }
 }

具体的媒体类型和特性可以在W3C官网上查看,我个人觉得没必要看,会一些常用的。其他到用到时再去查阅即可。
举个例子说明一下:

//处理屏幕宽小于等于320px时,类名为inner的标签样式
@media screen and (max-width: 320px) {
    .inner {
        height: 100%;
        width: 25%;
        float: left;
    }
}
//处理屏幕宽大于等于321px时,类名为inner的标签样式
@media screen and (min-width: 321px) {
    .inner {
        height: 50px;  
        width: 100%;
     }
}

五、vh、vw方案适配

这种好像算是目前最流行的移动端适配方案,暂时还没接触。待定...

上一篇下一篇

猜你喜欢

热点阅读