自动适应网站Retina图片

114

使用新的苹果MacBook Pro带视网膜屏幕,如果在您的网站上提供“标准”图像,则会有点模糊。因此,您必须提供retina图像。

是否有一种自动切换到像iOS(使用Objective-C)那样的@2x图像的方法?我发现的是:移动和视网膜显示器上高分辨率图像的CSS,但我希望我能找到一个自动处理所有图像的过程,不使用CSS或JavaScript

这可能吗?

更新
我想强调这篇有趣的文章,它由@Paul D. Waite推荐,并且有一个有趣的讨论与之相关,由Sebastian链接。


不错!我不想使用js,但那个解决方案似乎很好。 - jacoz
3
您可以使用PHP在服务器端完成此操作:http://retina-images.complexcompulsions.com/。 - ReLeaf
2
@michaelward82:对于摄影图像,Daan Jobsis建议您可以通过增加应用于图像的JPG压缩量,向每个人提供视网膜大小的图像,而文件大小不会比非视网膜图像更大。事实上,图像要么被缩小显示,要么在视网膜显示器上显示,这通常意味着压缩伪影不可见。 - Paul D. Waite
1
其实这并不是“错误”,但我在想是否有一些技巧可以使用。在iOS中它是自动的...这就是为什么我在问! :) - jacoz
2
请注意,“有趣的建议文章”的作者在这里犯了一些大错误:http://silev.org/test/Retina-resize.html - 因此,这篇文章必须被谨慎对待。 - Sebastian
显示剩余3条评论
10个回答

171

<img src="LaunchAirportIcon.png" srcset="LaunchAirportIcon@2x.png 2x"> - malhal
10
现在不仅限于webkit,Edge和Firefox也支持它。http://caniuse.com/#search=srcset - 因此当前全球大约有64%的用户可以使用。然后考虑到很少的高DPI用户将使用不受支持的浏览器(IE和旧版Android),最后它是故障安全的-没有支持的用户只会看到普通DPI图像。我认为它已经准备好供使用了。 - andrewb
1
此外,无需双重加载是一个巨大的优点。这意味着您永远不会浪费任何人的带宽。 - andrewb
再次不及格。但尽管如此,我同意@andrewb的观点。 为了加强他的评论,我在src中提供了x2,这样IE / Opera将始终请求更高分辨率的版本。 - Ricky Boyce
1
这应该是被接受的答案。这绝对是这个线程最简单的解决方案。 - Julien Le Coupanec

14
有不同的解决方案,各有利弊。哪种最适合您取决于各种因素,比如您的网站设计方式、典型访问者使用的技术等等。请注意,视网膜显示器不仅限于Macbook Pro Retina和即将推出的iMac,还包括移动设备,这些设备可能有自己的需求。
问题也与响应式设计中的图像密切相关。实际上,最好利用通用响应式设计技术,而不是针对特定设备进行设计。毕竟,在未来,技术将会不断变化。
我注意到了一些解决方案/讨论:
  • 尽可能使用向量图形,包括CSS技术(渐变、圆角等)、SVG和图标字体。
  • 提供高分辨率(“视网膜”)图像,但压缩它们更多(JPEG质量),如Yoav Weiss所建议的,或者让移动网络在真正需要时(即移动时)对它们进行压缩,如Paul Boag所建议的。
  • Adaptive Images是一种(大多数)服务器端解决方案。它基于存储屏幕分辨率的cookie、配置为从PHP脚本中提供图像的Web服务器以及命名脚本来读取cookie并提供适当的图像。
  • Smashing Magazine上描述和讨论的一堆可能性
  • 稍微提供更高分辨率以使视网膜显示更加平滑,如Paul Boag在视频中建议的那样。
  • A List Apart上的@1.5x技术基本上是相同的思路。
  • 在不久的将来,<picture>标签可能成为一个由W3C工作组甚至苹果公司支持的解决方案。
  • Jake Archebald提出的JavaScript技术
  • Smashing Magazine上对不同技术和一般问题的广泛讨论。
正如其他答案所示,还有更多的技术-但可能还没有最佳实践。
我想知道的一件事是,如何在没有相应设备的情况下测试和调试这些技术...

12

由于目前没有人提及显而易见的选择,我想说:在可能的情况下,尽量使用SVG。它们以完美的视网膜分辨率出现,毫不费力。

支持它的浏览器很好,只需要担心IE8这个主要的过时浏览器。压缩后的文件大小通常比位图(png/jpg)格式更小,而且图像更加灵活;您可以在不同的分辨率下重复使用它们并在必要时重新设计样式,这既节省了开发时间又减少了下载带宽。


我喜欢你的提示!svg唯一的问题是在老旧的浏览器上。 - jacoz
16
而且如果你有照片的话 - Baumr
确实,如果您拥有所需使用的图像的矢量版本,它们非常好,但我不认为您可以将普通光栅图像保存为SVG格式。 - Chuck Le Butt
1
在这个方向上没有“好”的转换方式,因此使用“可能的情况”。但除了摄影网站等,通常你会创建自己的艺术资源,所以我建议将它们制作为矢量图,如果需要可以轻松地将其转换为任何分辨率的光栅图像。 - svachalek
SVG在截图(例如记录UI功能时)中无法使用。 - Greg Brown

9
这是我用来实现背景图片的Less mixin。如果您使用dotLess,retina.js无法用于背景图像,因为它需要自己的mixin,而该mixin本身使用脚本评估,而在dotLess中不支持。
关键是要支持IE8。由于IE8无法轻松处理background-size,因此基本情况(非移动媒体查询)必须是简单的、非缩放的图标。然后媒体查询处理retina的情况,并且可以使用background-size类,因为retina永远不会在IE8上使用。
.retina-background-image( @path, @filename,@extension, @size )
{
     .background-size( cover );
     background-image: url( "@{path}@{filename}@{extension}" );
         @media only screen and ( -webkit-min-device-pixel-ratio: 2 ),
                only screen and ( -moz-min-device-pixel-ratio: 2 ),
                only screen and ( -o-min-device-pixel-ratio: 2/1 ),
                only screen and ( min-device-pixel-ratio: 2 )
         {
             background-image:url( "@{path}@{filename}@x2@{extension}" );
             background-size:@size @size;
         }
}

使用示例:

.retina-background-image( "../references/Images/", "start_grey-97_12", ".png", 12px );

这需要你拥有两个文件:

  • start_grey-97_12.png
  • start_grey-97_12@2x.png

2x文件是为视网膜屏幕设计的双倍分辨率文件。


8
只需要为所有人提供视网膜图片,并在图像元素内将图像压缩到其原始大小的一半。就像假设您的图像宽度和高度都为400像素-只需将图像宽度指定为200像素,以使其看起来清晰,如下所示:
<img src="img.jpg" width="200px" height="200px" />

如果您的图片是摄影照片,那么您可以增加JPG压缩比率而不会使图片质量变差,因为当该图片以2x显示时,JPG压缩的痕迹可能不会被看到。详情请参见:http://blog.netvlies.nl/design-interactie/retina-revolution/

1
Daan Jobsis建议对于摄影图像而言,这甚至不需要导致更大的文件大小:请参见http://blog.netvlies.nl/design-interactie/retina-revolution/。 - Paul D. Waite
9
如果没有必要,我认为提供更大、更重的图像文件不是一个好主意... - jacoz
1
@PaulD.Waite 首先很有趣,最后也非常准确! :) - jacoz
2
@PaulD.Waite 注意,链接文章的作者犯了一些大错误,在这里进行了讨论:http://silev.org/test/Retina-resize.html - 因此,这篇文章必须带着很大的保留态度。特别是“右侧未缩放图像”实际上是经过缩放的,因此不能与分辨率加倍的图像进行直接比较(告诉您的浏览器在新窗口中显示右侧图像,您将看到我和那篇其他文章的作者的意思)。 - Sebastian
很好,没人在意HTML的width/height属性中没有长度单位。http://www.w3.org/TR/html-markup/img.html#img.attrs.width - Volker E.
显示剩余7条评论

1
如果它的背景图片很简单,一种简单的方法是:
    #image { background: url(image.png); }

@media only screen and (-webkit-min-device-pixel-ratio: 2),
       only screen and (-moz-min-device-pixel-ratio: 2),
       only screen and (-o-min-device-pixel-ratio: 2/1),
       only screen and (min-device-pixel-ratio: 2) {
           #image { background: url(image@2x.png); background-size: 50%; }
}

另一种简单的方法是使用以下方法:

只需替换:

<img src="image.jpg" alt="" width="200" height="100" />

使用

<img src="image@2x.jpg" alt="" width="200" height="100" />

1
我发现了一种有趣的提供多分辨率图片的方法。
它实际上使用了CSS,这是我想避免的,并且只在Safari和Chrome中有效。
我说的是image-set
这里有一个由苹果提供的示例此处):
header {
    background: -webkit-image-set( url(images/header.jpg)    1x,
                                   url(images/header_2x.jpg) 2x);
    height: 150px; /* height in CSS pixels */
    width: 800px; /* width in CSS pixels */
}

我还想分享这两个链接:


1

使用JSF,您可以创建一个自定义Facelets标签,以免每个图像都需要添加srcset的繁琐操作。

在您的taglib.xml中,您可以编写以下内容:

<tag>
  <tag-name>img</tag-name>
  <source>tags/img.xhtml</source>
  <attribute>
    <name>src2x</name>
    <required>true</required>
    <type>java.lang.String</type>
  </attribute>
</tag>

而你的标签可能看起来像这样:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets">

  <img src="#{fn:replace(src2x, '@2x', '')}"
       srcset="#{src2x} 2x"/>

</ui:composition>

可以这样使用:
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:myTag="http://your.com/namespace-of-taglib">
  <myTag:src2x="image@2x.jpg"/>
</html>

并将呈现:

<img src="image.jpg"
     srcset="image@2x.jpg 2x"/>

0
如果您不因使用 JavaScript 而感到沮丧,那么这篇好文章http://www.highrobotics.com/articles/web/ready-for-retina.aspx会对您有所帮助。它提供了非常简单的解决方案。
JSFiddle 的示例则胜过千言万语。
使用:
<img onload="getImgSrc(this,'image_x1.png')" width="100" height="100" />

JS:

/* RETINA READY IMG SRC */
function getImgSrc(img, src) {
    var srcResult = src;
    // if high-res screen then change _x1 on _x2
    if (window.devicePixelRatio > 1 && 
        src.indexOf("_x1.")>=0) {
          srcResult = src.replace("_x1.", "_x2.");
    }
    img.onload = null; //protect from second rasing
    img.src = srcResult;    
}

$(document).ready(function(){
  // fire onload trigger on IMG tags that have empty SRC attribute
  var images = $('img:not([src=""])');
    images.each(function(i) {
        $(this).trigger('onload');            
    });
});

0
这个问题在响应式网站上尤为棘手,因为图像的宽度可能会根据浏览器大小而变化。而且,在处理多个编辑人员潜在地上传数千张图片的内容管理系统时,要求他们上传经过特殊压缩的图片对我来说似乎不切实际。
因此,我编写了一个脚本来解决这个问题,它会在页面底部和调整大小完成时触发。每次都会考虑像素密度和图像所占空间的大小。

http://caracaldigital.com/retina-handling-code/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接