爱意满满的作品展示区。
Kaiyuan

简单办法支持 Retina 网页图像

  •  
  •   Kaiyuan ·
    Kaiyuan · Oct 12, 2013 · 4841 views
    This topic created in 4671 days ago, the information mentioned may be changed or developed.
    我很久之前就想,为什么 Apple 不直接在 img 标签加一个属性设置图像的 Retina 版的 URL 呢?然后今天再想的时候忽然醒起,可以用 data 属性然后用 js 判断 Retina 然后替换 img 的 src。
    应该很多人早就用这办法了吧?

    代码:


    演示: http://codepen.io/Kaiyuan/pen/swoCL
    17 replies    1970-01-01 08:00:00 +08:00
    dorentus
        1
    dorentus  
       Oct 12, 2013   ❤️ 1
    不加新属性应该是为了遵循标准。开发者自己实现起来(比如你这个实现)也不麻烦。

    不过 if (window.devicePixelRatio) 这个判断方式不对吧,我的非 retina 的 MBP 的 Safari 7.0 (9537.71) 上面,window.devicePixelRatio 是存在的,值为 1。
    Kaiyuan
        2
    Kaiyuan  
    OP
       Oct 12, 2013
    @dorentus 再搜索一下,原来要 window.devicePixelRatio && window.devicePixelRatio > 1 才可以。
    http://segmentfault.com/q/1010000000190706
    gonghao
        3
    gonghao  
       Oct 12, 2013
    这样对于 Retina 还是要多一次下载,最佳的办法是能在 server 端判断,然后针对 Retina 直接提供 2x 资源
    ericls
        4
    ericls  
       Oct 12, 2013 via Android
    如果有针对retina的类似viewport的东西就好了
    Kaiyuan
        5
    Kaiyuan  
    OP
       Oct 12, 2013
    @gonghao 貌似没有办法在 server 判断吧?只要 JS 加上 $(document).ready(); 放在 head 就不用载入原图像,DOM 载入完成就直接把 src 替换成 @2x 了。
    luikore
        6
    luikore  
       Oct 12, 2013
    这个方案对 retina 设备要发两次下载请求
    用 progressive jpg / interlaced png 就可以了, 只需要一张图片, 不用加任何属性和 js
    zythum
        7
    zythum  
       Oct 12, 2013
    这个问题就载入你能处理首屏的img 但是之后的呢? 动态插入的呢。 每次都来一次替换么?
    donnior
        8
    donnior  
       Oct 12, 2013
    其实要是浏览器支持一下问题就很好解决了,不过为什么浏览器现在都不加这样一个特性呢?如果浏览器支持了,假设语法仍然跟楼主的写法一样,那么浏览器也可以只去加载一次图像,脚本啥的都不用了。

    虽然这样子不是Html标准,不过浏览器各自的hack多了去了,也不差这么一个啊。。。
    Kaiyuan
        9
    Kaiyuan  
    OP
       Oct 12, 2013
    @zythum 如果是使用 Ajax 载入,那么在 Ajax 里面载入内容后再触发一次就可以了啊。
    gonghao
        10
    gonghao  
       Oct 12, 2013
    @Kaiyuan 是的,这样可行,只是这个跟 lazyload 机制差不多,有些 img 的请求可能已经发出,还是可能会造成浪费,理论上是可以做到绝对不浪费的,只是感觉成本也不低,而且把 js 塞到 head 会有其他一些问题出现。server 端独立判断是目前做不到的,目前看来比较有效的方法是在页面访问的时候 js 植入一个 cookie 后续 server 根据 cookie 来分发 2x 的图片
    luo123qiu
        11
    luo123qiu  
       Oct 12, 2013
    .class1, .class2, .class3 {background-image:url(img/img.png); background-repeat:no-repeat;}
    @media only screen and (-webkit-min-device-pixel-ratio: 2),
    only screen and (min-device-pixel-ratio: 2) {
    .class1, .class2, .class3 {background-image:url(img/[email protected]); background-repeat:no-repeat; background-size:50% 50%;}
    }

    我一般这样做
    luo123qiu
        12
    luo123qiu  
       Oct 12, 2013
    主要用来支持rMBP、iphone4+、ipad3+
    otakustay
        13
    otakustay  
       Oct 12, 2013
    标准上有picture元素和srcset属性来做这事,至于苹果有没有实现……
    zythum
        14
    zythum  
       Oct 12, 2013
    @Kaiyuan 那不是很麻烦么…
    Kaiyuan
        15
    Kaiyuan  
    OP
       Oct 12, 2013
    @luo123qiu 这个只能用于元素的背景图,不能替换 img.

    @zythum 写成函数然后在 Ajax success 里面加上一句代码而已。不过这种办法倒是会像 @gonghao 说的那样每一张需要替换的图都可能增加一次请求。

    @luikore 你是指保存图像时候保存 progressive jpg / interlaced png?还是指网页上设置?

    @otakustay 喔,原来有这样的属性,貌似还没完善,应该以后所有浏览器都支持这个吧?毕竟是个标准。
    luikore
        16
    luikore  
       Oct 18, 2013
    @Kaiyuan 是的. 其实 1x 的客户端直接放 2x 图片只有两个问题:

    一是下载量比原来大. 其实不管也行. 但如果想要更快, 把图片保存成 progressive/interlaced 可以在下载完成前就开始显示低清版本.

    二是缩小到 50% 大小后样子不好看. 绝大部分情况用 image-rendering:optimizeQuality; -ms-interpolation-mode:bicubic 改成二次立方就可以了. 某些特例参考

    https://developer.mozilla.org/en-US/docs/Web/CSS/image-rendering?redirectlocale=en-US&redirectslug=CSS%2Fimage-rendering
    fantasticfears
        17
    fantasticfears  
       Oct 25, 2013 via Android
    @donnior 标准定义了一个新的属性,叫srcset,但是直到最近webkit才支持了它。而且src和srcset并存,JavaScript API实现起来就有些问题需要考量了。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3314 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 41ms · UTC 11:34 · PVG 19:34 · LAX 04:34 · JFK 07:34
    ♥ Do have faith in what you're doing.