SVG快速⼊门
SVG 全称是 Scalable Vector Graphics,即,⽮量图。在 Web 中使⽤ SVG 可以解决位图放⼤失真的问题。⾸先,不要把 SVG 和 CSS,Canvas,HTML 搞混。他们之间并没有你中有我,我中有你的关系。SVG 是通过 XML 的形式写在 HTML ⽂档中的。
如何书写
开篇说过,SVG 就是⼀个 XML。看⼀下代码吧:
<svg x="0px" y="0px" width="450px" height="100px" viewBox="0 0 450 100">
<rect x="10" y="5" fill="white" stroke="black" width="90" height="90"/>
<circle fill="white" stroke="black" cx="170" cy="50" r="45"/>
<polygon fill="white" stroke="black" points="279,5 294,35 328,40 303,62
309,94 279,79 258,94 254,62 230,39 263,35"/>
<line fill="none" stroke="black" x1="410" y1="95" x2="440" y2="6"/>
<line fill="none" stroke="black" x1="360" y1="6" x2="360" y2="95"/>
</svg>
⼤家看 svg 标签中带有⼀个 viewBox 的属性。这其实是 SVG 中⼀个很重要的概念,后⾯的缩放都会与它有关。
说到这⾥,我们就需要了解⼀下关于 SVG 的⼏个基本概念。
基本概念
简单来说有 3 个基本概念:
viewport: 物理窗⼝
viewbox: 实物窗⼝(算了,下⾯解释)
preserveAspectRatio: 保留横纵⽐
我们接下来,⼀个⼀个的进⾏讲解吧。
viewport
参照上⾯的 demo,这实际上就是你⽤ x,y,width,height。这 4 个属性,在页⾯上固定的矩形区域。
viewbox
定义 SVG 元素在 viewport 中的具体尺⼨⽐例。假设有如下内容:
<svg width="500" height="200" viewBox="0 0 50 20" >
<rect x="20" y="10" width="10" height="5"
/>
</svg>
viewport 为 [0,0] 到 [500,200]
viewbox 为 [0,0] 到 [50,20]
默认情况下 SVG 是⾃动填充满 viewport 的。注意,在 SVG 中,⼦标签的所有尺⼨都是不能带单位的,因为初始单位就是根据上⾯两个概念确定。
当为以上情况,SVG 中基本的尺⼨则不是 1px,⽽是 500/50 = 10px。所以,如下的图形⼤⼩为:
<rect x="20" y="10" width="10" height="5"
/>
也就是在 SVG ⾥⾯定义的rect图形,它的实际尺⼨为 [200,100] 到 [100,50]。
preserveAspectRatio
该属性就是⽤来定义上⾯ viewport 和 viewbox 相互对齐的⽅式。换句话就是说,它的属性可以改变 viewbox 的具体位置。基本格式为:
<align> [<meetOrSlice>]
align: 定义 viewport 和 viewbox 的对齐⽅式,分为 x,y 轴两个⽅向。X 轴⽅向有三种⽅式:左边重合(xMin),x 轴中点重合(xMid),右边重合(xMax)。同理,Y 轴也有顶边重合(YMin),y 轴中点重合(YMid),底边边重合(YMax)
meetOrSlice: 主要就是定义该 SVG 是内嵌,还是裁剪或是 none(听天有命)。
其中,align 需要着重理解⼀下。⾸先,它的默认值为 xMidYMid,即为中点重合。
可以从图中看出,viewbox 是通过中⼼进⾏延展的。注意,它的原点坐标还是在 viewbox 的左上⾓。如果你是动态增加尺⼨的话,此时并不是从左到右增加,⽽是从中⼼向两端扩张。同理,如果你使⽤的是xMinYMin 的话,那么如果存在尺⼨变化,那么相对点则是从左上⾓开始的。简单来说,align 相对点其实⼀共有 9个。
然后就是 meet || slice || none 这三个属性具体⼲的事情。
在这之前,我们需要了解⼀个公式–缩放⽐计算公式:
vb_h * rat_y = vp_h; 或者 vb_w * rat_x = vp_w;
其中,vb_ 为 viewbox 简写,vp_ 为 viewport 的简写。vb_h 代表就是 viewbox height。vb_w 代表就是viewbox width。rat_x/y 代表的是 x,y 轴的缩放⽐例。
假设有下列情况:
<svg width="400" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin slice" > <rect x="10" y="10" width="150" height="150" fill="#cd0000"/>
</svg>
那么,rat_x 和 rat_y 分别为:
rat_x = 400/200 = 2
rat_y = 200/200 = 1
现在,针对上⾯ meet/slice 不同的取值,实际应⽤到 svg ⾥⾯的缩放⽐例是不同的。
meet(默认值): 本意是让 svg 尽可能的显⽰在 viewport ⾥,即,会在 rat_x 和 rat_y 中选择最⼩的值作为缩放标准。
slice: 本意是让 svg 完全铺满 viewport,即,会在 rat_x 和 rat_y 中选择最⼤的值作为缩放标准。
所以针对不同的取值,基准⽐例也不同。
当为 meet 的情况,那么实际缩放⽐例为 1。则⾥⾯实际矩形的⼤⼩就为 (10,10) 到 (150,150)。
当为 slice 的情况,那么实际缩放⽐例为 2。则⾥⾯实际矩形的⼤⼩就为 (20,20) 到 (300,300)。
如果你的值为 none 的话,他会直接铺满整个 viewport,即,实际矩形⼤⼩为:(20,10) 到 (300,150)。
响应式 SVG
虽然讲起响应式,⼀些童鞋会想这 TM ⼜是啥奇技淫巧?
对不起,并不是。。。就是⼀个 viewbox 并且不带 width/height ⽽已。
看个实际的例⼦吧:
<svg viewBox="0 0 218.8 87.1">
<g fill="none" stroke="#000">
<path d="M7.3 75L25.9 6.8s58.4-6.4 33.5 13-41.1 32.8-11.2 30.8h15.9v5.5s42.6
18.8 0 20.6" />
<path d="M133.1 58.2s12.7-69.2 24.4-47.5c0 0 4.1 8.6 9.5.9 0 0 5-10 10.4.9 0
0 12.2 32.6 13.6 43 0 0 39.8 5.4 15.8 15.4-13.2 5.5-53.8
13.1-77.4 5.9.1 0-51.9-15.4 3.7-18.6z" />
</g>
</svg>
可以看到,上⾯的 svg 标签并没有带上啥 width/height 属性,只是简单描述了 viewBox 的范围⽽已。当然,⾥⾯的尺⼨标准都是在这 viewBox 的范围内进⾏设置的。
另外,在这⾥声明⼀下,本⽂章并不是新⼿教程,也就是说,不会教你⼀步⼀步的画直线啊,圆啊,矩形啊等等这些基本图形。这些直接 google ⼀下,⼀搜⼀⼤把。所以,这⾥假设⼤家的⽔平是处于,能对 SVG 基本的图形属性熟悉即可,对⼀些⾼级属性还不是很清楚和熟练。OK,继续~
svg图形在 SVG 中,能够直接使⽤的图形有:
rect
circle
ellipse
line
polyline
polygon
上⾯没有啥说的,后⾯我详细说⼀下两个⽐较重要的概念,分组和 Path。
分组和 Path
通常 Path 和分组通常是⼀起使⽤的,如上:
<g fill="none" stroke="#000">
<path d="M7.3 75L25.9 6.8s58.4-6.4 33.5 13-41.1 32.8-11.2 30.8h15.9v5.5s42.6
18.8 0 20.6" />
<path d="M133.1 58.2s12.7-69.2 24.4-47.5c0 0 4.1 8.6 9.5.9 0 0 5-10 10.4.9 0
0 12.2 32.6 13.6 43 0 0 39.8 5.4 15.8 15.4-13.2 5.5-53.8
13.1-77.4 5.9.1 0-51.9-15.4 3.7-18.6z" />
</g>
分组我们放到后⾯进⾏讲解,这⾥先看⼀下 Path。
Path
Path 在 SVG 中的地位应该是⽐较⾼的,实际上,利⽤ Path 这个⼀个标签可以画出任意的图形。path 中
d(data) 属性是⽤来定义相关线条数据,通常是以M/m为起始,代表的就是move to的意思。在 path 中,⼀共可以定义 10 种不同的图形。例如M/m,L/l。⼤家可以注意,每种标识符有两种书写⽅式,即,⼤⼩写。
⼤写: 参照的是绝对坐标,即,SVG 的右上⾓
⼩写: 参照的相对坐标,即,前⼀个点的坐标。
⽽在 10 中不同表⽰符中,⼜可以分为直线和曲线两种不同的标识符。这⾥,我们分类来讲解⼀下。
线型
M/m
该使⽤定义起始点的,没啥特殊的作⽤。
<path d="M10 10"/>
表⽰,以 (10,10) 为起始点。
L/l
原意是 Line to,⽤来画线段的。格式和 M/m 差不多:
L x y (or l dx dy)
H/h
⽤来画⽔平线,即,Horizontal。既然⽅向已经定了,剩下的就是距离,格式很简单:
H x (or h dx)
V/v
⽤来画竖直线,即,vertical。同上,⽅向也定了,格式为:
V y (or v dy)
看个例⼦吧:
<path d="M10 10 H 90 V 90 H 10 L 10 10"/>
该 path 实际上就是画了⼀个正⽅形,宽 = ⾼ = 90。
Z/z
该标识符⽤来表⽰ path 的结束,并且将最后⼀点和 M/m 标识开头的⼀点连接起来。所以,它不存在什么表⽰点之类的,格式为:
Z (or z)
⽽上⾯也可以进⾏相关的优化,最终的结果为:
<path d="M10 10 H 90 V 90 H 10 L 10 10"/>
// 使⽤ Z
<path d="M10 10 H 90 V 90 H 10 Z" fill="transparent" stroke="black"/>
曲线
曲线就是 Web 画图中常见的 Bezier Curves(贝塞尔),Arcs,several Bezier curves(很多贝塞尔 - .-)等。
我们简单看⼀下:
C/c
这是正统的贝塞尔曲线,需要 4 个参考点,下图应该说⽐较确切表⽰了⼆次贝塞尔所需要的点。所以,C/c 需要定义三个点。
基本格式为:
C x1 y1, x2 y2, x y (or c dx1 dy1, dx2 dy2, dx dy)
例如:
<path d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/>
S/s
该标识符实际上使⽤来表⽰⼀个反射贝塞尔,即,在原有贝塞尔上再加⼀段贝塞尔曲线,所以,S/s ⼀般和C/c ⼀起使⽤。
基本格式为:
S x2 y2, x y (or s dx2 dy2, dx dy)
实际样式图为:
相当于原有的贝塞尔曲线的最后⼀段进⾏反向延长并对称。然后加上新定义的⼀段限制曲线。
具体实例为:
<path d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="black" fill="transparent"/>
Q/q
该标识符是⽤来定义⼆次(quadratic)贝塞尔曲线,该曲线相当于上⾯传统的贝塞尔来说,更加简单,它只需要定义三个点,即可完整⼀个贝塞尔曲线,具体作图过程如下:
基本格式为:
Q x1 y1, x y (or q dx1 dy1, dx dy)
即为图上点, P1(x1,y1),P2(x,y)
起始点为 M 定义的点,例如:
<path d="M10 80 Q 95 10 180 80" stroke="black" fill="transparent"/>
T/t
该标识符和 S 差不多,也是⼀个贝塞尔曲线的延长。相当于原曲线的控制点 P1 相当于 end point P2 做对称,然后,只需要定义⼀个终点即可,即,T/t 只需要定义贝塞尔曲线⾥⾯的终点即可:
T x y (or t dx dy)
如图:
所以,简单来说,C/S,Q/T 是两两搭配⼀起使⽤的。在使⽤的时候,千万不要搞混即可。
弧线
A/a
该曲线是⽤来画弧线(Arcs),⽽,弧线通常是圆/椭圆的⼀部分。当,椭圆的两个轴径长相等则为圆,所
以,A/a 是按照椭圆作为基准格式:
A rx ry x-axis-rotation large-arc-flag sweep-flag x y
a rx ry x-axis-rotation large-arc-flag sweep-flag dx dy
说实在的,这个⽐较复杂。因为,他画椭圆的⽅式和我们平常不⼀样,⼀般情况下,椭圆只要确定⼀个中⼼,然后是长短轴,然后是弧度范围即可。
但是,它这⾥是通过椭圆上的两点来确定的,在加上旋转⾓度,俩轴径等因素来确定的。另外,需要注意,它的起始点是从上⼀个命令的结束点位置开始计算的。OK,我们⾸先简单了解⼀下格式⾥⾯的参数:
rx,ry: 代表的就是长轴短轴,没得说。
x,y: 代表的是弧长的结束点。开始点就是上⼀个命令的终点。
x-axis-rotation: x 轴的旋转⾓度。顺时针为正
large-arc-flag[0,1]: 表⽰取⼤弧还是⼩弧。因为两点之间的弧长有两部分。
sweep-flag[0,1]: 取顺时针的弧,还是逆时针的弧长。参考点是以起始点开始的。
上⾯⼏个属性中,⽐较难理解的就是large-arc-flag和sweep-flag。这么说吧,前⾯⼏个属性充其量只能确定椭圆的位置,和经过椭圆的两个点,不过,⼀般能通过指定两点的椭圆有两个,⽽通过这两点划分⼜会出现 4 段弧长。为了确定 4 个弧长中,是哪⼀个,需要两个值来确定。即,4 抽 2,2 抽 1。
简单说⼀种,例如当,laf 和 sf 都为 0的情况。⾸先,laf 为 0 选择的是⼩弧长。所以,⾥⾯两段⽐较⼩的弧长被抽出来。然后,sf 为 0 选择的是逆时针。即,以起始点为参考,选择通过逆时针⽅向到达终点的那段弧。即,2 抽 1。最终得出我们需要的弧。
说实在的,这个是真 TM 复杂。。。
给⼀个参考codepen。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论