2021-03-07

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-1 07:45   367   0

目录

概念理解

CSS像素(逻辑像素/设备独立像素/设备无关像素)

物理像素

CSS像素和物理像素的联系

3个viewport

移动端适配方案

Flexible方案

使用vw、vh

实际应用

1px解决方案

目前项目中的解决方案

伪类加transform

动态修改initial-scale

横屏适配

图片模糊问题

输入结束输入框上移

参考链接:


概念理解

CSS像素(逻辑像素/设备独立像素/设备无关像素)

CSS像素是一个抽像的单位,主要使用在浏览器上,用来精确度量Web页面上的内容。

当页面缩放比例为100%时,一个CSS像素等于一个设备独立像素

物理像素

是显示设备中一个最微小的物理部件。每个像素可以根据操作系统设置自己的颜色和亮度。正是这些设备像素的微小距离欺骗了我们肉眼看到的图像效果。

CSS像素和物理像素的联系

早期手机分辨率较低的时候,一个CSS像素等于一个物理像素,没有设备独立像素。苹果公司便推出了所谓的Retina屏,比如iphone4的逻辑分辨率320x480,物理分辨率640x960,但屏幕尺寸却没变化,这就意味着同样大小的屏幕上,物理像素却多了一倍,这时,1 个独立像素 == 2 个物理像素,屏幕不缩放的情况下,一个css像素是等于两个物理像素的。设备像素比(dpr)被用来描述物理像素和设备独立像素之间的关系:

设备像素比=物理像素/设备独立像素

dpr的值越大,css中1px代表的物理像素就会越多,屏幕也就看起来越清楚。

通过window.devicePixelRatio可以获取到dpr,但devicePixelRatio在手机的火狐浏览器和IE浏览器还存在着问题。

更多详情参考MDN上的接口文档:Window.devicePixelRatio - Web API 接口参考 | MDN

3个viewport

layout viewport:浏览器默认的viewport,通常较宽,远大于屏幕本身的宽度。可以通过document.documentElement.clientWidth来获取。

visual viewport:浏览器可视区域的大小,可以通过window.innerWidth来获取,但在Android 2, Oprea mini 和 UC 8中无法正确获取。

ideal viewport:理想状态的viewport,首先不需要用户缩放和横向滚动条就能正常的查看网站的所有内容;第二,显示的文字的大小是合适。iOS的都是,Android各有不同,在css中把元素宽度设成ideal viewport的大小,那这个元素刚好占满屏幕宽度而且没滚动条。

移动端开发中想要获取的就是这个ideal viewport的值。

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

第一种理论:
width=device-width和initial-scale=1都可以将默认的layout viewport设置成ideal viewport。前者在iphone和ipad上,无论是竖屏还是横屏,宽度都是竖屏时ideal viewport的宽度,后者在windows phone 上的IE 无论是竖屏还是横屏都把宽度设为竖屏时ideal viewport的宽度。所以一般两个都写上。

第二种理论:

width=device-width:将layout viewport设置成ideal viewport。

initial-scale=1:initial-scale = 理想视口宽度 / 视觉视口宽度,此时visual viewport=ideal viewport,1个CSS像素=1个设备独立像素(注意:并不是物理像素)。这样在各种设备上呈现出来的页面布局能大体相似。

所以结合两者,能让layout viewport=ideal viewport=visual viewport

移动端适配方案

Flexible方案

这也是canary项目中使用的方案,缩放页面,并且dpr的值来修改htmlfont-size,从而使用rem实现等比缩放。

虽然在server/views/njk/layout.njk文件中写了"initial-scale=1/dpr"缩放了页面,但是在server/views/njk/dpmmweb/layout.njk中又写了initial-scale=1 不缩放页面,所以dpmmweb下的njk页面默认缩放比例仍然是1.0。

参考链接:

使用vw、vh

Flexible方案是通过JavaScript来模拟vw的特性,那么到今天为止,vw已经得到了众多浏览器的支持,也就是说,可以直接考虑将vw单位运用于我们的适配布局中。

vw是基于Viewport视窗的长度单位,这里的视窗(Viewport)指的就是浏览器可视化的区域。而这个可视区域是window.innerWidth/window.innerHeight的大小.

比如iPhone6的innerWidth是375,那么1vw=3.75px

要实现设计图给的px单位到vw单位的转换,可以使用PostCSS的插件. 官方文档:postcss-px-to-viewport

参考链接:再聊移动端页面的适配

实际应用

在项目中实际应用vw方案时,使用vh做为容器的高度单位,会让使用transform方案的1px边框展示出现部分变粗的问题,但是如果使用vw来作为高度的单位,展示正常,不会出现上述问题。

现在另外为了和其他端保持一致,决定还是使用rem方案,但可以考虑统一使用vw作为单位。

文字较多的部分,字体大小仍然使用px作为单位,px可以让大屏幕手机展示出更多的内容,更符合人们的阅读习惯。

参考链接:rem, vw, 还是...? 各凭本事的移动端适配方案

1px解决方案

目前项目中的解决方案

在outline.scss中设置了一些通用的边框类,这些边框已经实现了1px,在njk页面引入这些类就可以达到1px边框的效果。

outline.scss中实现1px的方法是:

1.准备一张符合条件的边框背景图,模拟在背景上。

2.基于media查询判断等于2或3的设备像素比,background-size设置为高为1px

伪类加transform

原理:把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,根据媒体查询结合tranform缩放为相应尺寸

实现关键代码:

.border-bottom{
  position: relative;
}
/* 2倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
  .border-bottom::after {
   position: absolute;
  left: 0;
    bottom: 0;
    height: 1px;
    width: 100%;
    background: #333333;
    content: '';
    -webkit-transform: scaleY(0.5);
    transform: scaleY(0.5);
    -webkit-transform-origin: 0 0;
    transform-origin: 0 0;
  }
}
/* 3倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
  .border-bottom::after {
 ...//其他和2倍屏类似
 -webkit-transform: scaleY(0.33);
    transform: scaleY(0.33);
  }
}

效果对比图:

动态修改initial-scale

原理:在运行的时候拿到设备的devicePixelRatio,动态改变viewport的initial-scale为 1/devicePixelRatio,这样就能保证1px的宽度就是真正的1物理像素宽。

实现关键代码:

function changeView(){
  const clientWidth = window.screen.width;
  const dpr = window.devicePixelRatio;
  const vp = document.createElement('meta');
  document.documentElement.style.fontSize = clientWidth > 414 ? '20px' : 20 * dpr * clientWidth / 360 + 'px';
  vp.name = 'viewport';
  vp.content = `initial-scale=${1.0 * 1 / dpr}, user-scalable=no, width=device-width`;
  var m = document.getElementsByTagName('meta')[0];
  m.parentNode.insertBefore(vp, m);
}
changeView();

效果对比图:适配iphoneX

目前layout.njk页面已经使用viewport-fit,也有许多页面使用了env和constant两个函数设定安全区域与边界的距离。

<meta name="viewport" content="viewport-fit=cover">

横屏适配

目前只有极少量页面做了。可以使用媒体特性@media,orientation: portrait是竖屏,orientation: landscape是横屏;也可以通过在js文件中监听resize事件,再根据的window.orientation属性判断旋转的角度得出是横屏还是竖屏。

图片模糊问题

1.尽量使用svg,这样无论放大多少倍都不会失真

2.上传多张图片进行适配。推荐使用img的srcset属性让浏览器自动根据像素密度匹配图片,比较简单明了。

<img src="source.jpg" srcset="source_2x.jpg 2x, source_3x.jpg 3x">


现在一般直接用的都是2倍图。

输入结束输入框上移

1.隐藏某个元素使用的是display:none,或者jQuery的hide方法,导致页面空间发生变化,下一行的输入框上移

2.输入框在调出软键盘之后输入框上移。

参考链接:

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP