移动端屏幕适配 fis3+rem方案

2024-01-26 16:58

本文主要是介绍移动端屏幕适配 fis3+rem方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

移动端多屏适配rem方案

 

背景

1. 开发移动端H5页面

2. 面对不同分辨率dpr的手机

3. 面对不同屏幕尺寸的手机

 

一、概念

1、物理像素(physical pixel)

一个物理像素是显示器(手机屏幕)上最小的物理显示单元,在操作系统的调度下,每一个设备像素都有自己的颜色值和亮度值。

2、设备独立像素(density-independent pixel)

设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如: css像素),然后由相关系统转换为物理像素。

所以说,物理像素和设备独立像素之间存在着一定的对应关系,这就是接下来要说的设备像素比

3、设备像素比(device pixel ratio )

设备像素比简称dpr定义了物理像素和设备独立像素的对应关系,它的值可以按如下的公式的得到:

设备像素比 = 物理像素 / 设备独立像素 // 在某一方向上,x方向或者y方向

javascript中,可以通过window.devicePixelRatio获取到当前设备的dpr。

css中,可以通过

-webkit-device-pixel-ratio

-webkit-min-device-pixel-ratio

 -webkit-max-device-pixel-ratio

进行媒体查询,对不同dpr的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview)。

 

综合上面几个概念,一起举例说明下:

iphone6为例:

1. 设备宽高为375×667,可以理解为设备独立像素(或css像素)。

2. dpr为2,根据上面的计算公式,其物理像素就应该×2,为750×1334

用一张图来表现,就是这样


上图中可以看出,对于这样的css样式:

width: 2px;

height: 2px;

在不同的屏幕上(普通屏幕 vs retina屏幕),css像素所呈现的大小(物理尺寸)是一致的,不同的是1个css像素所对应的物理像素个数是不一致的。

在普通屏幕下,1个css像素 对应 1个物理像素(1:1)。
retina 屏幕下,1个css像素对应 4个物理像素(1:4)。

二、视觉稿要求

1. 现主流的iphone6宽度750px(以前是iphone4320)

2. 在设计过程中注意兼容最小尺寸(320),如图片中的文字、最小字体等...

问题:

1. 对于dpr=2的手机,为什么画布大小×2,就可以解决高清问题?

2. 对于2倍大小的视觉稿,在具体的css编码中如何还原每一个区块的真实宽高(也就是布局问题)?

三、图片问题

一个位图像素是栅格图像(如:png, jpg, gif等)最小的数据单元。每一个位图像素都包含着一些自身的显示信息(如:显示位置,颜色值,透明度等)。

1、retina下,图片高清问题

解决方案:@2x/@3x,然后图片容器缩小。

2背景图片问题

解决方案:

width: 200px;

height: 300px;

background-image: url(image@2x.jpg);

background-size: 200px 300px; // 或者: background-size: contain;

缺点:

1. 普通屏幕下同样下载了@2x的图片,造成资源浪费。

2. 普通屏幕下图片由于downsampling,会失去了一些锐利度(或是色差)。

所以最好的解决办法是:不同的dpr下,加载不同的尺寸的图片

不管是通过css媒体查询,还是通过javascript条件判断都是可以的。

那么问题来了,这样的话,不就是要准备两套图片了嘛?(@1x 和@2x)

我想,做的好的公司,都会有这么一个图片服务器,通过url获取参数,然后可以控制图片质量,也可以将图片裁剪成不同的尺寸。

所以我们只需上传大图(@2x),其余小图都交给图片服务器处理,我们只要负责拼接url即可。

如,这样一张原图:

https://img.alicdn.com/tps/TB1AGMmIpXXXXafXpXXXXXXXXXX.jpg // 原图

可以类似这样,进行图片裁剪:

// 200×200

https://img.alicdn.com/tps/TB1AGMmIpXXXXafXpXXXXXXXXXX.jpg_200x200.jpg

 

// 100×100

https://img.alicdn.com/tps/TB1AGMmIpXXXXafXpXXXXXXXXXX.jpg_100x100.jpg

(ps: 当然裁剪只是对原图的等比裁剪,得保证图片的清晰嘛~)

四、border:1px问题

 

解决方案:border使用1px而非rem单位,且div的盒子模型为:border-box

这大概是前端最敏感,最关心的问题了。

先来,来看看下面的图:


上面两张图分别是在iphone3gs(dpr=1)iphone5(dpr=2)下面的测试效果,对比来看,对于1px的border的展示,它们是一致的,并无区别。

那么retina显示屏的优势在哪里,设计师为何觉得高清屏(右图)这个线条呢?明明和左右一样的~

还是通过一张图来解释


上图中,对于一条1px宽的直线,它们在屏幕上的物理尺寸(灰色区域)的确是相同的,不同的其实是屏幕上最小的物理显示单元,即物理像素,所以对于一条直线,iphone5它能显示的最小宽度其实是图中的红线圈出来的灰色区域,用css来表示,理论上说是0.5px

五、前端布局要求

方案:

使用rem 针对不同手机屏幕尺寸dpr动态的改变根节点html的font-size大小(基准值),再使用fis-postprocessor-px2rem插件让px自动转化成rem

1)、配置代码(750px的设计稿):

fis.match('*css', {

    postprocessor: fis.plugin('px2rem', {

        baseDpr: 2,  // dpr基准

        remUnit: 75,  // rem 基准,由设计稿决定750/10

        remPrecision: 6  // rem 精确位数

    })

});

这样fis3就会自动按照750的大小将px转换为rem单位;前端无需自己计算转换;

