4

一些SVG向下兼容优雅降级技术

 3 years ago
source link: https://www.zhangxinxu.com/wordpress/2013/09/svg-fallbacks/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=3678

一、SVG前言

再一次拿可缩放矢量图形SVG(Scalable Vector Graphics)说事,对SVG有所关注的同行应该都知道,IE8-以及Android 2.3默认浏览器是不支持SVG的,实际项目,这些浏览器,至少IE8浏览器还没有到不管不问的时候,因此,在使用视网膜显示友好的SVG同时,我们还要做一点优雅降级,使IE8等考古价值浏览器也能手染余香。

本文内容参考自CSS-tricks SVG fallbacks一文,该文章在介绍一种新的SVG降级技术的同时,把以前Using SVG中提到的技术又总结了一遍。大集合什么的我做喜欢了,以后不要找来找去,因此,这里,我按照个人的理解,配合自己的一些实际测试,分享下。

本文内容当下可能不温不火,但明年的今天,估计就不一样了,记住这里,随时到访。

二、svg image标签降级技术

这是一个名叫Alexey Ten首先提出来的,类似下面的代码:

<svg width="96" height="96">
  <image xlink:href="svg.svg" src="svg.png" width="96" height="96" />
</svg>

若对上面代码效果感兴趣,您可以狠狠地点击这里:svg image标签降级技术demo

现代浏览器下,例如Chrome下,就是SVG形式显示,如下截图:

Chrome浏览器下SVG效果

IE7下则是png图片显示的效果,如下截图:

IE7浏览器下png图片显示截图

上面这个技术是非常巧妙的,其创意借鉴了Jake Archibald的一个研究,即所有浏览器,包括IE,会把image标签渲染成img标签,而SVG中的image作用是:

Provides a way to display a graphics image on the screen.

也就是提供在屏幕上显示一个图形图像的方法。

于是,就有,如果浏览器支持SVG,则SVG显示;对于不支持的浏览器,例如IE8浏览器,会忽略svg标签的存在,直接渲染image,在其看来,这就是个img标签,于是,图像就以svg.png的形式显示了。

略微的不爽
在iOS 3 and 4设备上,image降级技术使用的结果是——图片显示。事实上,这两个操作系统的原生浏览器是支持SVG的,比方说以<img src="*.svg">形式,或者CSS的background-image;但是其唯独不支持inline SVG, 就是SVG标签形式嵌在HTML代码中的使用方法是不支持的。于是,导致的结果是,明明可以SVG形式显示的,现在这种用法就只能png图片显示了,略不爽!

然,iOS 3 and 4设备已是强弩之末(现在已经7了),面对现实,个人觉得现在已经没必要大惊小怪了。因此,这个技术,个人还是比较推荐的。

资源下载的研究
根据前辈的说法以及自己的验证,IE8-浏览器以及Android 2.3默认浏览器下,只会下载png图片,而Chrome这些噢啦的浏览器,只会下载SVG格式图形。如下:

Chrome浏览器的下载请求 张鑫旭-鑫空间-鑫生活

但是,在IE9~IE11浏览器下,情况就变得有些特殊了。

因为自己没忍住升级到了IE11,因此,没有IE10版本下的加载亲测截图,先用参考文章中的图片示意下:

IE10浏览器下IE9加载
IE10浏览器的加载

从上面两个测试截图可以看出,在IE10浏览器下,虽然其标准IE10以及IE9都支持SVG,但是,都发起了png图片的请求。不过,很有意思的是,该请求都被abort了,被阻止了,返回体的数据大小几乎或者就是0b,也就是没有任何数据返回。流量似乎是省掉了,但是,请求的时间依旧存在,如第一张截图所示的140ms. 根据某些更准确的测试,这个小小请求,虽然发送和接受的数据不过700多字节,但是,所耗费的时间有数百毫秒之多。如果页面头部有阻塞脚本,问题就比较严重了。

也可能正是由于这种略显奇葩的特性,在IE11浏览器中,情况又有大的改变,下面是我在win7 IE11下的测试截图:

IE11的显示
IE11浏览器下IE9模式下SVG请求

可以看到,IE11浏览器下,虽然显示的只有SVG,但是,png格式图片如若无人地加载进来了,以一种普通图片的姿态被加载进来了。且顺带影响了其小弟模式,如IE9模式也是这副拽模样。

测试结果大汇总

<svg><image>

<img src=svg.svg>

Browser <image> 技术 正常 <img> 下载 Chrome 28 SVG SVG 仅SVG IE 8 PNG — 仅PNG (via) IE 9 SVG SVG 阻断.png, 但仍耗费时间 IE 10 SVG SVG 也是声称阻断 – 但是看上去两者都下载 IE 11 SVG SVG 或阻断不阻断 (都不靠谱) iPhone 3GS (iOS 3) PNG SVG 需要测试 iPhone 4 (iOS 4) PNG SVG 仅PNG (来自) iPhone 4S (iOS 5) SVG SVG 需要测试 iPhone 5 (iOS 6) SVG SVG 仅SVG Android 2.3 PNG — 仅PNG (来自) Android 4 SVG SVG 仅SVG (来自) Firefox 22 SVG SVG 仅SVG

三、其他方式下的降级技术

1. 如果你使用SVG作为background-image
Modernizr有一个SVG测试,可以判定设备是否支持SVG,于是,我们就可以通过在HTML元素上添加特定的类名(eg. no-svg),做不同的样式控制。

.my-element {
  background-image: url(image.svg);
}
.no-svg .my-element {
  background-image: url(image.png);
}

这样就不会出现双下载的问题了。

但是,Modernizr毕竟是个外部依赖,且貌似膘肥体键,真要实际应用,不合适的来~

下面有个更优的方法,利用CSS支持的伪hack,如下使用:

.my-element {
  background-image: url(fallback.png);
  background-image: url(image.svg), none;
}

其利用的技术是CSS3多背景,这是一个经验式技术,我们通过各种观察或者积累发现,浏览器只要支持了多背景,几乎无一例外支持SVG. 于是,浏览器认识url(image.svg), none这个多背景声明,就使用SVG,否则,降级使用上面的png背景。很赞的match~

类似技术,我之前也介绍过,稍等,让我找找~

Get it! 此文为:“小tip:巧用CSS3属性作为CSS hack”。两年多前的了,唏嘘感叹时间流逝之快啊~~

2. 如果你使用SVG作为<svg>
首推本文一开始介绍的<image>技术,对于inline SVG轻微的降低支持问题(指针对ios3/ios4)设备,我个人觉得大可不必在意。

<svg width="96" height="96">
  <image xlink:href="svg.svg" src="svg.png" width="96" height="96" />
</svg>

David Ensinger发表过一项技术,是在SVG中使用<foreignObject>标签。呈现效果还不赖,但问题是,无论哪个浏览器,俱进派还是顽固派都会下载降级的PNG图片,这显然没有上面的<image>技术智能。

当然,你还可以借助Modernizr做些更加灵活的处理:

<svg> ... inline SVG XXX ... </svg>
<div class="my-svg-alternate"></div>
.my-svg-alternate {
  display: none;
}
.no-svg .my-svg-alternate {
  display: block;
  width: 96px;
  height: 96px;
  background-image: url(image.png);
}

3. 如果你使用SVG作为<object>
使用<object>标签作为SVG元素本身,对于不支持浏览器,还是需要Modernizr或自己写个判断,或者自己经验的浏览器判断实现:

<object type="image/svg+xml" data="image.svg" class="logo"></object>
.no-svg .logo {
  display: block;
  width: 96px;
  height: 96px;
  background-image: url(image.png);
}

4. 如果你使用SVG作为<img>
Scott Jehl喜欢这么做

<img src="image.svg" onerror="this.src=image.png">

HTML混杂行为,如果你是个具有分离癖好的人,上面的方法可能会让你揪心,你可以直接Modernizr的JS API,在脚本中判断处理,类似下面:

if (!Modernizr.svg) {
  $("img[src$='.svg']").attr("src", fallback);
}

如果上面代码中的fallback是个URL字符串,你可以把这个字符串放在data-fallback中,然后,你就可以根据你的实际需要,例如,根据后缀做智能判断加载等。

SVGeezy就是个专门做这种事情的JS库。

或者,你藏个隐藏的DIV,在需要降级显示的时候就显示,上面有出现过……

四、SVG结语

从最近我对国外一些知名前端网站的文章观察来看,SVG相关的内容比重越来越大,去年是满屏的响应式,SO,我似乎嗅到了一点技术流行趋势的味道。国内前端技术的流行普遍具有滞后性,差不多1~2年的样子。因此,本文内容,对于很大一部分同行而言,可能就是“哦~”一下,不打紧。您可以先记住这里,等明年这个时候,或者明年的明年的这个时候,当你发现你要折腾SVG的时候,再来围观围观,希望到时,本文的一些小技术不会过时,(*^__^*) 嘻嘻……

感谢阅读,欢迎纠错!

(本篇完)1f44d.svg 是不是学到了很多?可以分享到微信
1f44a.svg 有话要说?点击这里


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK