博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
谈一谈移动端1px的问题
阅读量:6359 次
发布时间:2019-06-23

本文共 3217 字,大约阅读时间需要 10 分钟。

起因

最近一个月都在准备校招,所以没什么时间写博客。今天想写的问题来自于网易一面的时候,面试官问我如何在移动端的页面上画一条1px的线。这个问题我模糊地记得之前看过相关文章,但是我清楚地记得当时自己脑子一片空白。是的,一面挂了,但是这个问题一直在我回来的路上不断想起,所以今天我就要解决这个问题,来看看有什么解决方案吧~

动态改变viewport的缩放

这是淘宝的flexible提出的解决方案,其核心就是根据window.devicePixelRatio(dpr)的值动态改变viewport的缩放,核心代码如下(有删减):

if (!dpr && !scale) {    var isAndroid = win.navigator.appVersion.match(/android/gi);    var isIPhone = win.navigator.appVersion.match(/iphone/gi);    var devicePixelRatio = win.devicePixelRatio;    if (isIPhone) {        // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案        if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {                            dpr = 3;        } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){            dpr = 2;        } else {            dpr = 1;        }    } else {        // 其他设备下,仍旧使用1倍的方案        dpr = 1;    }    scale = 1 / dpr;}if (!metaEl) {    metaEl = doc.createElement('meta');    metaEl.setAttribute('name', 'viewport');    metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');    if (docEl.firstElementChild) {        docEl.firstElementChild.appendChild(metaEl);    } else {        var wrap = doc.createElement('div');        wrap.appendChild(metaEl);        doc.write(wrap.innerHTML);    }}

这个方案只对iOS的Retina屏幕做了处理,而没有管安卓的Retina屏幕,原因可以看《》这篇文章。使用了flexible之后直接写1px就能实现效果,但是最新的2.0好像放弃了这种缩放的方案,对于1px的处理则变成了border-image或者background-image,详细的可以看《》。

这里再简单谈一下这种viewport缩放的原理:

首先一开始写移动端的时候,我是直接加一个meta标签 <meta name=viewport content="width=device-width,minimum-scale=1,maximum-scale=1,user-scalable=no">,这个meta标签使得页面宽度等于设备宽度,页面的缩放默认为1,且用户不能缩放,后来看到一篇文章讲viewport计算是这样的:

viewport的默认宽度是980px;设置了initial-scale则宽度是device-width/initial-scale;设置了width则宽度等于width的值;同时设置了initial-scale和width则宽度取两者中较大的一个。

上面的结论我在PC端谷歌浏览器的设备模拟器里证实了有效,但是安卓和iOS真机并没有试过。

transform: scale(0.5)

这个方案也是WeUI正在用的,核心思想是使用transform的scale来整体缩放,如果你想画一条1px的线,就可以直接用

div {    height: 1px;      background: #000;      transform: scaleY(0.5);      transform-origin: 0 0;}

理论上在dpr为2时就是scaleY(0.5),在dpr为3时就是scaleY(0.333),但是我注意到WeUI并没有针对其他dpr的做特殊处理,可能是因为在iPhone6(dpr=2)和iPhone6 Plus(dpr=3)中看起来差别不大吧。

如果你想给一个元素加一个1px的边框可以利用到伪元素,在这个方案下边框加圆角也很容易实现,具体代码如下:

div:after {  content: " ";  width: 78px;  height: 38px;  border-radius: 4px;  border: 1px solid #000;  transform: scale(0.5, 0.5);  transform-origin: 0 0;  position: absolute;}

其他方案

border-image

这种是AlloyTeam的《》这篇文章上看到的,代码写起来挺简单,但是要自己制作图片,而且圆角也不好弄,如果改了颜色就要对图片处理,所以不是很好的方案。

box-shadow

这个颜色不好弄,所以效果也不是很好。

div {  border: none;  box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.5);}

0.5px解决方案

div {    border: 1px solid #000;}@media (-webkit-min-device-pixel-ratio: 2) {  div {    border: .5px solid #000;  }}

安卓和iOS7之前版本碰到0.5px直接就解析成0px了,但是这一特性也是可以利用的,在最新的flexible中就有对0.5px进行判断的代码:

// detect 0.5px supportsif (dpr >= 2) {  var fakeBody = document.createElement('body')  var testElement = document.createElement('div')  testElement.style.border = '.5px solid transparent'  fakeBody.appendChild(testElement)  docEl.appendChild(fakeBody)  if (testElement.offsetHeight === 1) {    docEl.classList.add('hairlines')  }  docEl.removeChild(fakeBody)}

小结

这篇文章从国庆开始断断续续地写,到最后一天总算是写完了,这段时间整个人心态经历了一些变化,主要表现在对待技术比以前更加踏实了,无论如何希望自己能坚持写博客,坚持学习前端,相信总能找到一个理想的工作的,加油!

转载地址:http://dtbma.baihongyu.com/

你可能感兴趣的文章
Windows Server 2012 R2 Active Directory(活动目录)实验一
查看>>
android viewpager 无限左右滑动
查看>>
linux下SSH远程连接服务慢解决方案
查看>>
利用mic visual studio 2010 编译器执行wincap获取网络适配器的代码
查看>>
HTML
查看>>
CENTOS7下编译安装PHP-5.4以及配置phpMyAdmin
查看>>
磁盘显示无法访问拒绝访问,里面的资料怎样找到
查看>>
Java之品优购课程讲义_day07(5)
查看>>
Java的新项目学成在线笔记-day3(八)
查看>>
路由简单的实验
查看>>
好程序员web前端教程分享js reduce方法使用教程
查看>>
零基础学习大数据Hadoop需要什么准备?Hadoop如何发展起来的?
查看>>
前端程序员需要具备的几个软实力,你具备了吗
查看>>
RHEL系列网络配置2015083101
查看>>
c# 基本值类型及其默认值
查看>>
服务器端解决JS跨域调用问题
查看>>
MySql中添加用户,新建数据库,用户授权,删除用户,修改密码
查看>>
雨巷-戴望舒
查看>>
OpenCms创建网站过程图解——献给OpenCms的初学者们
查看>>
C++ 异常处理机制的实现
查看>>