对于动态改变根节点html的font-size,要求CSS和JS配合使用(解决闪烁问题)

2)、CSS设置(通过设备宽度来媒体查询来改变html的font-size,即min-device-width/10,与fis3配置对应

@media(min-device-width:320px){html{font-size: 32px;/*no*/}}

@media(min-device-width:360px){html{font-size: 36px;/*no*/}}

@media(min-device-width:375px){html{font-size: 37.5px;/*no*/}}

@media(min-device-width:384px){html{font-size: 38.4px;/*no*/}}

@media(min-device-width:412px){html{font-size: 41.2px;/*no*/}}

@media(min-device-width:414px){html{font-size: 41.4px;/*no*/}}

@media(min-device-width:480px){html{font-size: 48px;/*no*/}}

@media(min-device-width:540px){html{font-size: 54px;/*no*/}}

@media(min-device-width:560px){html{font-size: 56px;/*no*/}}

@media(min-device-width:600px){html{font-size: 60px;/*no*/}}

@media(min-device-width:768px){html{font-size: 76.8px;/*no*/}}

@media(min-device-width:800px){html{font-size: 80px;/*no*/}}

@media(min-device-width:1080px){html{font-size: 108px;/*no*/}}

@media(min-device-width:1280px){html{font-size: 128px;/*no*/}}

@media(min-device-width:1440px){html{font-size: 144px;/*no*/}}

@media(min-device-width:1600px){html{font-size: 160px;/*no*/}}

缺点不够精确。

3)、javascript设置,通过上面的公式,计算出基准值rem,然后写入样式,大概如下

var dpr, rem;

var docEl = document.documentElement;

var fontEl = document.createElement('style');

 

dpr = window.devicePixelRatio || 1;

rem = docEl.clientWidth / 10;

 

// 设置data-dpr属性,留作的css hack之用

docEl.setAttribute('data-dpr', dpr);

 

// 动态写入样式

docEl.firstElementChild.appendChild(fontEl);

fontEl.innerHTML = 'html{font-size:' + rem + 'px!important;}';

 

// 给js调用的,某一dpr下rem和px之间的转换函数

window.rem2px = function(v) {

v = parseFloat(v);

return v * rem;

};

window.px2rem = function(v) {

    v = parseFloat(v);

    return v / rem;

};

 

window.dpr = dpr;

window.rem = rem;

这种方式,可以精确地算出不同屏幕所应有的rem基准值,缺点就是要加载这么一段js代码,但个人觉得是这是目前最好的方案了。


这篇关于移动端屏幕适配 fis3+rem方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/647453

相关文章

MySQL 迁移至 Doris 最佳实践方案(最新整理)

《MySQL迁移至Doris最佳实践方案(最新整理)》本文将深入剖析三种经过实践验证的MySQL迁移至Doris的最佳方案,涵盖全量迁移、增量同步、混合迁移以及基于CDC(ChangeData... 目录一、China编程JDBC Catalog 联邦查询方案(适合跨库实时查询)1. 方案概述2. 环境要求3.

SpringBoot3.X 整合 MinIO 存储原生方案

《SpringBoot3.X整合MinIO存储原生方案》本文详细介绍了SpringBoot3.X整合MinIO的原生方案,从环境搭建到核心功能实现,涵盖了文件上传、下载、删除等常用操作,并补充了... 目录SpringBoot3.X整合MinIO存储原生方案:从环境搭建到实战开发一、前言:为什么选择MinI

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri

SQLite3 在嵌入式C环境中存储音频/视频文件的最优方案

《SQLite3在嵌入式C环境中存储音频/视频文件的最优方案》本文探讨了SQLite3在嵌入式C环境中存储音视频文件的优化方案,推荐采用文件路径存储结合元数据管理,兼顾效率与资源限制,小文件可使用B... 目录SQLite3 在嵌入式C环境中存储音频/视频文件的专业方案一、存储策略选择1. 直接存储 vs

HTML5实现的移动端购物车自动结算功能示例代码

《HTML5实现的移动端购物车自动结算功能示例代码》本文介绍HTML5实现移动端购物车自动结算,通过WebStorage、事件监听、DOM操作等技术,确保实时更新与数据同步,优化性能及无障碍性,提升用... 目录1. 移动端购物车自动结算概述2. 数据存储与状态保存机制2.1 浏览器端的数据存储方式2.1.

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

使用Python开发一个现代化屏幕取色器

《使用Python开发一个现代化屏幕取色器》在UI设计、网页开发等场景中,颜色拾取是高频需求,:本文主要介绍如何使用Python开发一个现代化屏幕取色器,有需要的小伙伴可以参考一下... 目录一、项目概述二、核心功能解析2.1 实时颜色追踪2.2 智能颜色显示三、效果展示四、实现步骤详解4.1 环境配置4.

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

Springboot3+将ID转为JSON字符串的详细配置方案

《Springboot3+将ID转为JSON字符串的详细配置方案》:本文主要介绍纯后端实现Long/BigIntegerID转为JSON字符串的详细配置方案,s基于SpringBoot3+和Spr... 目录1. 添加依赖2. 全局 Jackson 配置3. 精准控制(可选)4. OpenAPI (Spri

关于跨域无效的问题及解决(java后端方案)

《关于跨域无效的问题及解决(java后端方案)》:本文主要介绍关于跨域无效的问题及解决(java后端方案),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录通用后端跨域方法1、@CrossOrigin 注解2、springboot2.0 实现WebMvcConfig