prefacio
Este artículo documenta el aprendizaje sobre los conceptos básicos de SVG. Sobre el papel, es superficial, y si quieres saber esto, tienes que hacerlo. Ven, vela conmigo (§ •_•) §.
¿Qué es SVG?
svg es la abreviatura de Scalable Vector Graphics. El nombre completo es Scalable Vector Graphics. Es un formato gráfico en el que las formas se especifican en XML. Luego, el visor SVG procesa el XML.
Clasificación de gráficos en computadoras
Generalmente se puede dividir en dos categorías: mapas de bits, gráficos vectoriales. El mapa de bits (bitmap), también conocido como imagen de mapa de bits o imagen de trama, se compone de un solo punto llamado píxel (elemento de imagen). Por lo general, una foto es un mapa de bits. Se compone de puntos de píxeles. El diagrama vectorial es más como el relleno de posición de punto a punto, no hay concepto de resolución y la imagen se puede ampliar o reducir a voluntad sin distorsión.
ventajas de svg
[1] Se puede estirar infinitamente y la pantalla de impresión no se distorsiona
[2] Puede controlar svg como escribir código todos los días, casi sin costo de uso
[3] La huella es extremadamente pequeña (en relación con los mapas de bits) y se puede comprimir con gzip para comprimir aún más su tamaño
[4] SVG se representa mediante xml, y la esencia es dom
compatibilidad con svg
dibujo
[1] Método de referencia básico SVG
La visualización de SVG en navegadores web (como Chrome, Firefox e Internet Explorer) se puede realizar dirigiendo el navegador a la URL del archivo SVG, incrustando el SVG en una página HTML, usando elementos iframe, usando elementos img, etc. , hay cuatro formas de lograr la referencia 1: Usar el elemento iframe
<iframe :src="require('@/assets/data-show/banner/bt-image-09.png')" >
复制代码
2: Usar elemento img
<img class="s-left" :src="require('@/assets/data-show/banner/bt-image-09.png')" />
复制代码
3: Usar incrustar
<embed :src="require('@/assets/data-show/banner/bt-image-09.png')" pluginspage="http://www.adobe.com/svg/viewer/install/" />
复制代码
4: incrustar html directamente
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
</head>
<body>
<svg width="500" height="500" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
</svg>
</body>
</html>
复制代码
Cuál de los diversos métodos de cita elegir depende completamente de sus propias necesidades, y cada uno tiene sus propios méritos.
característica | SVG en línea | objeto/incrustar/iframe | imagen |
---|---|---|---|
Puede interactuar con los usuarios. | ✔ | ✔ | ✔ |
Animación de soporte | ✔ | ✔ | ✔ |
Puede ejecutar scripts js | ✔ | ✔ | ❌ |
Se puede programar externamente | ✔ | ❌ | ❌ |
[2] Atributos de línea SVG
Atributos | describir |
---|---|
llenar | Establecer el color de relleno de la forma |
opacidad de relleno | Establecer la opacidad de relleno de la forma |
carrera | Establece el color del trazo (línea) utilizado para dibujar el contorno de esta forma |
anchura del trazo | Establece el ancho del trazo (línea) utilizado para dibujar el contorno de esta forma |
trazo-dasharray | Establece el trazo (discontinuo) utilizado para delinear esta forma |
trazo-opacidad | 设置用于绘制此形状轮廓的笔触(直线)不透明度 |
【3】svg基本图形元素介绍
矩形:SVG <rect>
<rect x="10" y="10" height="100" width="100" style="stroke:#006600; fill: #00cc00"/>
复制代码
圆形:SVG <circle>
<circle cx="40" cy="40" r="24" style="stroke:#006600; fill:#00cc00"/>
复制代码
椭圆形:SVG <ellipse>
<ellipse cx="40" cy="40" rx="30" ry="15" style="stroke:#006600; fill:#00cc00"/>
复制代码
线段:SVG <line>
<line x1="0" y1="10" x2="0" y2="100" style="stroke:#006600;"></line>
复制代码
折线:SVG <polyline>
<polyline fill="none" stroke="black" points="20,100 40,60 70,80 100,20"/>
复制代码
多边形:SVG <polygon>
<polygon points="10,0 60,0 35,50" style="stroke:#660000; fill:#cc3333;"/>
复制代码
【4】创建svg坐标系统并构建完整图案
我们创建一个一个二维的坐标系统用 x
代表横轴,y
代表纵轴,单位默认像素(px)
。x增加位置右移,y增加位置下移。这和我们认知的笛卡尔坐标系相反。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>SVG</title>
<style type="text/css">
html, body {
height: 100%;
width: 100%;
background: #e9e9e9;
}
body {
margin: 0;
text-align: center;
}
.grid {
width: 500px;
height: 500px;
margin: 0 auto;
padding-top: 100px;
padding-left: 100px;
background-image: url('grid.png');
position: relative;
}
.grid::before {
content: "";
border-left: 1px solid #7c7cea;
position: absolute;
top: 0;
left: 100px;
width: 50px;
height: 600px;
}
.grid::after {
content: "";
border-top: 1px solid #7c7cea;
position: absolute;
top: 100px;
left: 0;
width: 600px;
height: 500px;
}
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
</style>
</head>
<body>
<div class="grid">
<svg version="1.1"
width="500" height="500"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<polyline class="right-ear" style="stroke:#583504; stroke-width: 3; fill:#fddb55" points="120,80 250,180 120,180 120,80"/>
<polyline class="left-ear" style="stroke:#583504; stroke-width: 3; fill:#fddb55" points="370,80 250,180 370,180 370,80"/>
<circle cx="250" cy="250" r="150" style="stroke:#583504; stroke-width: 3; fill:#fddb55"/>
<circle cx="183" cy="178" r="16" style="fill:#FFFFFF"/>
<circle cx="273" cy="180" r="18" style="fill:#FFFFFF"/>
<g class="right-eye">
<ellipse cx="170" cy="215" rx="45" ry="20" style="stroke:#583504; stroke-width: 3; fill:#FFFFFF"/>
<circle cx="185" cy="215" r="18" style="stroke:#583504; stroke-width: 1; fill:#583504"/>
</g>
<g class="left-eye">
<ellipse cx="300" cy="215" rx="45" ry="20" style="stroke:#583504; stroke-width: 3; fill:#FFFFFF"/>
<circle cx="315" cy="215" r="18" style="stroke:#583504; stroke-width: 1; fill:#583504"/>
</g>
<g class="nose">
<path id="路径" transform='translate(117 235) scale(1.6)' class="st0" d="M39.9,12.9c2.5-7.5,9.3-11.6,20.4-12.3S80.1,3,86.4,10c6.7-5.6,15.7-8.7,26.9-9.4s20.5,2.5,28,9.4
c13.3,14.8,13.3,32.5,0,53.1c-16.7,22.1-38.5,33.1-65.3,33c-15.7-0.4-31.9-6.7-48.6-19.1C9.4,63.9,0.3,49.6,0.2,34.4
c0.3-9.8,4.6-17,13-21.5S30.5,8.3,39.9,12.9z"/>
<ellipse cx="225" cy="285" rx="30" ry="18" style="stroke:#583504; stroke-width: 3; fill:#583504"/>
<line x1="225" y1="295" x2="225" y2="325" style="stroke:#583504; stroke-width: 5;"></line>
<line x1="190" y1="325" x2="275" y2="325" style="stroke:#583504; stroke-width: 5;"></line>
</g>
</svg>
</div>
</body>
</html>
复制代码
以上代码运行结果
svg代码复用问题
我们所知道的是svg的代码块都是极其庞大且复杂的,但是为了尽量的节约代码,svg也出现了代码复用的解决方案(即类似组件化的思路来复用基础组件来组合复杂图案)。
【1】<g>
元素
<g>
元素会将所有子元素作为一个组合。通常组合还会有一个唯一的id作为名称。同时元素所指定的样式还将应用于所有子元素,除非其单独设置。
<svg version="1.1"
width="500" height="500"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- g#house嵌套了g#man和g#woman -->
<g id="house" style="fill:none;stroke:black;" width="240px" height="240px">
<title>house</title>
<desc>House width door</desc>
<rect x="6" y="50" width="60" height="60"></rect>
<polyline points="6 50,36 9,66 50"></polyline>
<polyline points="35 110,36 80,50 80,50 110" />
</g>
<g id="man" style="fill:none;stroke:black;">
<title>man</title>
<desc>Male human</desc>
<circle cx="85" cy="56" r="10" />
<line x1="85" y1="66" x2="85" y2="80" />
<polyline points="76 104,85 80,94 104" />
<polyline points="76 70,85 76,94 70" />
</g>
<g id="woman" style="fill:none;stroke:black;">
<title>woman</title>
<desc>Female human</desc>
<circle cx="110" cy="56" r="10" />
<polyline points="110 66,110 80,100 90,120 90,110 80" />
<line x1="104" y1="104" x2="108" y2="90" />
<line x1="112" y1="90" x2="116" y2="104" />
<polyline points="101 70,110 76,119 80" />
</g>
</svg>
复制代码
【2】<use>
元素
复杂的图形中经常会出现重复元素,svg使用<use>
元素为定义在<g>
元素内的组合或者任意独立图形元素提供了类似复杂黏贴的能力; 定义了一组<g>
图形对象后,使用<use>
标签再次显示它们。要指定想要的重用的组合就给xlink:href
属性指定URI
即可,同时还要指定x
和y
的位置以表示组合应该移动到的位置。
<use xlink:href="#house" x="70" y="100"></use> // house模块
<use xlink:href="#man" x="-55" y="100"></use> // man模块
<use xlink:href="#woman" x="-50" y="100"></use> // woman模块
复制代码
【3】<defs>
元素
<defs>
元素可以做为容器来容纳所有可复用的元素,并且不显示它们,只把她们做为模版来使用
<svg version="1.1"
width="500" height="500"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="house" style="fill:none;stroke:red;" width="240px" height="240px">
<title>house</title>
<desc>House width door</desc>
<rect x="6" y="50" width="60" height="60"></rect>
<polyline points="6 50,36 9,66 50"></polyline>
<polyline points="35 110,36 80,50 80,50 110" />
</g>
<g id="man" style="fill:none;stroke:black;">
<title>man</title>
<desc>Male human</desc>
<circle cx="85" cy="56" r="10" />
<line x1="85" y1="66" x2="85" y2="80" />
<polyline points="76 104,85 80,94 104" />
<polyline points="76 70,85 76,94 70" />
</g>
<g id="woman" style="fill:none;stroke:black;">
<title>woman</title>
<desc>Female human</desc>
<circle cx="110" cy="56" r="10" />
<polyline points="110 66,110 80,100 90,120 90,110 80" />
<line x1="104" y1="104" x2="108" y2="90" />
<line x1="112" y1="90" x2="116" y2="104" />
<polyline points="101 70,110 76,119 80" />
</g>
</defs>
<use xlink:href="#house" x="70" y="100"></use>
<use xlink:href="#man" x="-55" y="100"></use>
<use xlink:href="#woman" x="-50" y="100"></use>
</svg>
复制代码
【4】<symbol>
元素
<symbol>
元素本质也是容器,可以放置组合构建复杂图案。此外<symbol>
元素与<g>
元素不同的是可以指定viewBox
和preserveAspectRatio
属性,通过给<use>
元素添加width和height属性就可以让symbol适配视口大小。这边就简单的介绍一下viewPort
、viewBox
与preserveAspectRatio
。
viewPort
:简单而言就是所要显示的区域的大小即屏幕大小。如果有设置具体大小则以设置的为准(支持单位混合但不推荐)
viewBox
:viewBox拥有四个参数( min-x, min-y, width, height )。 其中 min-x:左上角横坐标,min-y:左上角纵坐标,width:宽度,height:高度。 原点默认位于左上角,x 轴水平向右,y 轴垂直向下
本质上viewBox
是改变了坐标系与单位,将区域图像变成用户坐标和用户单位 那么这些事如何得到的?下面是一个例子
<svg width="500" height="200" viewBox="0 0 50 20" >
<rect x="20" y="10" width="10" height="5"
style="stroke: #000000; fill:none;"/>
</svg>
复制代码
本示例创建<svg>
一个宽度为500像素,高度为200 的元素。的viewBox属性<svg>
包含四个坐标。这些坐标定义了<svg>
元素的视图框(ViewBox)。坐标是x y width height视图框(ViewBox)的坐标。在这种情况下,视图框(ViewBox)从处开始0,0并且50宽而20高。也就是说,500 x 200像素<svg>
元素在内部使用从0,0 到的坐标系50,20。换句话说,用于内部形状的坐标中的每1个单位<svg>
对应于宽度500/50 = 10像素,高度对应200/20 = 10像素。这就是为什么x位置为20,y位置为10的矩形真正位于的原因200,100,并且其宽度(10)和高度(5)分别对应于100个像素和50个像素。
如果图像超出?
在前面的例子中我们的viewBox
的宽高比是相同的(500/200 = 50/20)但是在实际应用中不一定比例一定相同,那么或造成三种结果 1: 按较小尺寸等比缩放图形,以完全填充 2: 按较大尺寸等比缩放图形,超出部分进行切割 3: 拉伸或者压缩图形以使其完全是配视口(意思就是完全不保留宽高比,适应视口为第一要务)
preserveAspectRatio
:该属性允许我们指定被缩放的图像相对与视口的对齐方式,以及是希望它适配边缘还是要剪裁。 这一模型preserveAspectRatio= "( align [meet/Slice/none] )"
align值 | 描述 |
---|---|
xMin | 按视口的左侧边缘对齐 |
xMid | 按视口的水平中心对齐 |
xMax | 按视口的右侧边缘对齐 |
YMin | 按视口的顶部边缘对齐 |
YMid | 按视口的垂直中心对齐 |
YMax | 按视口的底部边缘对齐 |
[meet/Slice/none]值 | 描述 |
---|---|
meet | 保留宽高比并缩放视图框(ViewBox)以适合视口(Viewport)。 |
slice | 保留宽高比并切掉不适合视口(Viewport)内部的图像任何部分。 |
none | 不保留宽高比。缩放图像以使视图框(ViewBox)完全适合视口(Viewport)。比例会失真。 |
使用:preserveAspectRatio="xMidYMid meet"/preserveAspectRatio="xMinYMin slice" |
总结
svg给了我们绘图的新的想象空间。虽然有弊端,但是这并不足以否定其地位。何况svg技术已经是W3C所推荐的标准。其在地图、高精度图形、可移植图形,由数据驱动的响应式图形领域的广泛应用也触及我们普通人的日常生活。同时在印刷领域也可通过svg提供高质量的输出文件,在跨平台的一致性上也可以做到极佳控制。正是由于这诸多优点,svg的学习与使用都能产生更多价值,也许很多有趣的应用场景也等待我们去发现扩展。
推荐好文
- 面试官系列:请说说你对深拷贝、浅拷贝的理解
- 面试官系列:请你说说原型、原型链相关
- 面试官系列:请手写防抖或节流函数debounce/throttle
- 面试官系类:请手写instanceof
- 10分钟快速手写实现:call/apply
- 5分钟快速手写实现:bind
- 5分钟快速手写实现:new
参考
- SVG精髓(第二版) —— David Eisenberg & Amelia Bellamy-Royds
- 深入浅出 SVG —— Flavio Copes
- SVG入门—如何手写SVG
- SVG 研究之路 (23) - 理解 viewport 與 viewbox