简介
SVG指的是可缩放矢量图(Scalable Vector Graphics),它使用 XML 格式定义图形,在改变尺寸后仍能保持图形质量。SVG在2003年1月14日被确立为W3C标准。
svg、canvas、img对比
canvas
使用html + js来绘制图形,可用于图片、动画、游戏、数据可视化和实时视频处理。canvas默认开启硬件加速。(使用chrome://gpu/可进行查看)
<html>
<head>
<script>
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#000";
ctx.fillRect (10, 10, 20, 40);
}
}
</script>
</head>
<body onload="draw()">
<canvas id="canvas" width="150" height="150"></canvas>
</body>
</html>
优点
- 可用于制作图片,动画,绘制文本等
- 可避免图片下载,资源污染
canvas与img对比
- canvas是块元素,img是替换元素(默认display为inline,但内置宽高属性)
- canvas默认宽高为width: 300px; height: 150px;
- canvas默认只有
width
和height
两个属性,img还有src
、alt
等属性
svg
使用html + css来绘制图形,用于描述矢量图像的XML语言,可以理解为是一个HTML片段
优点
- 可使用工具进行读取和修改(记事本、IDE等)
- 尺寸更小,且可压缩性更强
- 图像中的文本是可选的,同时也是可搜索的
svg与img对比
-
内联svg可以减少http请求,从而减少加载时间,但浏览器不能像缓存图片一样缓存内联svg
-
可以通过选择器或行内属性设置样式
-
内联svg会加深HTML层级和增加HTML文件大小
-
svg中可以包含
<a>
使其成为超链接<svg width="140" height="30" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <a xlink:href="https://developer.mozilla.org/en-US/docs/SVG" target="_blank"> <rect height="30" width="120" y="0" x="0" rx="15"/> <text fill="white" text-anchor="middle" y="21" x="60">SVG on MDN</text> </a> </svg>
-
在img中引入svg作为图片时,仅能设置宽高,不能修改svg本身的样式(如颜色、文字大小等)
基本属性
-
xmlns:SVG文件设置该属性为
http://www.w3.org/2000/svg
后才能被浏览器解析成图形 -
viewBox(min-x min-y width height):设置图形容器
除
<svg>
外,<symbol>
、<image>
、<marker>
、<pattern>
、<view>
也具有该属性
CSS
mix-blend-mode
background-blend-mode
SVG形状
通用
- 所有面均可设置
fill
、fill-opacity
等填充相关属性,如果不设置fill
属性则默认填充色为黑色 - 所有形状均可设置
stroke
、stroke-width
、stroke-opacity
、stroke-dasharray
等描边相关属性,但stroke-dashoffset
属性仅能在 style 中设置,可用animation和该属性实现描边动画 - 设置
stroke-width
后描边从边框中心位置向两侧扩散,一般情况下设置偏移属性(如x
、y
、cx
、cy
等)时需要加上1/2的stroke-width
矩形
<rect width="100" height="100" x="5" y="5" rx="10" ry="50" fill="black" fill-opacity="0.5" stroke="red" stroke-width="10" stroke-opacity="0.3" stroke-dasharray="40,20" style="stroke-dashoffset: 100" />
rx
和ry
属性仅设其一时,另一属性也会自动应用
圆形
<circle r="50" cx="55" cy="55" fill="black" fill-opacity="0.5" stroke="red" stroke-width="10" stroke-opacity="0.3" />
椭圆
<ellipse rx="50" ry="40" cx="55" cy="45" fill="black" fill-opacity="0.5" stroke="red" stroke-width="10" stroke-opacity="0.3" />
- 椭圆与圆形十分类似,唯一不同的是需要分别设置
rx
、ry
属性
线条
<line x1="0" y1="55" x2="100" y2="55" stroke="red" stroke-width="10" stroke-opacity="0.3" />
stroke-linecap: butt | round | square | inherit
stroke-linejoin:arcs | bevel | miter | miter-clip | round
多边形
<polygon points="220,100 300,210 170,250 123,234" fill="black" fill-opacity="0.5" stroke="red" stroke-width="10" stroke-opacity="0.3" />
折线
<polyline points="220,100 300,210 170,250 123,234" fill="black" fill-opacity="0.5" stroke="red" stroke-width="10" stroke-opacity="0.3" />
- 折线与多边形不同的是折线不会将首尾两点相连形成面
- 折线与线条不同的是折线可以设置多个点和填充背景
路径[1]
下面的命令可用于路径数据(大写表示绝对路径,小写表示相对路径):
- M = moveto(M x,y):将画笔移动到指定的坐标位置
- L = lineto(L x,y):画直线到指定的坐标位置
- H = horizontal lineto(H x):画水平线到指定的X坐标位置
- V = vertical lineto(V y):画垂直线到指定的Y坐标位置
- C = curveto(C x1,y1,x2,y2,endx,endy):三次贝塞尔曲线
[2]
- S = smooth curveto(S x2,y2,endx,endy):平滑三次贝塞尔曲线
- Q = quadratic Belzier curve(Q x,y,endx,endy):二次贝塞尔曲线
- T = smooth quadratic Belzier curveto(T endx,endy):平滑二次贝塞尔曲线
- A = elliptical Arc(A rx,ry,xrotation,flag1,flag2,x,y):椭圆弧
- Z = closepath:关闭路径
<path d="M250 150 L150 350 L350 350 Z" />
<path d="M153 334 C153 334 151 334 151 334 C151 339 153 344 156 344 C164 344 171 339 171 334 C171 322 164 314 156 314 C142 314 131 322 131 334 C131 350 142 364 156 364 C175 364 191 350 191 334 C191 311 175 294 156 294 C131 294 111 311 111 334 C111 361 131 384 156 384 C186 384 211 361 211 334 C211 300 186 274 156 274" fill="none" stroke="red" stroke-width="2" />
SVG渐变[3]
SVG中渐变颜色的设置,不能像css
那样,直接写fill="linear-gradient(color1, color2)"
,而要使用专门的渐变标签:<linearGradient>
(线性渐变) 和 <radialGradient>
(径向渐变或放射渐变)。一个SVG元素上只能有一个渐变。
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="orange_red" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
</defs>
<ellipse cx="200" cy="190" rx="85" ry="55" style="fill:url(#orange_red)" />
</svg>
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="grey_blue" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(200,200,200);stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="230" cy="200" rx="110" ry="100" style="fill:url(#grey_blue)" />
</svg>
SVG滤镜[4]
用来给形状和文本添加特殊效果,如:模糊、阴影、扭曲、图像合成叠加等,一个SVG元素上可以同时使用多个滤镜。
CSS提供的内置滤镜有:
- blur 高斯模糊
- brightness 亮度
- contrast 对比度
- drop-shadow 图形阴影
- grayscale 灰度
- hue-rotate 色相旋转
- invert 颜色反转
- opacity 透明度
- saturate 饱和度
- sepia 深褐色滤镜
SVG提供的滤镜有:
- feBlend:混合滤镜
- feColorMatrix:颜色矩阵变换滤镜
- feComponentTransfer
- feComposite
- feConvolveMatrix
- feDiffuseLighting:漫反射(太阳光/灯光照明)滤镜
- feDisplacementMap:映射置换滤镜,用于改变元素和图形的像素位置
- feFlood:填充滤镜
- feGaussianBlur:高斯模糊滤镜
- feImage:图片滤镜
- feMerge、feMergeNode:多滤镜叠加滤镜
- feMorphology:形态滤镜,可使图形变细或变粗
- feOffset:位移滤镜
- feSpecularLighting:镜面反射(光照明)滤镜
- feTile
- feTurbulence:噪声滤镜,可实现半透明的烟熏或波状图像
- feDistantLight:距离光源滤镜
- fePointLight:点光源滤镜
- feSpotLight:聚光灯光源滤镜
- feDropShadow:图像投影滤镜
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="Gaussian_Blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>
<ellipse cx="200" cy="150" rx="70" ry="40" style="fill:#ff0000;stroke:#000000;stroke-width:2;filter:url(#Gaussian_Blur)" />
</svg>
其他常见标签
-
<g>:分组
-
<text>:文本
-
<marker>:标记(在路径的结束位置放置图形标记)
-
<pattern>:纹理(可将图形或其他内容作为纹理填充到图形中)
- patternUnits:userSpaceOnUse(重复)/objectBoundingBox(缩放)
- patternContentUnits:userSpaceOnUse/objectBoundingBox
-
<mask>:遮罩(可看做一个透明的遮罩层和当前对象合成,形成背景)
mask内图形的颜色不会改变作用元素的颜色。
mask内的颜色表现为越接近#FFFFFF越透明(合成后作用元素的颜色越明显),反之越接近#000000越不透明,因此可以用来实现穿孔效果
<svg class="border" width="200" height="200" viewBox="0 0 200 200"> <defs> <mask id="Mask1"> <!-- mask 内图形的颜色不会改变作用元素的颜色,只影响遮罩的透度,越接近白色越透 --> <rect x="0" y="0" width="200" height="200" fill="#FF0000" /> <circle cx="100" cy="100" r="50" fill="#FFFFFF" /> </mask> </defs> <rect x="0" y="0" width="200" height="200" fill="green" mask="url(#Mask1)"/> </svg>
-
<clipPath>:限制渲染区域(如果图形超出了当前剪切路径所包围的区域,那么超出部分将不会绘制)
- inset(top right bottom left round radius):创建一个矩形区域,将元素的内容裁剪成矩形或带有圆角的矩形。
top
,right
,bottom
,left
:分别定义裁剪区域的四个边距,可以是像素值、百分比或auto
。radius
(可选):定义四个角的圆角半径。可以是单一值或四个不同的值来分别设置每个角的圆角。
- circle(radius at centerX centerY):创建一个圆形的裁剪区域。
radius
:定义圆的半径,可以使用像素(px)、百分比(%)等单位。center
:可选的圆心位置,默认为元素的中心。可以用x
和y
坐标值来指定圆心的位置,例如:circle(50% at 50% 50%)
表示圆心位于元素的中心,半径为元素宽度的一半。
- ellipse(radiusX radiusY at centerX centerY):创建一个椭圆形的裁剪区域。
radiusX
:椭圆的水平半径。radiusY
:椭圆的垂直半径。centerX
和centerY
:椭圆的中心位置,默认为元素的中心。
- polygon(x1 y1, x2 y2, x3 y3, …):定义一个多边形形状的裁剪区域。可以通过指定一组坐标来定义多边形的顶点。
- path(‘path data’):使用路径定义任意形状的裁剪区域。通过路径数据(SVG路径)来描述复杂形状。
- url(#clipId):引用外部 SVG 文件中定义的
<clipPath>
元素,其中<clipPath>
元素可以定义成渐变形状。
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"> <defs> <clipPath id="master_svg0_1122_19473"> <rect x="0" y="0" width="24" height="24" rx="0"/> </clipPath> </defs> <g clip-path="url(#master_svg0_1122_19473)"> <g> <path d="M5.889,15.99996103553772L2,15.99996103553772C1.447715,15.99996103553772,1,15.55226103553772,1,14.99996103553772L1,9.00000103553772C1,8.447711035537719,1.447715,8.00000103553772,2,8.00000103553772L5.889,8.00000103553772L11.183,3.6680000355377196C11.3325,3.5454199355377196,11.5393,3.5200295355377196,11.714,3.6027975355377198C11.8888,3.68556503553772,12.0001,3.86165603553772,12,4.05500003553772L12,19.94496103553772C12.0001,20.13836103553772,11.8888,20.314461035537718,11.714,20.39716103553772C11.5393,20.47996103553772,11.3325,20.45456103553772,11.183,20.33196103553772L5.89,15.99996103553772L5.889,15.99996103553772ZM19.406,20.13396103553772L17.99,18.71796103553772C19.9075,17.01186103553772,21.0031,14.56666103553772,21,12.00000103553772C21.0025,9.29867103553772,19.7891,6.73965103553772,17.696,5.03200103553772L19.116,3.6120000355377195C21.5823,5.699941035537719,23.0032,8.76858103553772,23,12.00000103553772C23,15.22296103553772,21.614,18.12196103553772,19.406,20.13396103553772ZM15.863,16.59096103553772L14.441,15.16896103553772C15.425,14.41236103553772,16.0011,13.24123103553772,16,12.00000103553772C16,10.57000103553772,15.25,9.315001035537719,14.12,8.60800103553772L15.559,7.16900103553772C17.0952,8.29904103553772,18.0016,10.09294103553772,18,12.00000103553772C18,13.84196103553772,17.17,15.48996103553772,15.863,16.59096103553772Z" fill="#3E84FF" fill-opacity="1"/> </g> </g> </svg>
- inset(top right bottom left round radius):创建一个矩形区域,将元素的内容裁剪成矩形或带有圆角的矩形。
应用场景
- 直接作为矢量图片使用
- 内联SVG为组件添加背景
- 内联SVG + CSS / JS为组件添加动画
- 手动绘制简单图形,如:点线面图例、线路图(可绘制阴影)等
- …
其他应用
- 如果想让父元素来控制svg颜色,可将
fill
或stroke
属性设为currentColor
<div style="width: 100px; height: 100px; color: blue"> <svg viewBox="0 0 24 24" style="fill: currentColor; stroke: currentColor"> <circle r="10" cx="10" cy="10" /> <line x1="0" y1="10" x2="10" y2="10" /> </svg> </div>
- 当viewBox属性固定,默认修改svg标签的宽高,svg都会按比例缩放。如果不想按比例缩放,需要svg撑满整个画面,只需为svg标签添加属性:preserveAspectRatio=“none”
- 获取路径或线条的长度
const path = document.querySelector('path'); const length = path.getTotalLength();
- 第三方库:echarts
[5]
、d3等
附录
[1]
SVG path
[2]
贝塞尔曲线
[3]
SVG 渐变
[4]
SVG 滤镜