网站客服:zx81024163 |

如何适配不同分辨率和不同屏幕尺寸的手机

2023-12-11 07:00:45发布    浏览635次    信息编号:87636

友情提醒:凡是以各种理由向你收取费用,均有骗子嫌疑,请提高警惕,不要轻易支付。

如何适配不同分辨率和不同屏幕尺寸的手机

背景

开发移动H5页面

面对不同分辨率的手机

面对不同屏幕尺寸的手机

视觉模型

在前端开发之前, MM会给我们一个psd文件,称为视觉稿。

对于移动开发来说,为了实现页面的高清效果,视觉稿的规范往往会遵循以下两点:

首先,选择手机的屏幕宽度和高度作为基准(以前是320×480,现在更多的是375×667)。

对于屏幕(例如:dpr=2),为了达到高清效果,视觉稿的画布尺寸会是基线的两倍,也就是说像素数会是原来的4倍(例如:原来的375×667,会变成750×1334)。

问题:

对于dpr=2的手机,为什么尺寸×2就能解决高清问题呢?

对于两倍大小的视觉稿,如何在具体的CSS编码中恢复每个块的真实宽度和高度(即布局问题)?

带着疑问往下看……

一些概念

在进行具体分析之前,首先要了解以下关键的基本概念(术语)。

物理像素

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

设备独立像素(-pixel)

设备无关像素(也称为密度无关像素)可以被视为计算机坐标系中的一个点。 该点代表程序可以使用的虚拟像素(例如:CSS像素),然后由相关系统转换为物理像素。

因此,物理像素和设备无关像素之间存在一定的对应关系。 这就是我们接下来要讲的设备像素比。

设备像素比(像素比)

设备像素比(简称dpr)定义了物理像素和设备独立像素之间的对应关系。 其值可根据以下公式求得:

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

在 中,可以通过获取当前设备的dpr。

在css中,可以使用--pixel-ratio、--min--pixel-ratio和--max--pixel-ratio来执行媒体查询,并对不同DPR的设备进行一些样式适配(这仅适用于内核浏览器和)。

结合上面的概念,我们用例子来说明一下:

例如:

设备宽度和高度为375×667,可以理解为设备独立像素(或CSS像素)。

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

用图片来表达就是这样的(原谅我盗图):

如上图所示,对于这样的css样式:

width: 2px;
height: 2px;

在不同的屏幕上(普通屏 vs 屏幕),CSS像素所呈现的尺寸(物理尺寸)是相同的,但不同的是,1个CSS像素对应的物理像素数量不一致。

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

位图像素

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

说到这里就不得不说说下面图片的显示?

理论上,1个位图像素对应1个物理像素,这样图片才能完美、清晰地显示。

正常屏幕下没有问题,但屏幕下会出现位图像素不够,导致图片模糊的情况。

用一张图片来表示:

如上图:对于dpr=2的屏幕,1个位图像素对应4个物理像素。 由于单个位图像素无法进一步划分,因此只能从最近的位置取颜色,导致图片模糊(注意上面几个颜色值)。

因此,对于高清图片的问题,更好的解决方案是图片加倍(@2x)。

例如:200×300(css像素)img标签,您需要提供400×600的图片。

这样,位图像素数就变成了原来的4倍。 在屏幕下,位图像素数可以与物理像素数形成1:1的比例,图片自然就清晰了(这也解释了回答之前留下的一个问题,为什么视觉稿的画布大小是× 2?)。

这里还有一个问题。 如果在普通屏幕上使用两倍的图像会发生什么?

显然,在普通屏幕上,200×300(css像素)img标签对应的物理像素数为200×300,两倍图片的位图像素数为200×300*4,所以看起来一个物理像素对应四个位图像素,因此它的颜色选择只能经过一定的算法(显示结果是一张只有原图像总像素数四分之一的图片,我们称这个过程),虽然图片肉眼看上去不会模糊,会感觉图片缺乏一些清晰度或者有轻微的色差(但还是可以接受的)。

用一张图片来表示:

针对以上两个问题,我做了一个demo(内网访问),点击这里。

演示中将100×100张图片分别放入100×100、50×50、25×25的img容器中,并在屏幕上显示显示效果。

在条形图中,实际上可以通过放大镜看到边界像素值的差异:

图1,选择最接近的颜色,颜色值介于红色和白色之间,颜色越浅,图片就会显得模糊(可以理解为图片拉伸)。

图2,附近没有颜色,颜色值不是红色就是白色,图片看起来很清晰。

图3,取最接近的颜色,色值介于红白之间,偏重。 画面看上去有色差,缺乏清晰度(可以理解为画面挤压)。

有了爱字图片,你可以通过看“爱”字来判断图片是模糊还是清晰。

(ps:如果看起来不明显,可以用手机扫描网页(内网地址)或者点击原图看更清楚。

一些问题

下面讲一下移动H5开发在不同分辨率、屏幕的手机上会遇到的几个经典问题。

接下来,图片高清问题

上面已经介绍过这个问题的解决方案:将镜像加倍(@2x),然后将镜像容器缩小50%。

例如:图片尺寸,400×600;

1.img标签

width: 200px;
height: 300px;

2.背景图片

width: 200px;
height: 300px;
background-image: url(image@2x.jpg);
background-size: 200px 300px; // 或者: background-size: contain;

这样的缺点是显而易见的。 普通屏幕下:

我还下载了@2x的图片,造成资源浪费。

由于这个原因,图片会失去一些清晰度(或色差)。

所以最好的解决方案是:在不同的dprs下加载不同尺寸的图片。

无论是通过css媒体查询还是条件判断,都是可以的。

那么问题来了,这样的话,我们是不是需要准备两组图片呢? (@1x 和 @2x)

我想任何好的公司都会有这样的图片服务器,可以通过URL获取参数,然后控制图片的质量,或者将图片裁剪成不同的尺寸。

所以我们只需要上传大图(@2x),其他小图将由图片服务器处理。 我们只需要负责URL的拼接即可。

比如这张原图:

https://img.alicdn.com/tps/TB1AGMmIp**afXp****XX.jpg // 原图

您可以像这样裁剪图像:

// 200×200
https://img.alicdn.com/tps/TB1AGMmIp**afXp****XX.jpg_200x200.jpg
// 100×100
https://img.alicdn.com/tps/TB1AGMmIp**afXp****XX.jpg_100x100.jpg

(ps:当然,裁剪只是对原图按比例裁剪,你要保证图像清晰~)

下一篇:1px问题

这可能是设计师最敏感、最关心的问题。

首先我要说一下为什么会有:1px这个东西?

我们正常写css,像这样:1px;,在屏幕下面会不会有问题呢?

首先我们看一下下面这张图:

上面两张图分别是(dpr=1)和(dpr=2)下的测试结果。 相比之下,对于1px的显示,它们是一致的,没有差异。

那么显示屏的优点是什么? 为什么设计师认为高清屏幕下的线条(如右图)很粗? 明显是左右都是一样的~

我通过一张图来解释一下(原谅我又盗图了):

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

因此,设计者想要的是:1px;,实际上是1个物理像素宽。 对于CSS来说,可以认为是:0.5px;,这是(dpr=2)下可以显示的最小单位。

不过遗憾的是并不是所有的手机浏览器都能识别:0.5px;,ios7以下,以及其他系统,0.5px会被当成0px,那么这个0.5px怎么实现呢?

最简单的方法是这样的(元素比例):

.scale{
    position: relative;
}
.scale:after{
    content:"";
    position: absolute;
    bottom:0px;
    left:0px;
    right:0px;
    border-bottom:1px solid #ddd;
    -webkit-transform:scaleY(.5);
    -webkit-transform-origin:0 0;
}

我们写-:1px实体#ddd; 照常,然后缩小0.5倍:(.5),达到0.5px的效果。 不过这个hack通用性不够(比如圆角等),而且写起来比较麻烦。

当然,还有很多其他的破解方法,可以在网上搜索到,但每种方法都有自己的优点和缺点。 这里比较推荐的是页面缩放方案,它的通用性比较强,几乎可以满足所有场景。

对于 (dpr=2),添加以下元标记并设置(比例 0.5):

这样页面中的all:1px就会缩小0.5,从而达到:0.5px;的效果。

有人担心缩放后页面的性能会受到影响。 @做了一个性能测试,见这里(内网地址)。

看一下实现后的效果图对比(右图是优化后的):

(ps:图片经过压缩,可能看起来不太明显,可以用手机扫码或者点击这里(内网地址)进行对比)

然而,页面缩放不可避免地会带来一些问题:

字体大小将会缩放

页面布局会缩放(如:div宽度和高度等)

这两个问题稍后讨论……

多屏适配布局问题

对于移动布局,为了适应各种大屏手机,目前最好的解决方案是使用相对单位rem。

基于rem的原理,我们要做的是:根据不同的手机屏幕尺寸和dpr,动态改变根节点html的font-size大小(基值)。

这里我们提取一个公式(rem代表参考值)

rem = document.documentElement.clientWidth * dpr / 10

阐明:

乘以 dpr,因为页面可能会缩放 1/dpr 倍才能达到 1px(如果没有,则 dpr=1)。

除以10是为了四舍五入,方便计算(理论上可以是任意值)

所以像下面这样,html的font-size可能是:

: 320 像素 / 10 = 32 像素

/5: 320 像素 * 2 / 10 = 64 像素

: 375 像素 * 2 / 10 = 75 像素

对于动态改变根节点html的font-size,我们可以通过css来实现,也可以通过.

使用CSS,您可以通过设备宽度和媒体查询来更改html的字体大小:

html{font-size: 32px;}
//iphone 6 
@media (min-device-width : 375px) {
   html{font-size: 64px;}
}
// iphone6 plus 
@media (min-device-width : 414px) {
    html{font-size: 75px;}
}
*/

缺点:通过设备宽度范围等媒体查询动态改变rem参考值不够准确。 例如:宽度为360px和宽度为320px的手机,因为屏幕宽度在同一范围内(

方法,通过上面的公式,计算出参考值rem,然后编写样式,大致如下(代码引用自kimi的m-base模块)

var dpr, rem, scale;
var docEl = document.documentElement;
var fontEl = document.createElement('style');
var metaEl = document.querySelector('meta[name="viewport"]');
dpr = window.devicePixelRatio || 1;
rem = docEl.clientWidth * dpr / 10;
scale = 1 / dpr;
// 设置viewport,进行缩放,达到高清效果
metaEl.setAttribute('content', 'width=' + dpr * docEl.clientWidth + ',initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale + ',user-scalable=no');
// 设置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代码,但我个人认为这是目前最好的解决方案。

因为这个方案同时解决了三个问题:

: 1px 问题

图片高清问题

屏幕适配布局问题

说到布局,自然要回答最初的问题:CSS编码中如何还原视觉稿的真实宽度和高度?

先决条件:

我得到的是750×1334的高清视觉稿

使用上述高清方案(js代码)。

如果psd文件中有一个测量的块:一个宽高为750×300px的div,那么如何将其转换为rem单位呢?

公式如下:

rem = px / 基准值;

对于模型来说,它的基线值为 75(之前提到过);

因此,在确定视觉草案(即确定基线值)后,我们通常使用 less 来编写 mixin,如下所示:

// 例如: .px2rem(height, 80);
.px2rem(@name, @px){
    @{name}: @px / 75 * 1rem;
}

所以,对于一个宽高为750×300px的div,我们使用less,这样写:

.px2rem(width, 750);
.px2rem(height, 300);

转换成html就是这样:

width: 10rem; // -> 750px
height: 4rem; // -> 300px

最后,由于dpr为2,页面缩放了0.5,所以手机屏幕上实际显示的宽高应该是375×150px,刚刚好。

如果页面没有比例 0.5,我们的代码将如下所示:

.px2rem(width, 375);
.px2rem(height, 150);

我们经常得到这样的宽度和高度:

将750×1334的模型转换成375×667的尺寸后,再测量这个块的尺寸(感觉好傻)。

测量出750×1334的块宽高为750×300px后,口头除以2(感觉很麻烦)。

最后给出一张没有布局适配(上图)和有rem布局适配(下图)的对比图:

(以上手机为:、、)

很明显,适应rem的每个块的宽度和高度会随着手机屏幕宽度的变化而变化。 最明显的可以从图片列表中看到。 最后一张图稿要求只出现一点点,rem布局在任何屏幕上看起来都很棒。

字体大小问题

由于上述方案会导致页面缩放,因此页面块的宽度和高度我们可以依靠高清样机来确定。 因为模型已经是×2了,所以我们可以直接测量它。 那么我们应该如何处理字体呢? ?

关于字体缩放的问题,设计者最初的要求是这样的:任何手机屏幕上的字体大小必须是统一的,所以我们会针对不同的分辨率(不同的dpr)做如下处理:

font-size: 16px;
[data-dpr="2"] input {
  font-size: 32px;
}

(注意字体不能使用rem,误差太大,而且任何屏幕上字体大小都不能一样)

为了方便起见,我们还将使用 less 编写一个 mixin:

.px2px(@name, @px){
    @{name}: round(@px / 2) * 1px;
    [data-dpr="2"] & {
        @{name}: @px * 1px;
    }
    // for mx3
    [data-dpr="2.5"] & {
        @{name}: round(@px * 2.5 / 2) * 1px;
    }
    // for 小米note
    [data-dpr="2.75"] & {
        @{name}: round(@px * 2.75 / 2) * 1px;
    }
    [data-dpr="3"] & {
        @{name}: round(@px / 2 * 3) * 1px
    }
    // for 三星note4
    [data-dpr="4"] & {
        @{name}: @px * 2px;
    }
}

(注:html的data-dpr属性在前面的js解决方案中提到过,这里有用)

根据经验和测试,这些奇怪的 DPR 仍然会出现。 这里我们统一兼容~

使用时,它看起来像这样:

.px2px(font-size, 32);

当然,对于其他css属性,如果你也要求它们在不同DPR下保持一致,也可以这样做,比如:

.px2px(padding, 20);
.px2px(right, 8);

终于

以上是对移动H5高清及多屏适配的一些解决方案的总结,以及知识讲解。 如有错误请指出新浪微博- 。

提醒:请联系我时一定说明是从星空网上看到的!