Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

20.7. SVG 图形库

20.7.1. SVG 标签

20.7.1.1. 符号定义

symbol元素用来定义一个图形模板对象,它可以用一个use元素实例化。symbol元素对图形的作用是在同一文档中多次使用,添加结构和语义。结构丰富的文档可以更生动地呈现出来,类似讲演稿或盲文,从而提升了无障碍。注意,一个symbol元素本身是不呈现的。只有symbol元素的实例(亦即,一个引用了symbol的 use元素)才能呈现。

			
<svg>
  <!-- symbol definition  NEVER draw -->
  <symbol id="sym01" viewBox="0 0 150 110">
    <circle cx="50" cy="50" r="40" stroke-width="8" stroke="red" fill="red" />
    <circle
      cx="90"
      cy="60"
      r="40"
      stroke-width="8"
      stroke="green"
      fill="white" />
  </symbol>

  <!-- actual drawing by "use" element -->
  <use xlink:href="#sym01" x="0" y="0" width="100" height="50" />
  <use xlink:href="#sym01" x="0" y="50" width="75" height="38" />
  <use xlink:href="#sym01" x="0" y="100" width="50" height="25" />
</svg>			
			
			

20.7.1.2. 矩形

绘制圆角矩形

			
<svg width="300px" height="300px" viewBox="0 0 200 200">
  <!-- rx 和 ry 相等, 逐渐增大 -->
  <rect x="10" y="10" width="20" height="40" rx="2" ry="2"
    style="stroke: black; fill: none;"/>

  <rect x="40" y="10" width="20" height="40" rx="5"
    style="stroke: black; fill: none;"/>

  <rect x="70" y="10" width="20" height="40" ry="10"
    style="stroke: black; fill: none;"/>

  <!-- rx 和 ry 不相等 -->
  <rect x="10" y="60" width="20" height="40" rx="10" ry="5"
    style="stroke: black; fill: none;"/>

  <rect x="40" y="60" width="20" height="40" rx="5" ry="10"
    style="stroke: black; fill: none;"/>
</svg>
			
			

20.7.1.3. 圆形

			
<circle
  cx="x-coordinate"      <!-- 圆心的 x 坐标 -->
  cy="y-coordinate"      <!-- 圆心的 y 坐标 -->
  r="radius"             <!-- 圆的半径 -->
  fill="fill-color"      <!-- 圆的填充颜色 -->
  stroke="stroke-color"  <!-- 圆的描边颜色 -->
  stroke-width="width"   <!-- 圆的描边宽度 -->
/>
			
			

20.7.1.4. 路径

贝塞尔曲线
两次贝塞尔曲线

拥有两个控制点的贝塞尔曲线

				
<path d="M{x},{y} C{cx1},{cy1} {cx2},{cy2} {x1},{y1}" id="路径" stroke="blue" stroke-width="2"></path>

起点:M{x},{y}
起点控制点:C{cx1},{cy1}
终点控制点:{cx2},{cy2}
终点:{x1},{y1}
				
					

下面代码生成类似 mindmap 思维导图的连接线

				
            <path d="M0,200 C200,200 200,0 400,0" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,50 400,50" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,100 400,100" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,150 400,150" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,200 400,200" id="路径" stroke="#FFA500" stroke-width="2"></path>

            <path d="M0,200 C200,200 200,250 400,250" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,300 400,300" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,350 400,350" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,400 400,400" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,450 400,450" id="路径" stroke="#FFA500" stroke-width="2"></path>				
				
					

进一步增加复杂度,生成二级子集,同时在起点处增加两个圆圈点缀。

				
            <path d="M0,200 C150,200 200,0 300,0" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,50 300,50" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,100 300,100" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,150 300,150" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,200 300,200" id="路径" stroke="#FFA500" stroke-width="2"></path>

            <path d="M0,200 C150,200 200,250 300,250" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,300 300,300" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,350 300,350" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,400 300,400" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,450 300,450" id="路径" stroke="#FFA500" stroke-width="2"></path>

            <path d="M300,200 C400,200 500,100 600,100" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M300,200 C400,200 500,150 600,150" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M300,200 C400,200 500,200 600,200" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M300,200 C400,200 500,250 600,250" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M300,200 C400,200 500,250 600,250" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M300,200 C400,200 500,300 600,300" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M300,200 C400,200 500,350 600,350" id="路径" stroke="#FFA500" stroke-width="2"></path>
            
            <circle cx="0" cy="200" r="5" fill="white" stroke="blue" stroke-width="2"/>
            <circle cx="300" cy="200" r="5" fill="white" stroke="green" stroke-width="2"/>				
				
					

两端延伸出一段横线,横线上增加文字

				
            <text text-anchor="middle" x="50" y="120" fill="purple" stroke="none">咖啡豆分类</text>

            <text text-anchor="middle" x="350" y="45" fill="red" stroke="none">阿拉比卡咖啡豆</text>
            <path d="M0,125 L100,125 C200,125 200,50 300,50 L 400,50" id="路径" stroke="red" stroke-width="2"></path>

            <text text-anchor="middle" x="350" y="95" fill="green" stroke="none">罗布斯塔咖啡豆</text>
            <path d="M0,125 L100,125 C200,125 200,100 300,100 L 400,100" id="路径" stroke="green" stroke-width="2"></path>

            <text text-anchor="middle" x="350" y="145" fill="orange" stroke="none">利比里亚咖啡豆</text>
            <path d="M0,125 L100,125 C200,125 200,150 300,150 L 400,150" id="路径" stroke="orange" stroke-width="2"></path>

            <text text-anchor="middle" x="350" y="195" fill="blue" stroke="none">埃克萨斯咖啡豆</text>
            <path d="M0,125 L100,125 C200,125 200,200 300,200 L 400,200" id="路径" stroke="blue" stroke-width="2"></path>
            <circle cx="100" cy="125" r="5" fill="white" stroke="blue" stroke-width="2"/>				
				
					

20.7.2. drawsvg

20.7.2.1. 安装

		
pip3 install drawsvg -i https://pypi.tuna.tsinghua.edu.cn/simple
pip3 install cairosvg -i https://pypi.tuna.tsinghua.edu.cn/simple
		
			

20.7.2.2. 绘制多边形

		
lines = draw.Lines(
    # 坐标
    5, 5,
    # 横线 
    200, 5,
    # 竖线 
    200, 40, 
    # 斜线
    200 - 10, 20,
    # 横线2
    5 + 10, 20,
    # 斜线
    5, 40,
    # 闭合竖线
    5,5,
    fill='none', stroke='black')		
		
			

20.7.2.3. SVG 事件

		
<!DOCTYPE html>  
<html>  
<body>  
<svg width="500" height="150">  

<rect x="10" y="10" width="100" height="40"  
   style="stroke: black; fill: silver; fill-opacity: .4;"  
   onmouseover="this.style.stroke = 'blue'; this.style['stroke-width'] = 5;"  
   onmouseout="this.style.stroke = 'green'; this.style['stroke-width'] = 1;"
   onclick="this.style['width'] = 300;" />  

</svg>  
</body>  
</html>		
		
			
		
<!DOCTYPE html>
<html>

<body>
   <input id="aa" type="text" value="200" onclick="svg.style['width']=this.value;" />
   <svg width="500" height="150">


      <rect id='svg' x="10" y="10" width="100" height="40" style="stroke: black; fill: silver; fill-opacity: .4;"
         onmouseover="this.style.stroke = 'blue'; this.style['stroke-width'] = 5;"
         onmouseout="this.style.stroke = 'green'; this.style['stroke-width'] = 1;"
         onclick="this.style['width'] = 300; aa.value='300'" />

   </svg>
</body>

</html>		
		
			

20.7.3. CairoSVG - SVG 转换为 PNG/PDF/PS

			
$ pip3 install cairosvg			
			
		
			
$ cairosvg image.svg -o image.png			
			
		
			
$ python3
>>> import cairosvg
>>> cairosvg.svg2pdf(url='image.svg', write_to='image.pdf')			
			
		

		
import os

import cairosvg

input_file = os.getcwd() + "/mindmap.svg"
output_file = os.getcwd() + "/mindmap.png"

cairosvg.svg2png(url=input_file, write_to=output_file)

# 设置背景色
cairosvg.svg2png(url=input_file, write_to=output_file, background_color="white")