- 原文地址:ANIN-DEPTHSVGTUTORIAL
- 原文作者:flaviocopes.com
- 译文出自:掘金翻译计划
- 本文永久链接:github.com/xitu/gold-m…
- 译者:Starrier
- 校对者:dandyxu、allenlongbaobao
深入浅出SVG
SVG是优秀且令人难以置信的强大图像格式。本教程通过简单地解释所有需要了解的知识,为您提供SVG的概述。
介绍
尽管在21世纪初被标准化了,SVG(ScalableVectorGraphics的缩写)是近年来的一个热门话题。
SVG已经被糟糕的浏览器支持(尤其是IE)惩罚了好多年。
我发现这话源自一本2011的书:在撰写本文时,只有在最新的浏览器中才能将SVG直接嵌入到HTML中工作。7年过去了,这句话现在已经是过去式了,我们可以很安全地使用SVG图像。
现在我们可以安全地使用SVG图像,除非您有很多用户使用IE8以及更低版本,或者使用较旧的Android设备。这种情况下,依然存在着备选方案。
SVG成功的一部分是由于我们必须支持各种不同分辨率和尺寸的屏幕显示。SVG能完美解决这个问题。
同时,Flash在过去几年的迅速衰退导致大家对SVG产生了兴趣。这对于Flash过去所做的许多事情都是非常重要的。
SVG是一种vector图像文件格式。这使得它们与其他图像格式(如PNG、GIF或JPG)有很大的不同,后者是光栅图像文件格式。
SVG的优势
由于SVG图像是矢量图像,可以无限缩放,而且在图像质量下降方面没有任何问题。为什么会这样呢?因为SVG图像是使用XML标记构建的,浏览器通过绘制每个点和线来打印它们,而不是用预定义的像素填充某些空间。这确保SVG图像可以适应不同的屏幕大小和分辨率,即使是那些尚未发明的。
由于是在XML中定义的,SVG图像比JPG或PNG图像更灵活,而且我们可以使用CSS和JavaScript与它们进行交互。SVG图像设置可以包含CSS和JavaScript。
SVG可以渲染比其他格式小得多的矢量风格图像,主要用于标识和插图。另一个巨大的用例是图标。曾经是图标字体域,比如FontAwesome,现在的设计师更喜欢使用SVG图像,因为它更小,并且允许使用多色图标。
SVG在动画方面很简单,这是一个非常酷的话题。
SVG提供了一些图像编辑效果,比如屏蔽和剪裁、应用过滤器等等。
SVG只是文本,因此可以使用GZip对其进行有效压缩。
您的第一个SVG图像
SVG图像使用XML定义,这意味着如果您精通HTML,SVG看起来会非常熟悉,除了在SVG中有标签适合文档构建(如p
、article
、footer
、aside
)我们还有矢量图的构建块:path
、rect
、line
等等。
这是一个SVG图像示例:
<svgwidth="10"height="10"><rectx="0"y="0"width="10"height="10"fill="blue"/></svg>
注意它非常容易阅读和理解图像的样子:它是一个10x10像素的简单蓝色矩形(默认单元)。
大多情况下,您不必编写SVG代码,因为您可以使用Sketch或Figma等工具或任何其他矢量图形工具来创建图像,并将其导出为SVG。
SVG的当前版本是1.1,SVG2.0正在研发。
使用SVG
浏览器可以通过将它们包含在一个img
标签中来显示SVG图像:
<imgsrc="image.svg"alt="MySVGimage"/>
就像其他基于像素的图像格式一样:
<imgsrc="image.png"alt="MyPNGimage"/><imgsrc="image.jpg"alt="MyJPGimage"/><imgsrc="image.gif"alt="MyGIFimage"/><imgsrc="image.webp"alt="MyWebPimage"/>
此外,SVG非常独特,它们可以直接包含在HTML页面中:
<!DOCTYPEhtml><html><head><title>Apage</title></head><body><svgwidth="10"height="10"><rectx="0"y="0"width="10"height="10"fill="blue"/></svg></body></html>
请注意HTML5和XHTML对于内联SVG图像需要不同的语法。幸运的是,XHTML已经是过去的事情了,因为它过于繁杂,但是如果您仍然需要处理XHTML页面,就值得去了解它。
在HTLM中内联SVG的功能使该格式成为场景中的unicorn,因为其他图像不能这样做,必须为每个图像打开一个单独的请求来获取该格式。
SVG元素
在上面的示例中,您看到了rect
元素的用法。SVG有许多不同的元素。
最常用的是
text
:创建一个text元素circle
:创建一个圆rect
:创建一个矩形line
:创建一条线path
:在两点之间创建一条路径textPath
:在两点之间创建一条路径,并创建一个链接文本元素polygon
:允许创建任意类型的多边形g
:单独的元素
坐标从绘图区域左上角的0,0开始,并从左到右表示x
,从上到下表示y
。
您看到的图像反映了上面所示的代码。使用浏览器DevTools,您可以检查和更改它们。
text
text
元素添加文本。可以使用鼠标选择文本。x
和y
定义文本的起始点。
<svg><textx="5"y="30">Anicerectangle</text></svg>
漂亮的长方形
circle
定义圆。cx
和cy
是中心坐标,r
是半径。fill
是一个常用属性,表示图形颜色。
<svg><circlecx="50"cy="50"r="50"fill="#529fca"/></svg>
rect
定义矩形。x
,y
是起始坐标,width
和height
是自解释的。
<svg><rectx="0"y="0"width="100"height="100"fill="#529fca"/></svg>
line
x1
和y1
定义起始坐标。x2
和y2
定义结束坐标。stroke
是一个常用属性,表示线条颜色。
<svg><linex1="0"y1="0"x2="100"y2="100"stroke="#529fca"/></svg>
path
路径是一系列的直线和曲线。它是所有SVG绘制工具中最强大的,因此也是最复杂的。
d
包含方向命令。这些命令以命令名和一组坐标开始:
M
表示移动,它接受一组x,y坐标L
表示直线将绘制到它接受一组x,yH
是一条水平线,它只接受x坐标V
是一条垂直线,它只接受y坐标Z
表示关闭路径,并将其放回起始位置A
表示Arch,它自己需要一个完整的教程Q
是一条二次Bezier曲线,同样,它自己也需要一个完整的教程
<svgheight="300"width="300"><pathd="M100100L200200H10V40H70"fill="#59fa81"stroke="#d85b49"stroke-width="3"/></svg>
textPath
沿路径元素的形状添加文本。
WowsuchaniceSVGtut
polygon
使用polygon
绘制任意多边形。points
代表一组x,y坐标多边形应该链接:
<svg><polygonpoints="9.9,1.1,3.3,21.78,19.8,8.58,0,8.58,16.5,21.78"/></svg>
g
使用g
元素,您可以对多个元素进行分组:
<svgwidth="200"height="200"><rectx="0"y="0"width="100"height="100"fill="#529fca"/><gid="my-group"><rectx="0"y="100"width="100"height="100"fill="#59fa81"/><rectx="100"y="0"width="100"height="100"fill="#59fa81"/></g></svg>
SVGviewport和viewBox
SVG相对于其容器的大小由svg
元素的width
和height
属性设置。这些单位默认为像素,但您可以使用任何其他常用单位,如%
或em
。这是viewport。
通常“container”指的是浏览器窗口,但svg
元素可以包含其他svg
元素,在这种情况下,容器是父元素svg
。
一个重要的属性是viewBox
。它允许您在SVG画布中定义一个新的坐标系统。
假设在200x200pxSVG中有一个简单的圆:
<svgwidth="200"height="200"><circlecx="100"cy="100"r="100"fill="#529fca"/></svg>
通过指定viewBox,您可以选择只显示此SVG的一部分。例如,您可以从0,0点开始,只显示一个100x100px画布:
<svgwidth="200"height="200"viewBox="00100100"><circlecx="100"cy="100"r="100"fill="#529fca"/></svg>
从100,100开始,您会看到另一部分,圆圈的右下角:
<svgwidth="200"height="200"viewBox="100100100100"><circlecx="100"cy="100"r="100"fill="#529fca"/></svg>
一个很好的可视化方法是想象GoogleMaps是一个巨大的SVG图像,而您的浏览器是一个和窗口大小一样大的视图框。当您移动时,Viewbox会更改它的起始点(x,y)坐标,并且当您调整窗口的大小时,会更改Viewbox的宽度和高度。
在Web网页中插入SVG
将SVG添加到网页中有多种方法。
最常见的是:
- 带有
img
标签 - 带有CSS
background-image
属性 - 在HTML中内联
- 带有
object
、iframe
或embed
标签
在Glitch上可以查看这些示例flavio-svg-loading-ways.glitch.me/
带有img
标签
<imgsrc="flag.svg"alt="Flag"/>
带有cssbackground-image
属性
<style>.svg-background{background-image:url(flag.svg);height:200px;width:300px;}</style><divclass="svg-background"></div>
在HTML中内联
<svgwidth="300"height="200"viewBox="00300200"version="1.1"xmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink"><title>ItalianFlag</title><desc>ByFlavioCopeshttps://flaviocopes.com</desc><gid="flag"><rectfill="green"x="0"y="0"width="100"height="200"></rect><rectfill="white"x="100"y="0"width="100"height="200"></rect><rectfill="red"x="200"y="0"width="100"height="200"></rect></g></svg>
带有object
、iframe
或embed
标签
<objectdata="flag.svg"type="image/svgxml"></object><iframesrc="flag.svg"frameborder="0"></iframe><embedsrc="flag.svg"type=""/>
使用embed
,您可以使用以下命令从父文档获取SVG文档
document.getElementById('my-svg-embed').getSVGDocument()
在SVG内部,您可以通过以下方式引用父文档:
window.parent.document
使用数据URL内联SVG
您可以使用以上任何示例结合DataURLs将SVG内联到HTML中:
<imgsrc="data:image/svgxml;<DATA>"alt="Flag"/><objectdata="data:image/svgxml;<DATA>"type="image/svgxml"></object><iframedata="data:image/svgxml;<DATA>"frameborder="0"></iframe>
在CSS中也是:
.svg-background{background-image:url("data:image/svgxml;<DATA>");}
只需使用适当的DataURL更改<DATA>
。
样式元素
任何SVG元素都可以接受style
属性,就像HTML标签一样。并非所有的CSS属性都能像您预期的那样工作。例如,要更改文本元素的颜色,请使用fill
而不是color
。
<svg><textx="5"y="30"style="fill:green">Anicetext</text></svg><svg><textx="5"y="70"style="fill:green;font-family:CourierNew">Anicetext</text></svg>
您也可以使用fill
作为元素属性,正如您在前面看到的那样:
<svg><textx="5"y="70"fill="green">Anicetext</text></svg>
其他公共属性包括
fill-opacity
,背景颜色不透明度stroke
,定义边框颜色stroke-width
,设置边框宽度
CSS可以针对SVG元素,就像您以HTML标签为目标一样:
rect{fill:red;}circle{fill:blue;}
使用CSS或JavaSCript与SVG交互
SVG图像可以使用CSS进行样式化,或者使用JavaScript编写脚本,这种情况下:
- 当SVG在HTML中内联
- 通过
object
、embed
或iframe
标签加载图像时
但是(⚠️取决于浏览器实现)它们必须从相同的域(和协议)加载,这是同源策略所导致的。iframe
需要显式定义的尺寸,否则内容将被裁剪,同时调整object
和embed
尺寸以适应其内容。.
如果SVG是使用img
标签加载的,或者使用CSS作为背景,则与源无关:
- CSS和JavaScript不能与之进行交互
- SVG中包含的JavaScript被禁用
- 无法从外部加载资源(如图像、样式表、脚本、字体)
细节
特性 | SVG内联 | object /embed /iframe | img |
---|---|---|---|
可以与用户交互 | ✅ | ✅ | ✅ |
支持动画 | ✅ | ✅ | ✅ |
可以运行JavaScript脚本 | ✅ | ✅ | ?? |
可以从外部编写脚本 | ✅ | ?? | ?? |
内联SVG图像无疑是最强大和最灵活的,它是使用SVG执行某些操作的唯一方法。
如果您想要SVG与您的脚本进行任何交互,它必须以内联的方式加载到HTML中。
如果您不需要与SVG交互,只需在页面中显示它,将SVG加载至img
、object
或者embed
中即可,如果您在不同的页面中重用SVG图像,或者SVG图像的大小相当大,那么加载SVG就特别方便。
CSS嵌入SVG
将CSS加至CDATA:
<svg><style><![CDATA[#my-rect{fill:blue;}]]></style><rectid="my-rect"x="0"y="0"width="10"height="10"/></svg>
SVG文件还可以包括外部样式表
<?xmlversion="1.0"standalone="no"?><?xml-stylesheettype="text/css"href="style.css"?><svgxmlns="http://www.w3.org/2000/svg"version="1.1"width=".."height=".."viewBox=".."><rectid="my-rect"x="0"y="0"width="10"height="10"/></svg>
JavaScript嵌入SVG
你可以将JavaScript放在第一个位置上,并包装在一个load
事件中,以便在页面完全加载并在DOM中插入SVG时执行它:
<svg><script><![CDATA[window.addEventListener("load",()=>{//...},false)]]></script><rectx="0"y="0"width="10"height="10"fill="blue"/></svg>
或者如果您将JS放在其他SVG代码的末尾,可以避免添加事件监听,确保当SVG出现在页面时JavaSCript会执行。
<svg><rectx="0"y="0"width="10"height="10"fill="blue"/><script><![CDATA[//...]]></script></svg>
与HTML元素一样,SVG元素也可以有id
和class
属性,因此我们可以使用SelectorsAPI来引用它们:
<svg><rectx="0"y="0"width="10"height="10"fill="blue"id="my-rect"class="a-rect"/><script><![CDATA[console.log(document.getElementsByTagName('rect'))console.log(document.getElementById('my-rect'))console.log(document.querySelector('.a-rect'))console.log(document.querySelectorAll('.a-rect'))]]></script></svg>
请查看此故障flaviocopes-svg-script.glitch.me/以获得功能性提示。
SVG外部的JavaScript
如果可以与SVG交互(SVG在HTML中是内联的),则可以使用JavaScript更改任何SVG属性,例如:
document.getElementById("my-svg-rect").setAttribute("fill","black")
或者真正地做任何您想要的DOM操作。
SVG外部的CSS
您可以使用CSS更改SVG图像的任何样式。
SVG属性可以很容易地在CSS中被覆盖,并且它们比CSS具有更低的优先级。它们的行为不像具有更高优先级的内联CSS。
<style>#my-rect{fill:red}</style><svg><rectx="0"y="0"width="10"height="10"fill="blue"id="my-rect"/></svg>
SVGvsCanvasAPI
CanvasAPI是Web平台一个很好的补充,它有类似于SVG的浏览器支持。与SVG主要的(也是最大的)不同之处是:画布不是基于矢量的,而是基于像素的,所以
- 它具有与基于像素的png、jpg和gif图像格式相同的缩放问题。
- 这使得不可能像使用SVG那样使用CSS或JavaScropt编辑画布图像。
SVG符号
符号使您可以定义一次SVG图像,并在多个地方重用它。如果您需要重用一个图像,这是一个很大的帮助,可能只是改变一点它的一些属性。
您可以通过添加一个symbol
元素并分配一个id
属性来完成此操作:
<svgclass="hidden"><symbolid="rectangle"viewBox="002020"><rectx="0"y="0"width="300"height="300"fill="rgb(255,159,0)"/></symbol></svg>
<svg><usexlink:href="#rectangle"href="#rectangle"/></svg><svg><usexlink:href="#rectangle"href="#rectangle"/></svg>
(xlink:href
用于Safari支持,即使它是一个已废弃的属性)
这让我们能开始了解SVG的强大功能。
如果您希望对这两个矩形使用不同的样式,例如,对每个矩形使用不同的颜色?您可以使用CSS变量.
<svgclass="hidden"><symbolid="rectangle"viewBox="002020"><rectx="0"y="0"width="300"height="300"fill="var(--color)"/></symbol></svg>
<svgclass="blue"><usexlink:href="#rectangle"href="#rectangle"/></svg><svgclass="red"><usexlink:href="#rectangle"href="#rectangle"/></svg><style>svg.red{--color:red;}svg.blue{--color:blue;}</style>
查看SVG符号--我的Glitchplayground。
验证SVG
SVG文件是XML,可以用无效的格式编写,有些服务或应用程序可能不接受无效的SVG文件。
SVG可以使用W3CValidator验证。
我应该包含xmlns
属性么?
有时SVG别定义为
<svg>...</svg>
有时定义为
<svgversion="1.1"xmlns="http://www.w3.org/2000/svg">...</svg>
第二个表单是XHTML。它可以与HTML5一起使用(文档具有<!DOCTYPEhtml>
),但在本例中,第一种形式更简单。
我应该担心浏览器支持问题么?
在2018版本中,绝大多数用户的浏览器都支持SVG。.
您仍然可以使用诸如Modernizr这样的库来检查缺少的支持,并提供一个后备:
if(!Modernizr.svg){$(".my-svg").attr("src","images/logo.png");}