Home >Web Front-end >H5 Tutorial >淘宝的flexible适配方案为什么只对iOS进行dpr判断,对于Android始终认为其dpr为1?

淘宝的flexible适配方案为什么只对iOS进行dpr判断,对于Android始终认为其dpr为1?

WBOY
WBOYOriginal
2016-06-07 08:42:582400browse

<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">dpr</span> <span class="o">&&</span> <span class="o">!</span><span class="nx">scale</span><span class="p">)</span> <span class="p">{</span>
        <span class="kd">var</span> <span class="nx">isAndroid</span> <span class="o">=</span> <span class="nx">win</span><span class="p">.</span><span class="nx">navigator</span><span class="p">.</span><span class="nx">appVersion</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/android/gi</span><span class="p">);</span>
        <span class="kd">var</span> <span class="nx">isIPhone</span> <span class="o">=</span> <span class="nx">win</span><span class="p">.</span><span class="nx">navigator</span><span class="p">.</span><span class="nx">appVersion</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/iphone/gi</span><span class="p">);</span>
        <span class="kd">var</span> <span class="nx">devicePixelRatio</span> <span class="o">=</span> <span class="nx">win</span><span class="p">.</span><span class="nx">devicePixelRatio</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(</span><span class="nx">isIPhone</span><span class="p">)</span> <span class="p">{</span>
            <span class="c1">// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案</span>
            <span class="k">if</span> <span class="p">(</span><span class="nx">devicePixelRatio</span> <span class="o">>=</span> <span class="mi">3</span> <span class="o">&&</span> <span class="p">(</span><span class="o">!</span><span class="nx">dpr</span> <span class="o">||</span> <span class="nx">dpr</span> <span class="o">>=</span> <span class="mi">3</span><span class="p">))</span> <span class="p">{</span>                
                <span class="nx">dpr</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">devicePixelRatio</span> <span class="o">>=</span> <span class="mi">2</span> <span class="o">&&</span> <span class="p">(</span><span class="o">!</span><span class="nx">dpr</span> <span class="o">||</span> <span class="nx">dpr</span> <span class="o">>=</span> <span class="mi">2</span><span class="p">)){</span>
                <span class="nx">dpr</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="nx">dpr</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="c1">// 其他设备下,仍旧使用1倍的方案</span>
            <span class="nx">dpr</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nx">scale</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">/</span> <span class="nx">dpr</span><span class="p">;</span>
    <span class="p">}</span>

回复内容:

能提出这个问题,想必你也是看过Android & iOS设计尺寸规范 相关的东西,如果没有这张图很很不错:


淘宝的flexible适配方案为什么只对iOS进行dpr判断,对于Android始终认为其dpr为1?

第三代iPad发布会上,苹果给出了Retina设计标准的公式: 淘宝的flexible适配方案为什么只对iOS进行dpr判断,对于Android始终认为其dpr为1?其中 a代表人眼视角,h 代表像素间距,d代表肉眼与屏幕的距离。符合以上条件的屏幕可以使肉眼看不见单个物理像素点。这样的IPS屏幕就可被苹果称作“Retina显示屏”。将通常使用距离代入上公式可知:行动电话显示器的像素密度达到或高于300ppi就不会再出现颗粒感;手持平板类电器显示器的像素密度达到或高于260ppi就不会再出现颗粒感,而苹果电脑的Retina显示器像素密度只要超过200ppi就无法区分出单独的像素。

说多了......
(以下忽略低端机)
iPhone4, 4s, 5, 5s, 6, 6+, 6s, 6s+ 都是用的是Retina屏,其中4, 4s, 5, 5s, 6, 6s的ppi都是326,dpr都是2,6+和6s+ppi是441,dpr是3。在ipad上同样只有dpr2和3两种的屏幕。
再来看看安卓的吧,算了,我不想看dpr=1,1.5,1.75,2,2.5,3,4......
淘宝在设置initial-scale(屏幕缩放比)的同时使用的是rem的方式设置各种尺寸大小
<code class="language-html"><span class="nt"><meta> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"width=divece-width,initial-scale=1,user-scalable=no"</span><span class="nt">/></span>
</span></code>
因为Android设备的兼容问题太过复杂,Android Pad 和 中兴 等国产 Android 机有很多奇葩的BUG,比如:
  • viewport content 的写法要兼容各种奇葩 Android 设备,兼容测试的成本很高
  • 部分机型修改viewport之后产生屏幕抖动
  • 部分机型 WebView Width 与屏幕实际宽度不一致
  • 还有很多无法预料到的奇葩BUG存在
故统一对 Android 设备进行 dpr = 1 处理。

同时 flexible 是 2014年5月诞生的,国内的大前端对于移动端的经验还不算成熟,而手机淘宝能有这种思路,已经是非常厉害的一个方案!

顺便说点不相关的:
  1. 上述的几个小点的问题,后来阿里也有别的同学解决了,但方案并未开源
  2. 我们团队的方案是不对 viewport 进行缩放处理,仅根据 width 在 html 添加 font-size
  3. 对于1px 边框的处理是进行特性检查,对于支持的容器直接就写 border-width:0.5px
<code class="language-js"><span class="k">if</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">devicePixelRatio</span> <span class="o">&&</span> <span class="nx">devicePixelRatio</span> <span class="o">>=</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">docElem</span>  <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">;</span>
    <span class="kd">var</span> <span class="nx">testElem</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">'div'</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">fakeBody</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">'body'</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">refNode</span>  <span class="o">=</span> <span class="nx">docElem</span><span class="p">.</span><span class="nx">firstElementChild</span> <span class="o">||</span> <span class="nx">docElem</span><span class="p">.</span><span class="nx">firstChild</span><span class="p">;</span>
    <span class="nx">testElem</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">border</span> <span class="o">=</span> <span class="s1">'.5px solid transparent'</span><span class="p">;</span>
    <span class="nx">fakeBody</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">testElem</span><span class="p">);</span>
    <span class="nx">docElem</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">fakeBody</span><span class="p">,</span> <span class="nx">refNode</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">testElem</span><span class="p">.</span><span class="nx">offsetHeight</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">'html'</span><span class="p">).</span><span class="nx">classList</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="s1">'hairlines'</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="nx">docElem</span><span class="p">.</span><span class="nx">removeChild</span><span class="p">(</span><span class="nx">fakeBody</span><span class="p">);</span>
<span class="p">}</span>
</code>
issue中有人提过这个问题 一些安卓厂商给定的dpr值并不准确
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn