挑战21天手写前端框架 day17 移动端屏幕适配方案实现

简介: 挑战21天手写前端框架 day17 移动端屏幕适配方案实现

image.png

原理

先讲重点,我们使用的方案是在淘宝高清方案的基础上修改的方案,因为淘宝高清方案使用 meta 使用 0.5,这个设定在将移动端页面嵌套到其他平台的 iframe 中,会有内外 viewport 不一致导致的缩放问题,因此我们将 initial-scale 默认为 1。


设置为1也会有内外不一致的问题,只是现在对接的系统多数都写1,跨域部署的时候,没办法获取到,所以这里我暂时没有更好的解法。


我们的实现原理其实很简单,将项目中写的 px 值,通过 postcss 转换成 rem 单位。然后通过动态修改 html 上的 fontsize 大小,来实现在不同的屏幕上 px 的缩放比一致的效果。

在讲的简单一点,比如我们在一个宽度为 50 的屏幕上,看到一个宽度为40的按钮。我们期望在宽度100的屏幕上,看到它时,它的宽度应该是 80.



实现

转换所有的 px 为 rem

实现原理比较简单,就是通过 postcss 插件,匹配正则然后做一个值除与100的转化,比如 32px 转为 0.32rem。 为什么是除 100 而不是其他的值呢,是为了便于计算和直观表现做的约定。比如 css 文件中我们通过 postcss 转换,而在内联样式中,我们需要手动写明 rem 单位。这时候除与100,就只是简单的小数点缩进。


上面的理由其实还是不够充分说明为什么是 100。这其实还和设备的像素点和像素倍率dpr等知识点有关,这里我不详细的展开,只做简要说明。在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rem =100px = 100物理像素。所以就相当于 iPhone6 上面取一整个屏幕宽度为 7.5rem 。设计师在输出设计稿的时候,只要以 iPhone6 的标准输出,我们就可以直接使用设计师标注的尺寸进行开发了。


我们使用 postcss 转换我们之前使用 esbuild 构建后的样式产物。

安装需要的模块

cd packages/malita
pnpm i postcss @alitajs/postcss-plugin-px2rem
复制代码

@alitajs/postcss-plugin-px2rem 是在 postcss-plugin-px2rem 的基础上修改的,我增加了一个配置 selectorDoubleRemList: [/.adm-/, /.ant-/] 被匹配中的样式中 px 会被转化成两倍的 rem,比如 32px 转为 0.64rem。 这在使用一些没有使用高清方案编写的组件时非常有用。


修改 packages/malita/src/styles.ts,以下仅仅摘录了本次的修改。我们将 esbuild 构建后的产物,使用 postcss 再构建一次。

+ import postcss from 'postcss';
+ // @ts-ignore
+ import px2rem from '@alitajs/postcss-plugin-px2rem';
const { errors, warnings, outputFiles } = await esbuild.build(
    {
        entryPoints: [args.path],
        logLevel: 'silent',
        bundle: true,
        write: false,
        charset: 'utf8',
        minify: true,
        loader: {
            '.svg': 'dataurl',
            '.ttf': 'dataurl',
        },
    }
);
+ if (errors.length > 0) {
+     return {
+         errors,
+         warnings,
+         contents: outputFiles![0].text,
+         loader: 'text',
+     };
+ }
+ try {
+     const result = await postcss(
+         [
+             px2rem({
+                 rootValue: 100,
+                 minPixelValue: 2,
+                 selectorDoubleRemList: [/.adm-/, /.ant-/],
+             }),
+         ],
+     ).process(outputFiles![0].text, {
+         from: args.path,
+         to: args.path,
+     });
+     return {
+         errors,
+         warnings,
+         contents: result.css,
+         loader: 'text',
+     };
+ } catch (error){
+     return {
+         errors,
+         warnings,
+         contents: outputFiles![0].text,
+         loader: 'text',
+     };
+ }
复制代码


运行验证

cd examples/app
pnpm dev
> malita dev
App listening at http://127.0.0.1:8888
复制代码


查看产物文件 examples/app/dist/malita.js 全文搜索 malita-home,我们将会看到 font-size 被转换成 0.32rem

var home_default = ".malita-home{font-size:0.32rem;background:blue;width:1rem}\n";
复制代码


动态修改 html 的 font-size

新建文件 packages/malita/src/hd.ts,实现复制了 alita 中的实现,这个在很多文章中都有体现,我这里就列出来的了。 主要需要注意的几个点如下:

1、安卓dpr乱标

2、非淘宝高清方案,默认的 initial-scale 为 1

3、有些兼容环境下, fontSize为100px的时候, 结果1rem=86px; 需要纠正viewport

4、在 iframe 中打开

5、手机横屏需要使用高作为标准而不是宽

6、部分安卓手机转屏之后,需要延迟获取可视宽高

7、横屏模式时手机软件盘键盘弹起事件


在框架中引入 hd 脚本,修改我们的主入口文件,添加 import '/Users/congxiaochen/Documents/malita/packages/malita/lib/hd';

实现很简单就是修改我们之前的新建主入口文件的方法,在返回的 content 的 import 部分增加 import '${path.resolve(__dirname,'hd')}';。如果你没有想到这里的实现,可能你之前的 generateEntry 的逻辑还没有很理解。


运行验证

cd examples/app
pnpm dev
> malita dev
App listening at http://127.0.0.1:8888
复制代码


使用谷歌浏览器的手机模拟器,Dimensions: iPhone 6/7/8 访问 http://127.0.0.1:8888,打开控制台查看 elements ,需要关注的信息在 html 的上方

1、 html 上的 style

<html lang="en" style="font-size: 50px;" data-scale="true">
复制代码


2、meta 信息

<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,viewport-fit=cover">
复制代码


感谢阅读,今天的内容做了部分的简略,因为关于单位都是标准的文档,我就没有再拷贝一份了。你可以简单的理解,使用高清方案的时候,主要就是有 rem 、动态的 fontsize 和 meta 组合控制的,这样当你在项目中遇到整体的适配有误时,你就知道该从这些地方着手调查了。


源码归档

目录
相关文章
|
1天前
|
移动开发 编解码 前端开发
【面试题】前端 移动端自适应?
【面试题】前端 移动端自适应?
|
1天前
|
前端开发 JavaScript
Web前端之移动端课程开发之06.bootstrap
Web前端之移动端课程开发之06.bootstrap
49 0
|
8月前
|
JSON 前端开发 JavaScript
前端(十七)——gitee上开源一个移动端礼盒商城项目(前端+后台)
前端(十七)——gitee上开源一个移动端礼盒商城项目(前端+后台)
100 0
|
10月前
|
移动开发 前端开发
前端(十八):移动端H5调用摄像头拍照旋转解决方案
移动端H5调用摄像头拍照旋转解决方案
222 0
|
1天前
|
编解码 前端开发 JavaScript
【Web 前端】移动端适配方案有哪些?
【4月更文挑战第22天】【Web 前端】移动端适配方案有哪些?
|
1天前
|
前端开发 JavaScript 容器
前端vw自适应解决方案,适用pc端以及移动端,适用webpack以及vite,适用vue以及react
前端vw自适应解决方案,适用pc端以及移动端,适用webpack以及vite,适用vue以及react
79 0
|
1天前
|
编解码 前端开发 UED
Web前端开发中的移动端适配与响应式设计
【2月更文挑战第11天】 对于现代 Web 前端开发而言,移动端适配与响应式设计是至关重要的技术环节。移动设备的普及使得用户更多地通过手机或平板设备访问网站,因此,如何有效地适配各种屏幕尺寸并提供良好的用户体验成为了前端开发者需要面对的重要问题。本文将介绍移动端适配与响应式设计的基本原理,并结合实际案例探讨其在前端开发中的应用。
|
1天前
|
移动开发 前端开发 JavaScript
web前端移动端课程之canvas教程系列
web前端移动端课程之canvas教程系列
49 0
|
6月前
|
移动开发 前端开发 JavaScript
前端开发中web和移动端动画的常见实现方式
前端动画一般在展示性网站、交互操作或者移动端活动页面使用比较多,可能对于大部分前端平时只会用 css 里的 transition 动画,其实前端动画还有很多实现方式
91 0
|
6月前
|
存储 移动开发 前端开发
前端-移动端--支付
前端-移动端--支付
37 0