简单办法支持 Retina 网页图像

2013-10-12 12:03:09 +08:00
 Kaiyuan
我很久之前就想,为什么 Apple 不直接在 img 标签加一个属性设置图像的 Retina 版的 URL 呢?然后今天再想的时候忽然醒起,可以用 data 属性然后用 js 判断 Retina 然后替换 img 的 src。
应该很多人早就用这办法了吧?

代码:
https://gist.github.com/6945613

演示: http://codepen.io/Kaiyuan/pen/swoCL
4113 次点击
所在节点    分享创造
17 条回复
dorentus
2013-10-12 12:13:46 +08:00
不加新属性应该是为了遵循标准。开发者自己实现起来(比如你这个实现)也不麻烦。

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

虽然这样子不是Html标准,不过浏览器各自的hack多了去了,也不差这么一个啊。。。
Kaiyuan
2013-10-12 14:27:38 +08:00
@zythum 如果是使用 Ajax 载入,那么在 Ajax 里面载入内容后再触发一次就可以了啊。
gonghao
2013-10-12 15:46:51 +08:00
@Kaiyuan 是的,这样可行,只是这个跟 lazyload 机制差不多,有些 img 的请求可能已经发出,还是可能会造成浪费,理论上是可以做到绝对不浪费的,只是感觉成本也不低,而且把 js 塞到 head 会有其他一些问题出现。server 端独立判断是目前做不到的,目前看来比较有效的方法是在页面访问的时候 js 植入一个 cookie 后续 server 根据 cookie 来分发 2x 的图片
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/img@2x.png); background-repeat:no-repeat; background-size:50% 50%;}
}

我一般这样做
luo123qiu
2013-10-12 15:54:23 +08:00
主要用来支持rMBP、iphone4+、ipad3+
otakustay
2013-10-12 17:41:59 +08:00
标准上有picture元素和srcset属性来做这事,至于苹果有没有实现……
zythum
2013-10-12 18:05:49 +08:00
@Kaiyuan 那不是很麻烦么…
Kaiyuan
2013-10-12 23:37:55 +08:00
@luo123qiu 这个只能用于元素的背景图,不能替换 img.

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

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

@otakustay 喔,原来有这样的属性,貌似还没完善,应该以后所有浏览器都支持这个吧?毕竟是个标准。
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
2013-10-25 18:56:36 +08:00
@donnior 标准定义了一个新的属性,叫srcset,但是直到最近webkit才支持了它。而且src和srcset并存,JavaScript API实现起来就有些问题需要考量了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/85316

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX