V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
Kaiyuan
V2EX  ›  分享创造

简单办法支持 Retina 网页图像

  •  
  •   Kaiyuan ·
    Kaiyuan · 2013-10-12 12:03:09 +08:00 · 4212 次点击
    这是一个创建于 4061 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我很久之前就想,为什么 Apple 不直接在 img 标签加一个属性设置图像的 Retina 版的 URL 呢?然后今天再想的时候忽然醒起,可以用 data 属性然后用 js 判断 Retina 然后替换 img 的 src。
    应该很多人早就用这办法了吧?

    代码:


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

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

    虽然这样子不是Html标准,不过浏览器各自的hack多了去了,也不差这么一个啊。。。
    Kaiyuan
        9
    Kaiyuan  
    OP
       2013-10-12 14:27:38 +08:00
    @zythum 如果是使用 Ajax 载入,那么在 Ajax 里面载入内容后再触发一次就可以了啊。
    gonghao
        10
    gonghao  
       2013-10-12 15:46:51 +08:00
    @Kaiyuan 是的,这样可行,只是这个跟 lazyload 机制差不多,有些 img 的请求可能已经发出,还是可能会造成浪费,理论上是可以做到绝对不浪费的,只是感觉成本也不低,而且把 js 塞到 head 会有其他一些问题出现。server 端独立判断是目前做不到的,目前看来比较有效的方法是在页面访问的时候 js 植入一个 cookie 后续 server 根据 cookie 来分发 2x 的图片
    luo123qiu
        11
    luo123qiu  
       2013-10-12 15:53:20 +08:00
    .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  
       2013-10-12 15:54:23 +08:00
    主要用来支持rMBP、iphone4+、ipad3+
    otakustay
        13
    otakustay  
       2013-10-12 17:41:59 +08:00
    标准上有picture元素和srcset属性来做这事,至于苹果有没有实现……
    zythum
        14
    zythum  
       2013-10-12 18:05:49 +08:00
    @Kaiyuan 那不是很麻烦么…
    Kaiyuan
        15
    Kaiyuan  
    OP
       2013-10-12 23:37:55 +08:00
    @luo123qiu 这个只能用于元素的背景图,不能替换 img.

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

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

    @otakustay 喔,原来有这样的属性,貌似还没完善,应该以后所有浏览器都支持这个吧?毕竟是个标准。
    luikore
        16
    luikore  
       2013-10-18 14:51:14 +08:00
    @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  
       2013-10-25 18:56:36 +08:00 via Android
    @donnior 标准定义了一个新的属性,叫srcset,但是直到最近webkit才支持了它。而且src和srcset并存,JavaScript API实现起来就有些问题需要考量了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   928 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:41 · PVG 03:41 · LAX 11:41 · JFK 14:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.