SVG 在线画图工具:https://svg.haowen100.com/
把画的图片代码保存成svg文件,加载
http://www.bejson.com/convert/image_to_svg/
https://www.aconvert.com/cn/image/png-to-svg/
参考一
SVG 是一种基于 XML 语法的图像格式,全称是可缩放矢量图(Scalable Vector Graphics)。其他图像格式都是基于像素处理的,SVG 则是属于对图像的形状描述,所以它本质上是文本文件,体积较小,且不管放大多少倍都不会失真。
SVG 文件可以直接插入网页,成为 DOM 的一部分,然后用 JavaScript 和 CSS 进行操作。
上面是 SVG 代码直接插入网页的例子。
SVG 代码也可以写在一个独立文件中,然后用<img>
、<object>
、<embed>
、<iframe>
等标签插入网页。
CSS 也可以使用 SVG 文件。
SVG 文件还可以转为 BASE64 编码,然后作为 Data URI 写入网页。
二、语法
2.1 <svg>
标签
SVG 代码都放在顶层标签<svg>
之中。下面是一个例子。
<svg>
的width
属性和height
属性,指定了 SVG 图像在 HTML 元素中所占据的宽度和高度。除了相对单位,也可以采用绝对单位(单位:像素)。如果不指定这两个属性,SVG 图像默认大小是300像素(宽) x 150像素(高)。
如果只想展示 SVG 图像的一部分,就要指定viewBox
属性。
<viewBox>
属性的值有四个数字,分别是左上角的横坐标和纵坐标、视口的宽度和高度。上面代码中,SVG 图像是100像素宽 x 100像素高,viewBox
属性指定视口从(50, 50)
这个点开始。所以,实际看到的是右下角的四分之一圆。
注意,视口必须适配所在的空间。上面代码中,视口的大小是 50 x 50,由于 SVG 图像的大小是 100 x 100,所以视口会放大去适配 SVG 图像的大小,即放大了四倍。
如果不指定width
属性和height
属性,只指定viewBox
属性,则相当于只给定 SVG 图像的长宽比。这时,SVG 图像的默认大小将等于所在的 HTML 元素的大小。
2.2 <circle>
标签
<circle>
标签代表圆形。
上面的代码定义了三个圆。<circle>
标签的cx
、cy
、r
属性分别为横坐标、纵坐标和半径,单位为像素。坐标都是相对于<svg>
画布的左上角原点。
class
属性用来指定对应的 CSS 类。
SVG 的 CSS 属性与网页元素有所不同。
- fill:填充色
- stroke:描边色
- stroke-width:边框宽度
2.3 <line>
标签
<line>
标签用来绘制直线。
上面代码中,<line>
标签的x1
属性和y1
属性,表示线段起点的横坐标和纵坐标;x2
属性和y2
属性,表示线段终点的横坐标和纵坐标;style
属性表示线段的样式。
2.4 <polyline>
标签
<polyline>
标签用于绘制一根折线。
<polyline>
的points
属性指定了每个端点的坐标,横坐标与纵坐标之间与逗号分隔,点与点之间用空格分隔。
2.5 <rect>
标签
<rect>
标签用于绘制矩形。
<rect>
的x
属性和y
属性,指定了矩形左上角端点的横坐标和纵坐标;width
属性和height
属性指定了矩形的宽度和高度(单位像素)。
2.6 <ellipse>
标签
<ellipse>
标签用于绘制椭圆。
<ellipse>
的cx
属性和cy
属性,指定了椭圆中心的横坐标和纵坐标(单位像素);rx
属性和ry
属性,指定了椭圆横向轴和纵向轴的半径(单位像素)。
2.7 <polygon>
标签
<polygon>
标签用于绘制多边形。
<polygon>
的points
属性指定了每个端点的坐标,横坐标与纵坐标之间与逗号分隔,点与点之间用空格分隔。
2.8 <path>
标签
<path>
标签用于制路径。
<path>
的d
属性表示绘制顺序,它的值是一个长字符串,每个字母表示一个绘制动作,后面跟着坐标。
- M:移动到(moveto)
- L:画直线到(lineto)
- Z:闭合路径
2.9 <text>
标签
<text>
标签用于绘制文本。
<text>
的x
属性和y
属性,表示文本区块基线(baseline)起点的横坐标和纵坐标。文字的样式可以用class
或style
属性指定。
2.10 <use>
标签
<use>
标签用于复制一个形状。
<use>
的href
属性指定所要复制的节点,x
属性和y
属性是<use>
左上角的坐标。另外,还可以指定width
和height
坐标。
2.11 <g>
标签
<g>
标签用于将多个形状组成一个组(group),方便复用。
2.12 <defs>
标签
<defs>
标签用于自定义形状,它内部的代码不会显示,仅供引用。
2.13 <pattern>
标签
<pattern>
标签用于自定义一个形状,该形状可以被引用来平铺一个区域。
上面代码中,<pattern>
标签将一个圆形定义为dots
模式。patternUnits="userSpaceOnUse"
表示<pattern>
的宽度和长度是实际的像素值。然后,指定这个模式去填充下面的矩形。
2.14 <image>
标签
<image>
标签用于插入图片文件。
上面代码中,<image>
的xlink:href
属性表示图像的来源。
2.15 <animate>
标签
<animate>
标签用于产生动画效果。
上面代码中,矩形会不断移动,产生动画效果。
<animate>
的属性含义如下。
- attributeName:发生动画效果的属性名。
- from:单次动画的初始值。
- to:单次动画的结束值。
- dur:单次动画的持续时间。
- repeatCount:动画的循环模式。
可以在多个属性上面定义动画。
2.16 <animateTransform>
标签
<animate>
标签对 CSS 的transform
属性不起作用,如果需要变形,就要使用<animateTransform>
标签。
上面代码中,<animateTransform>
的效果为旋转(rotate
),这时from
和to
属性值有三个数字,第一个数字是角度值,第二个值和第三个值是旋转中心的坐标。from="0 200 200"
表示开始时,角度为0,围绕(200, 200)
开始旋转;to="360 400 400"
表示结束时,角度为360,围绕(400, 400)
旋转。
三、JavaScript 操作
3.1 DOM 操作
如果 SVG 代码直接写在 HTML 网页之中,它就成为网页 DOM 的一部分,可以直接用 DOM 操作。
上面代码插入网页之后,就可以用 CSS 定制样式。
然后,可以用 JavaScript 代码操作 SVG。
上面代码指定,如果点击图形,就改写circle
元素的r
属性。
3.2 获取 SVG DOM
使用<object>
、<iframe>
、<embed>
标签插入 SVG 文件,可以获取 SVG DOM。
注意,如果使用<img>
标签插入 SVG 文件,就无法获取 SVG DOM。
3.3 读取 SVG 源码
由于 SVG 文件就是一段 XML 文本,因此可以通过读取 XML 代码的方式,读取 SVG 源码。
使用XMLSerializer
实例的serializeToString()
方法,获取 SVG 元素的代码。
3.4 SVG 图像转为 Canvas 图像
首先,需要新建一个Image
对象,将 SVG 图像指定到该Image
对象的src
属性。
然后,当图像加载完成后,再将它绘制到<canvas>
元素。
四、实例:折线图
下面将一张数据表格画成折线图。
上面的图形,可以画成一个坐标系,Date
作为横轴,Amount
作为纵轴,四行数据画成一个数据点。
参考二
介绍
尽管在 21 世纪初被标准化了,SVG(Scalable Vector Graphics的缩写)是近年来的一个热门话题。
SVG 已经被糟糕的浏览器支持(尤其是 IE)惩罚了好多年。
我发现这话源自一本 2011 的书:在撰写本文时,只有在最新的浏览器中才能将 SVG 直接嵌入到 HTML 中工作。7 年过去了,这句话现在已经是过去式了,我们可以很安全地使用 SVG 图像。
现在我们可以安全地使用 SVG 图像,除非您有很多用户使用 IE8 以及更低版本,或者使用较旧的 Android 设备。这种情况下,依然存在着备选方案。
SVG 支持的浏览器
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 图像示例:
<svg width="10" height="10"> <rect x="0" y="0" width="10" height="10" fill="blue" /></svg>
- 1
注意它非常容易阅读和理解图像的样子:它是一个 10 x 10 像素的简单蓝色矩形(默认单元)。
大多情况下,您不必编写 SVG 代码,因为您可以使用 Sketch 或 Figma 等工具或任何其他矢量图形工具来创建图像,并将其导出为 SVG。
SVG 的当前版本是 1.1, SVG 2.0 正在研发。
使用 SVG
浏览器可以通过将它们包含在一个img
标签中来显示 SVG 图像:
<img src="image.svg" alt="My SVG image" />
- 1
就像其他基于像素的图像格式一样:
<img src="image.png" alt="My PNG image" /><img src="image.jpg" alt="My JPG image" /><img src="image.gif" alt="My GIF image" /><img src="image.webp" alt="My WebP image" />
- 1
此外,SVG 非常独特,它们可以直接包含在 HTML 页面中:
<!DOCTYPE html><html> <head> <title>A page</title> </head> <body> <svg width="10" height="10"> <rect x="0" y="0" width="10" height="10" fill="blue" /> </svg> </body></html>
- 1
请注意 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> <text x="5" y="30">A nice rectangle</text></svg>
- 1
漂亮的长方形
circle
定义圆。cx
和cy
是中心坐标,r
是半径。fill
是一个常用属性,表示图形颜色。
<svg> <circle cx="50" cy="50" r="50" fill="#529fca" /></svg>
- 1
rect
定义矩形。x
,y
是起始坐标,width
和height
是自解释的。
<svg> <rect x="0" y="0" width="100" height="100" fill="#529fca" /></svg>
- 1
line
x1
和y1
定义起始坐标。x2
和y2
定义结束坐标。stroke
是一个常用属性,表示线条颜色。
<svg> <line x1="0" y1="0" x2="100" y2="100" stroke="#529fca" /></svg>
- 1
path
路径是一系列的直线和曲线。它是所有 SVG 绘制工具中最强大的,因此也是最复杂的。
d
包含方向命令。这些命令以命令名和一组坐标开始:
-
M
表示移动,它接受一组 x,y 坐标 -
L
表示直线将绘制到它接受一组 x,y -
H
是一条水平线,它只接受 x 坐标 -
V
是一条垂直线,它只接受 y 坐标 -
Z
表示关闭路径,并将其放回起始位置 -
A
表示 Arch,它自己需要一个完整的教程 -
Q
是一条二次 Bezier 曲线,同样,它自己也需要一个完整的教程<svg height="300" width="300"> <path d="M 100 100 L 200 200 H 10 V 40 H 70" fill="#59fa81" stroke="#d85b49" stroke-width="3" /> </svg>
- 1
textPath
沿路径元素的形状添加文本。
Wow such a nice SVG tut
- 1
polygon
使用polygon
绘制任意多边形。points
代表一组 x,y 坐标多边形应该链接:
<svg> <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" /></svg>
- 1
g
使用g
元素,您可以对多个元素进行分组:
<svg width="200" height="200"> <rect x="0" y="0" width="100" height="100" fill="#529fca" /> <g id="my-group"> <rect x="0" y="100" width="100" height="100" fill="#59fa81" /> <rect x="100" y="0" width="100" height="100" fill="#59fa81" /> </g></svg>
- 1
SVG viewport 和 viewBox
SVG 相对于其容器的大小由svg
元素的width
和height
属性设置。这些单位默认为像素,但您可以使用任何其他常用单位,如%
或em
。这是viewport。
通常 “container” 指的是浏览器窗口,但
svg
元素可以包含其他svg
元素,在这种情况下,容器是父元素svg
。
一个重要的属性是viewBox
。它允许您在 SVG 画布中定义一个新的坐标系统。
假设在 200x200px SVG 中有一个简单的圆:
<svg width="200" height="200"> <circle cx="100" cy="100" r="100" fill="#529fca" /></svg>
- 1
通过指定viewBox,您可以选择只显示此 SVG 的一部分。例如,您可以从 0,0 点开始,只显示一个 100 x 100 px 画布:
<svg width="200" height="200" viewBox="0 0 100 100"> <circle cx="100" cy="100" r="100" fill="#529fca" /></svg>
- 1
从 100,100 开始,您会看到另一部分,圆圈的右下角:
<svg width="200" height="200" viewBox="100 100 100 100"> <circle cx="100" cy="100" r="100" fill="#529fca" /></svg>
- 1
一个很好的可视化方法是想象 Google Maps 是一个巨大的 SVG 图像,而您的浏览器是一个和窗口大小一样大的视图框。当您移动时,Viewbox 会更改它的起始点(x,y)坐标,并且当您调整窗口的大小时,会更改 Viewbox 的宽度和高度。
在 Web 网页中插入 SVG
将 SVG 添加到网页中有多种方法。
最常见的是:
-
带有
img
标签 -
带有 CSS
background-image
属性 -
在 HTML 中内联
-
带有
object
、iframe
或embed
标签
在 Glitch 上可以查看这些示例flavio-svg-loading-ways.glitch.me/
带有img
标签
<img src="flag.svg" alt="Flag" />
- 1
带有 cssbackground-image
属性
<style>.svg-background { background-image: url(flag.svg); height: 200px; width: 300px;}</style><div class="svg-background"></div>
- 1
在 HTML 中内联
<svg width="300" height="200" viewBox="0 0 300 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <title>Italian Flag</title> <desc>By Flavio Copes https://flaviocopes.com</desc> <g id="flag"> <rect fill="green" x="0" y="0" width="100" height="200"></rect> <rect fill="white" x="100" y="0" width="100" height="200"></rect> <rect fill="red" x="200" y="0" width="100" height="200"></rect> </g></svg>
- 1
带有object
、iframe
或embed
标签
- 1
使用embed
,您可以使用以下命令从父文档获取 SVG 文档
document.getElementById('my-svg-embed').getSVGDocument()
- 1
在 SVG 内部,您可以通过以下方式引用父文档:
window.parent.document
- 1
使用数据 URL 内联 SVG
您可以使用以上任何示例结合Data URLs将 SVG 内联到 HTML 中:
<img src="data:image/svg+xml;<DATA>" alt="Flag" /><object data="data:image/svg+xml;<DATA>"type="image/svg+xml"></object><iframe data="data:image/svg+xml;<DATA>" frameborder="0"></iframe>
- 1
在 CSS 中也是:
.svg-background { background-image: url("data:image/svg+xml;<DATA>");}
- 1
只需使用适当的Data URL更改<DATA>
。
样式元素
任何 SVG 元素都可以接受style
属性,就像 HTML标签一样。并非所有的 CSS 属性都能像您预期的那样工作。例如,要更改文本元素的颜色,请使用fill
而不是color
。
<svg> <text x="5" y="30" style="fill: green">A nice text</text></svg><svg> <text x="5" y="70" style="fill: green; font-family: Courier New"> A nice text </text></svg>
- 1
您也可以使用fill
作为元素属性,正如您在前面看到的那样:
<svg> <text x="5" y="70" fill="green">A nice text</text></svg>
- 1
其他公共属性包括
-
fill-opacity
,背景颜色不透明度 -
stroke
,定义边框颜色 -
stroke-width
,设置边框宽度
CSS 可以针对 SVG 元素,就像您以 HTML 标签为目标一样:
rect { fill: red;}circle { fill: blue;}
- 1
使用 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:
- 1
- 2
- 3
SVG 文件还可以包括外部样式表
<?xml version="1.0" standalone="no"?><?xml-stylesheet type="text/css" href="style.css"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width=".." height=".." viewBox=".."> <rect id="my-rect" x="0" y="0" width="10" height="10" /></svg>
- 1
JavaScript 嵌入 SVG
你可以将 JavaScript 放在第一个位置上,并包装在一个load
事件中,以便在页面完全加载并在 DOM 中插入 SVG 时执行它:
<svg> <script> <![CDATA[ window.addEventListener("load", () => { //... }, false) ]]> </script> <rect x="0" y="0" width="10" height="10" fill="blue" /></svg>
- 1
或者如果您将 JS 放在其他 SVG 代码的末尾,可以避免添加事件监听,确保当 SVG 出现在页面时 JavaSCript 会执行。
<svg> <rect x="0" y="0" width="10" height="10" fill="blue" /> <script> <![CDATA[ //... ]]> </script></svg>
- 1
与 HTML 元素一样,SVG 元素也可以有id
和class
属性,因此我们可以使用Selectors API来引用它们:
<svg> <rect x="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>
- 1
请查看此故障flaviocopes-svg-script.glitch.me/以获得功能性提示。
SVG 外部的 JavaScript
如果可以与 SVG 交互(SVG 在 HTML 中是内联的),则可以使用 JavaScript 更改任何 SVG 属性,例如:
document.getElementById("my-svg-rect").setAttribute("fill", "black")
- 1
或者真正地做任何您想要的DOM操作。
SVG 外部的 CSS
您可以使用 CSS 更改 SVG 图像的任何样式。
SVG 属性可以很容易地在 CSS中 被覆盖,并且它们比 CSS 具有更低的优先级。它们的行为不像具有更高优先级的内联 CSS。
<style> #my-rect { fill: red }</style><svg> <rect x="0" y="0" width="10" height="10" fill="blue" id="my-rect" /></svg>
- 1
SVG vs Canvas API
Canvas API 是 Web 平台一个很好的补充,它有类似于 SVG 的浏览器支持。与 SVG 主要的(也是最大的)不同之处是:画布不是基于矢量的,而是基于像素的,所以
-
它具有与基于像素的 png、jpg 和 gif 图像格式相同的缩放问题。
-
这使得不可能像使用 SVG 那样使用 CSS 或 JavaScropt 编辑画布图像。
SVG 符号
符号使您可以定义一次SVG图像,并在多个地方重用它。如果您需要重用一个图像,这是一个很大的帮助,可能只是改变一点它的一些属性。
您可以通过添加一个symbol
元素并分配一个id
属性来完成此操作:
<svg class="hidden"> <symbol id="rectangle" viewBox="0 0 20 20"> <rect x="0" y="0" width="300" height="300" fill="rgb(255,159,0)" /> </symbol></svg><svg> <use xlink:href="#rectangle" href="#rectangle" /></svg><svg> <use xlink:href="#rectangle" href="#rectangle" /></svg>
- 1
(xlink:href
用于 Safari 支持,即使它是一个已废弃的属性)
这让我们能开始了解 SVG 的强大功能。
如果您希望对这两个矩形使用不同的样式,例如,对每个矩形使用不同的颜色?您可以使用CSS 变量.
<svg class="hidden"> <symbol id="rectangle" viewBox="0 0 20 20"> <rect x="0" y="0" width="300" height="300" fill="var(--color)" /> </symbol></svg><svg class="blue"> <use xlink:href="#rectangle" href="#rectangle" /></svg><svg class="red"> <use xlink:href="#rectangle" href="#rectangle" /></svg><style>svg.red { --color: red;}svg.blue { --color: blue;}</style>
- 1
查看 SVG 符号—我的 Glitch playground。
验证 SVG
SVG 文件是 XML,可以用无效的格式编写,有些服务或应用程序可能不接受无效的 SVG 文件。
SVG 可以使用W3C Validator验证。
我应该包含xmlns
属性么?
有时 SVG 别定义为
<svg> ...</svg>
- 1
有时定义为
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"> ...</svg>
- 1
第二个表单是 XHTML。它可以与 HTML5 一起使用(文档具有<!DOCTYPE html>
),但在本例中,第一种形式更简单。
我应该担心浏览器支持问题么?
在 2018 版本中,绝大多数用户的浏览器都支持 SVG。.
您仍然可以使用诸如Modernizr这样的库来检查缺少的支持,并提供一个后备:
if (!Modernizr.svg) { $(".my-svg").attr("src", "images/logo.png");}转自CSDN,原链接https://blog.csdn.net/weixin_41646716/article/details/89335639,原作者歪歪100
SVG 在线画图工具:https://svg.haowen100.com/
把画的图片代码保存成svg文件,加载
http://www.bejson.com/convert/image_to_svg/
https://www.aconvert.com/cn/image/png-to-svg/
参考一
SVG 是一种基于 XML 语法的图像格式,全称是可缩放矢量图(Scalable Vector Graphics)。其他图像格式都是基于像素处理的,SVG 则是属于对图像的形状描述,所以它本质上是文本文件,体积较小,且不管放大多少倍都不会失真。
SVG 文件可以直接插入网页,成为 DOM 的一部分,然后用 JavaScript 和 CSS 进行操作。
上面是 SVG 代码直接插入网页的例子。
SVG 代码也可以写在一个独立文件中,然后用<img>
、<object>
、<embed>
、<iframe>
等标签插入网页。
CSS 也可以使用 SVG 文件。
SVG 文件还可以转为 BASE64 编码,然后作为 Data URI 写入网页。
二、语法
2.1 <svg>
标签
SVG 代码都放在顶层标签<svg>
之中。下面是一个例子。
<svg>
的width
属性和height
属性,指定了 SVG 图像在 HTML 元素中所占据的宽度和高度。除了相对单位,也可以采用绝对单位(单位:像素)。如果不指定这两个属性,SVG 图像默认大小是300像素(宽) x 150像素(高)。
如果只想展示 SVG 图像的一部分,就要指定viewBox
属性。
<viewBox>
属性的值有四个数字,分别是左上角的横坐标和纵坐标、视口的宽度和高度。上面代码中,SVG 图像是100像素宽 x 100像素高,viewBox
属性指定视口从(50, 50)
这个点开始。所以,实际看到的是右下角的四分之一圆。
注意,视口必须适配所在的空间。上面代码中,视口的大小是 50 x 50,由于 SVG 图像的大小是 100 x 100,所以视口会放大去适配 SVG 图像的大小,即放大了四倍。
如果不指定width
属性和height
属性,只指定viewBox
属性,则相当于只给定 SVG 图像的长宽比。这时,SVG 图像的默认大小将等于所在的 HTML 元素的大小。
2.2 <circle>
标签
<circle>
标签代表圆形。
上面的代码定义了三个圆。<circle>
标签的cx
、cy
、r
属性分别为横坐标、纵坐标和半径,单位为像素。坐标都是相对于<svg>
画布的左上角原点。
class
属性用来指定对应的 CSS 类。
SVG 的 CSS 属性与网页元素有所不同。
- fill:填充色
- stroke:描边色
- stroke-width:边框宽度
2.3 <line>
标签
<line>
标签用来绘制直线。
上面代码中,<line>
标签的x1
属性和y1
属性,表示线段起点的横坐标和纵坐标;x2
属性和y2
属性,表示线段终点的横坐标和纵坐标;style
属性表示线段的样式。
2.4 <polyline>
标签
<polyline>
标签用于绘制一根折线。
<polyline>
的points
属性指定了每个端点的坐标,横坐标与纵坐标之间与逗号分隔,点与点之间用空格分隔。
2.5 <rect>
标签
<rect>
标签用于绘制矩形。
<rect>
的x
属性和y
属性,指定了矩形左上角端点的横坐标和纵坐标;width
属性和height
属性指定了矩形的宽度和高度(单位像素)。
2.6 <ellipse>
标签
<ellipse>
标签用于绘制椭圆。
<ellipse>
的cx
属性和cy
属性,指定了椭圆中心的横坐标和纵坐标(单位像素);rx
属性和ry
属性,指定了椭圆横向轴和纵向轴的半径(单位像素)。
2.7 <polygon>
标签
<polygon>
标签用于绘制多边形。
<polygon>
的points
属性指定了每个端点的坐标,横坐标与纵坐标之间与逗号分隔,点与点之间用空格分隔。
2.8 <path>
标签
<path>
标签用于制路径。
<path>
的d
属性表示绘制顺序,它的值是一个长字符串,每个字母表示一个绘制动作,后面跟着坐标。
- M:移动到(moveto)
- L:画直线到(lineto)
- Z:闭合路径
2.9 <text>
标签
<text>
标签用于绘制文本。
<text>
的x
属性和y
属性,表示文本区块基线(baseline)起点的横坐标和纵坐标。文字的样式可以用class
或style
属性指定。
2.10 <use>
标签
<use>
标签用于复制一个形状。
<use>
的href
属性指定所要复制的节点,x
属性和y
属性是<use>
左上角的坐标。另外,还可以指定width
和height
坐标。
2.11 <g>
标签
<g>
标签用于将多个形状组成一个组(group),方便复用。
2.12 <defs>
标签
<defs>
标签用于自定义形状,它内部的代码不会显示,仅供引用。
2.13 <pattern>
标签
<pattern>
标签用于自定义一个形状,该形状可以被引用来平铺一个区域。
上面代码中,<pattern>
标签将一个圆形定义为dots
模式。patternUnits="userSpaceOnUse"
表示<pattern>
的宽度和长度是实际的像素值。然后,指定这个模式去填充下面的矩形。
2.14 <image>
标签
<image>
标签用于插入图片文件。
上面代码中,<image>
的xlink:href
属性表示图像的来源。
2.15 <animate>
标签
<animate>
标签用于产生动画效果。
上面代码中,矩形会不断移动,产生动画效果。
<animate>
的属性含义如下。
- attributeName:发生动画效果的属性名。
- from:单次动画的初始值。
- to:单次动画的结束值。
- dur:单次动画的持续时间。
- repeatCount:动画的循环模式。
可以在多个属性上面定义动画。
2.16 <animateTransform>
标签
<animate>
标签对 CSS 的transform
属性不起作用,如果需要变形,就要使用<animateTransform>
标签。
上面代码中,<animateTransform>
的效果为旋转(rotate
),这时from
和to
属性值有三个数字,第一个数字是角度值,第二个值和第三个值是旋转中心的坐标。from="0 200 200"
表示开始时,角度为0,围绕(200, 200)
开始旋转;to="360 400 400"
表示结束时,角度为360,围绕(400, 400)
旋转。
三、JavaScript 操作
3.1 DOM 操作
如果 SVG 代码直接写在 HTML 网页之中,它就成为网页 DOM 的一部分,可以直接用 DOM 操作。
上面代码插入网页之后,就可以用 CSS 定制样式。
然后,可以用 JavaScript 代码操作 SVG。
上面代码指定,如果点击图形,就改写circle
元素的r
属性。
3.2 获取 SVG DOM
使用<object>
、<iframe>
、<embed>
标签插入 SVG 文件,可以获取 SVG DOM。
注意,如果使用<img>
标签插入 SVG 文件,就无法获取 SVG DOM。
3.3 读取 SVG 源码
由于 SVG 文件就是一段 XML 文本,因此可以通过读取 XML 代码的方式,读取 SVG 源码。
使用XMLSerializer
实例的serializeToString()
方法,获取 SVG 元素的代码。
3.4 SVG 图像转为 Canvas 图像
首先,需要新建一个Image
对象,将 SVG 图像指定到该Image
对象的src
属性。
然后,当图像加载完成后,再将它绘制到<canvas>
元素。
四、实例:折线图
下面将一张数据表格画成折线图。
上面的图形,可以画成一个坐标系,Date
作为横轴,Amount
作为纵轴,四行数据画成一个数据点。
参考二
介绍
尽管在 21 世纪初被标准化了,SVG(Scalable Vector Graphics的缩写)是近年来的一个热门话题。
SVG 已经被糟糕的浏览器支持(尤其是 IE)惩罚了好多年。
我发现这话源自一本 2011 的书:在撰写本文时,只有在最新的浏览器中才能将 SVG 直接嵌入到 HTML 中工作。7 年过去了,这句话现在已经是过去式了,我们可以很安全地使用 SVG 图像。
现在我们可以安全地使用 SVG 图像,除非您有很多用户使用 IE8 以及更低版本,或者使用较旧的 Android 设备。这种情况下,依然存在着备选方案。
SVG 支持的浏览器
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 图像示例:
<svg width="10" height="10"> <rect x="0" y="0" width="10" height="10" fill="blue" /></svg>
- 1
注意它非常容易阅读和理解图像的样子:它是一个 10 x 10 像素的简单蓝色矩形(默认单元)。
大多情况下,您不必编写 SVG 代码,因为您可以使用 Sketch 或 Figma 等工具或任何其他矢量图形工具来创建图像,并将其导出为 SVG。
SVG 的当前版本是 1.1, SVG 2.0 正在研发。
使用 SVG
浏览器可以通过将它们包含在一个img
标签中来显示 SVG 图像:
<img src="image.svg" alt="My SVG image" />
- 1
就像其他基于像素的图像格式一样:
<img src="image.png" alt="My PNG image" /><img src="image.jpg" alt="My JPG image" /><img src="image.gif" alt="My GIF image" /><img src="image.webp" alt="My WebP image" />
- 1
此外,SVG 非常独特,它们可以直接包含在 HTML 页面中:
<!DOCTYPE html><html> <head> <title>A page</title> </head> <body> <svg width="10" height="10"> <rect x="0" y="0" width="10" height="10" fill="blue" /> </svg> </body></html>
- 1
请注意 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> <text x="5" y="30">A nice rectangle</text></svg>
- 1
漂亮的长方形
circle
定义圆。cx
和cy
是中心坐标,r
是半径。fill
是一个常用属性,表示图形颜色。
<svg> <circle cx="50" cy="50" r="50" fill="#529fca" /></svg>
- 1
rect
定义矩形。x
,y
是起始坐标,width
和height
是自解释的。
<svg> <rect x="0" y="0" width="100" height="100" fill="#529fca" /></svg>
- 1
line
x1
和y1
定义起始坐标。x2
和y2
定义结束坐标。stroke
是一个常用属性,表示线条颜色。
<svg> <line x1="0" y1="0" x2="100" y2="100" stroke="#529fca" /></svg>
- 1
path
路径是一系列的直线和曲线。它是所有 SVG 绘制工具中最强大的,因此也是最复杂的。
d
包含方向命令。这些命令以命令名和一组坐标开始:
-
M
表示移动,它接受一组 x,y 坐标 -
L
表示直线将绘制到它接受一组 x,y -
H
是一条水平线,它只接受 x 坐标 -
V
是一条垂直线,它只接受 y 坐标 -
Z
表示关闭路径,并将其放回起始位置 -
A
表示 Arch,它自己需要一个完整的教程 -
Q
是一条二次 Bezier 曲线,同样,它自己也需要一个完整的教程<svg height="300" width="300"> <path d="M 100 100 L 200 200 H 10 V 40 H 70" fill="#59fa81" stroke="#d85b49" stroke-width="3" /> </svg>
- 1
textPath
沿路径元素的形状添加文本。
Wow such a nice SVG tut
- 1
polygon
使用polygon
绘制任意多边形。points
代表一组 x,y 坐标多边形应该链接:
<svg> <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" /></svg>
- 1
g
使用g
元素,您可以对多个元素进行分组:
<svg width="200" height="200"> <rect x="0" y="0" width="100" height="100" fill="#529fca" /> <g id="my-group"> <rect x="0" y="100" width="100" height="100" fill="#59fa81" /> <rect x="100" y="0" width="100" height="100" fill="#59fa81" /> </g></svg>
- 1
SVG viewport 和 viewBox
SVG 相对于其容器的大小由svg
元素的width
和height
属性设置。这些单位默认为像素,但您可以使用任何其他常用单位,如%
或em
。这是viewport。
通常 “container” 指的是浏览器窗口,但
svg
元素可以包含其他svg
元素,在这种情况下,容器是父元素svg
。
一个重要的属性是viewBox
。它允许您在 SVG 画布中定义一个新的坐标系统。
假设在 200x200px SVG 中有一个简单的圆:
<svg width="200" height="200"> <circle cx="100" cy="100" r="100" fill="#529fca" /></svg>
- 1
通过指定viewBox,您可以选择只显示此 SVG 的一部分。例如,您可以从 0,0 点开始,只显示一个 100 x 100 px 画布:
<svg width="200" height="200" viewBox="0 0 100 100"> <circle cx="100" cy="100" r="100" fill="#529fca" /></svg>
- 1
从 100,100 开始,您会看到另一部分,圆圈的右下角:
<svg width="200" height="200" viewBox="100 100 100 100"> <circle cx="100" cy="100" r="100" fill="#529fca" /></svg>
- 1
一个很好的可视化方法是想象 Google Maps 是一个巨大的 SVG 图像,而您的浏览器是一个和窗口大小一样大的视图框。当您移动时,Viewbox 会更改它的起始点(x,y)坐标,并且当您调整窗口的大小时,会更改 Viewbox 的宽度和高度。
在 Web 网页中插入 SVG
将 SVG 添加到网页中有多种方法。
最常见的是:
-
带有
img
标签 -
带有 CSS
background-image
属性 -
在 HTML 中内联
-
带有
object
、iframe
或embed
标签
在 Glitch 上可以查看这些示例flavio-svg-loading-ways.glitch.me/
带有img
标签
<img src="flag.svg" alt="Flag" />
- 1
带有 cssbackground-image
属性
<style>.svg-background { background-image: url(flag.svg); height: 200px; width: 300px;}</style><div class="svg-background"></div>
- 1
在 HTML 中内联
<svg width="300" height="200" viewBox="0 0 300 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <title>Italian Flag</title> <desc>By Flavio Copes https://flaviocopes.com</desc> <g id="flag"> <rect fill="green" x="0" y="0" width="100" height="200"></rect> <rect fill="white" x="100" y="0" width="100" height="200"></rect> <rect fill="red" x="200" y="0" width="100" height="200"></rect> </g></svg>
- 1
带有object
、iframe
或embed
标签
- 1
使用embed
,您可以使用以下命令从父文档获取 SVG 文档
document.getElementById('my-svg-embed').getSVGDocument()
- 1
在 SVG 内部,您可以通过以下方式引用父文档:
window.parent.document
- 1
使用数据 URL 内联 SVG
您可以使用以上任何示例结合Data URLs将 SVG 内联到 HTML 中:
<img src="data:image/svg+xml;<DATA>" alt="Flag" /><object data="data:image/svg+xml;<DATA>"type="image/svg+xml"></object><iframe data="data:image/svg+xml;<DATA>" frameborder="0"></iframe>
- 1
在 CSS 中也是:
.svg-background { background-image: url("data:image/svg+xml;<DATA>");}
- 1
只需使用适当的Data URL更改<DATA>
。
样式元素
任何 SVG 元素都可以接受style
属性,就像 HTML标签一样。并非所有的 CSS 属性都能像您预期的那样工作。例如,要更改文本元素的颜色,请使用fill
而不是color
。
<svg> <text x="5" y="30" style="fill: green">A nice text</text></svg><svg> <text x="5" y="70" style="fill: green; font-family: Courier New"> A nice text </text></svg>
- 1
您也可以使用fill
作为元素属性,正如您在前面看到的那样:
<svg> <text x="5" y="70" fill="green">A nice text</text></svg>
- 1
其他公共属性包括
-
fill-opacity
,背景颜色不透明度 -
stroke
,定义边框颜色 -
stroke-width
,设置边框宽度
CSS 可以针对 SVG 元素,就像您以 HTML 标签为目标一样:
rect { fill: red;}circle { fill: blue;}
- 1
使用 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:
- 1
- 2
- 3
SVG 文件还可以包括外部样式表
<?xml version="1.0" standalone="no"?><?xml-stylesheet type="text/css" href="style.css"?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width=".." height=".." viewBox=".."> <rect id="my-rect" x="0" y="0" width="10" height="10" /></svg>
- 1
JavaScript 嵌入 SVG
你可以将 JavaScript 放在第一个位置上,并包装在一个load
事件中,以便在页面完全加载并在 DOM 中插入 SVG 时执行它:
<svg> <script> <![CDATA[ window.addEventListener("load", () => { //... }, false) ]]> </script> <rect x="0" y="0" width="10" height="10" fill="blue" /></svg>
- 1
或者如果您将 JS 放在其他 SVG 代码的末尾,可以避免添加事件监听,确保当 SVG 出现在页面时 JavaSCript 会执行。
<svg> <rect x="0" y="0" width="10" height="10" fill="blue" /> <script> <![CDATA[ //... ]]> </script></svg>
- 1
与 HTML 元素一样,SVG 元素也可以有id
和class
属性,因此我们可以使用Selectors API来引用它们:
<svg> <rect x="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>
- 1
请查看此故障flaviocopes-svg-script.glitch.me/以获得功能性提示。
SVG 外部的 JavaScript
如果可以与 SVG 交互(SVG 在 HTML 中是内联的),则可以使用 JavaScript 更改任何 SVG 属性,例如:
document.getElementById("my-svg-rect").setAttribute("fill", "black")
- 1
或者真正地做任何您想要的DOM操作。
SVG 外部的 CSS
您可以使用 CSS 更改 SVG 图像的任何样式。
SVG 属性可以很容易地在 CSS中 被覆盖,并且它们比 CSS 具有更低的优先级。它们的行为不像具有更高优先级的内联 CSS。
<style> #my-rect { fill: red }</style><svg> <rect x="0" y="0" width="10" height="10" fill="blue" id="my-rect" /></svg>
- 1
SVG vs Canvas API
Canvas API 是 Web 平台一个很好的补充,它有类似于 SVG 的浏览器支持。与 SVG 主要的(也是最大的)不同之处是:画布不是基于矢量的,而是基于像素的,所以
-
它具有与基于像素的 png、jpg 和 gif 图像格式相同的缩放问题。
-
这使得不可能像使用 SVG 那样使用 CSS 或 JavaScropt 编辑画布图像。
SVG 符号
符号使您可以定义一次SVG图像,并在多个地方重用它。如果您需要重用一个图像,这是一个很大的帮助,可能只是改变一点它的一些属性。
您可以通过添加一个symbol
元素并分配一个id
属性来完成此操作:
<svg class="hidden"> <symbol id="rectangle" viewBox="0 0 20 20"> <rect x="0" y="0" width="300" height="300" fill="rgb(255,159,0)" /> </symbol></svg><svg> <use xlink:href="#rectangle" href="#rectangle" /></svg><svg> <use xlink:href="#rectangle" href="#rectangle" /></svg>
- 1
(xlink:href
用于 Safari 支持,即使它是一个已废弃的属性)
这让我们能开始了解 SVG 的强大功能。
如果您希望对这两个矩形使用不同的样式,例如,对每个矩形使用不同的颜色?您可以使用CSS 变量.
<svg class="hidden"> <symbol id="rectangle" viewBox="0 0 20 20"> <rect x="0" y="0" width="300" height="300" fill="var(--color)" /> </symbol></svg><svg class="blue"> <use xlink:href="#rectangle" href="#rectangle" /></svg><svg class="red"> <use xlink:href="#rectangle" href="#rectangle" /></svg><style>svg.red { --color: red;}svg.blue { --color: blue;}</style>
- 1
查看 SVG 符号—我的 Glitch playground。
验证 SVG
SVG 文件是 XML,可以用无效的格式编写,有些服务或应用程序可能不接受无效的 SVG 文件。
SVG 可以使用W3C Validator验证。
我应该包含xmlns
属性么?
有时 SVG 别定义为
<svg> ...</svg>
- 1
有时定义为
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"> ...</svg>
- 1
第二个表单是 XHTML。它可以与 HTML5 一起使用(文档具有<!DOCTYPE html>
),但在本例中,第一种形式更简单。
我应该担心浏览器支持问题么?
在 2018 版本中,绝大多数用户的浏览器都支持 SVG。.
您仍然可以使用诸如Modernizr这样的库来检查缺少的支持,并提供一个后备:
if (!Modernizr.svg) { $(".my-svg").attr("src", "images/logo.png");}来源:掘金,原链接https://blog.csdn.net/weixin_41646716/article/details/89335639,原作者歪歪100
https://blog.csdn.net/weixin_41646716
来源:https://www.cnblogs.com/GenuisZ/p/12164989.html