【svg】SVG基础知识、Pygal



2022年07月16日    Author:Guofei

文章归类: 0x70_可视化    文章编号: 722

版权声明:本文作者是郭飞。转载随意,但需要标明原文链接,并通知本人
原文链接:https://www.guofei.site/2022/07/16/svg.html


SVG

SVG是什么?

  • SVG 指可伸缩矢量图形 (Scalable Vector Graphics)
  • SVG 使用 XML 格式定义图形
  • SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失
  • SVG 是万维网联盟的标准
  • SVG 与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体
<svg width="300" height="300" style="border: 1px solid steelblue">
</svg>
viewBox="0 0 120 20"
分别是 x, y, weight, height
意义有些复杂:原本的图像上按照 (x, y, weight, height) 选出一个框,然后只显示这个框内的部分

如何引用svg文件


<object data="https://www.guofei.site/pages/trophy.svg"></object>
<img src="https://www.guofei.site/pages/trophy.svg"></img>

</img>

SVG 预定义形状

共有属性

  • stroke 和 stroke-width 轮廓颜色 和 轮廓宽度
    • stroke-opacity 边框透明度
  • fill 填充色,fill-opacity透明度

矩形 rect

<svg width="100%" height="200px" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="20" rx="30" ry="5" width="300" height="100"
style="fill:rgb(0,0,255);stroke-width:1;
stroke:rgb(0,0,0)"/>
</svg>
  • x, y 左上顶点的坐标
  • rx, ry 产生圆角

圆形 circle

<svg width="100%" height="200px" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
</svg>
  • cx 和 cy 定义圆中心的坐标,默认0
  • r 属性定义圆的半径。

椭圆 ellipse

<svg width="100%" height="300px" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="300" cy="150" rx="200" ry="80"
style="fill:rgb(200,100,50);
stroke:rgb(0,0,100);stroke-width:2"/>
</svg>
  • cx, cy 定义圆点的坐标
  • rx 属性定义水平半径
  • ry 属性定义垂直半径

线 line

<svg width="100%" height="300px" xmlns="http://www.w3.org/2000/svg">
<line x1="0" y1="0" x2="300" y2="300"
style="stroke:rgb(99,99,99);stroke-width:2"/>
</svg>
  • x1, y1 线条开始的坐标
  • y1, y2 线条结束的坐标

多边形 polygon

<svg width="100%" height="300px" xmlns="http://www.w3.org/2000/svg">
<polygon points="220,100 300,210 170,250"
style="fill:#cccccc;
stroke:#000000;stroke-width:1"/>
</svg>
  • points 属性定义多边形每个角的 x 和 y 坐标

折线 polyline

<svg width="100%" height="300px" xmlns="http://www.w3.org/2000/svg">
<polyline points="0,0 0,20 20,20 20,40 40,40 40,60"
style="fill:white;stroke:red;stroke-width:2"/>
</svg>

路径 path

<svg width="100%" height="100%"  xmlns="http://www.w3.org/2000/svg">
<path d="M250 150 L150 350 L350 350 Z"/>
</svg>
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<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" style="fill:white;stroke:red;stroke-width:2"/>
</svg>

参数意义:

  • M = moveto,代表起始位置。(可以有多个)
  • L = lineto,使用直线到新位置
  • H = horizontal lineto;V = vertical lineto,水平或者垂直连线,一个变量控制
  • C = curveto;S = smooth curveto。Cubic Bezier 曲线:使用一个起始点,一个终止点以及两个控制点定义
  • Q = quadratic Belzier curve;T = smooth quadratic Belzier curveto。Quadratic Bezier 曲线:使用一个起始点,一个终止点以及一个控制点定义
  • A = elliptical Arc。截取椭圆的弧形成的曲线
  • Z = closepath,用来闭合曲线,连接到启始点

注:以上所有命令:大写表示绝对定位,小写表示相对定位,相对定位指的是相对上一个点的位置

其它写法,为了压缩空间:

  • 多余的空格可以删除,M 100 100 L 200 200 => M100 100L200 200
  • 如果一个命令字母之前有一个相同的命令字母,则该命令字母可以被删除, 举例如下,M 100 200 L 200 100 L -100 -200 => M 100 200 L 200 100 -100 -200

文字 text

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="50" height="20" role="img">
  <text x="0" y="20" style="fill:red;">文字
  </text>
</svg>
文字

这里的y似乎是中心的位置,因此设定为0会看不清。

  • fill:默认 black
  • stroke="blue":加一层描边。如果再把fill设为none,就变成空心字。
  • font-size="36"
  • font-weight=600
  • font-family="Times New Roman"
  • font-style="italic"
  • 长度 textLength="150" lengthAdjust="spacing"。spacing 只调整字符之间的间隔, spacingAndGlyphs 调整间隔和字符大小
  • transform="rotate(90, 70, 20)" 旋转。 rotate="-90",字体本身旋转。两个结合可以实现竖向文字
  • 其它:text-anchor对齐方式,textPath:按照路径画图

参考:https://blog.csdn.net/weixin_40779234/article/details/113701444

g

用来分组,可以让整个组做一些变化

<svg xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <g transform="rotate(45 50 50)">
      <rect x="0" y="20" height="50" width="75"
          style="stroke: #006600; fill: #006600"/>
      <text x="10" y="90" style="stroke: #660000; fill: #660000">
        hello</text>
    </g>

</svg>
hello
  • transform="translate(x-value, y-value)" 平移
  • transform="scale(x-value, y-value)" 缩放xx倍
  • transform="rotate(angle,[centerX, centerY])",指定圆心和角度来旋转
  • transform="skewX(angle) skewY(angle)" 沿X轴或者Y轴歪斜 angle 角度

子元素会继承g的样式

<svg width="320" height="150">
	<g style="stroke: #0000ff; stroke-width: 4px; fill: red">
		<rect    x="10"  y="10" width="100" height="50" />
		<circle cx="150" cy="35" r="25" />
		<circle cx="250" cy="35" r="25"
			   style="stroke: #009900; fill: #00ff00;"/>
	</g>
</svg>

参考:https://blog.csdn.net/qq_39492374/article/details/89356931

滤镜

feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feFlood feGaussianBlur feImage feMerge feMorphology feOffset feSpecularLighting feTile feTurbulence feDistantLight fePointLight feSpotLight

Gaussian Blur

<svg width="100%" height="100%">
<defs>
<filter id="Gaussian_Blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="6" />
</filter>
</defs>
<ellipse cx="200" cy="150" rx="70" ry="40"
style="fill:#ff0000;stroke:#000000;
stroke-width:2;filter:url(#Gaussian_Blur)"/>
</svg>

SVG 线性渐变 linearGradient

<svg width="100%" height="100%" >
<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>
  • 多个stop来定义不同的颜色
  • offset 属性用来定义渐变的开始和结束位置。
  • stop-opacity 定义透明度

SVG 放射性渐变 radialGradient

<svg width="100%" height="100%">
<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>

其它案例

feBlend 滤镜

Normal Multiply Screen Darken Lighten

feColorMatrix 滤镜

Unfiltered Matrix Saturate HueRotate Luminance

feComponentTransfer 滤镜

Identity TableLookup LinearFunc GammaFunc

feOffset 滤镜

feOffset、feFlood、feComposite、feMerge 以及 feMergeNode

This is some text!

feMorphology 滤镜

Unfiltered Erode 1 Erode 3 Erode 4 Dilate 1 Dilate 3 Dilate 4

向矩形添加一个 “a” 元素,这样矩形就可以作为一个超级链接了。

重复用 5 秒时间淡出的矩形

动画

会改变颜色的三个矩形

沿一个运动路径移动的文本

It's SVG!

沿一个运动路径移动、旋转并缩放的文本

python实现:pygal

参考:https://zhuanlan.zhihu.com/p/444012351

pip install pygal
import pygal

view = pygal.Bar()
# 图表名
view.title = '柱状图'
# 添加数据
view.add('数据', [1, 3, 5, 7, 9, 11])
view.add('数据2', [5, 2, 9, 3, 7, 10])


# 在浏览器中查看
view.render_in_browser()
# 或者存储未文件
# view.render_to_file('bar.svg')

(图?)

其它bar图

# 横bar图
view = pygal.HorizontalBar()

# 横堆叠bar图
view = pygal.HorizontalStackedBar()

折线图

view = pygal.Line()

饼图

view = pygal.Pie()
#图表名
view.title = '饼状图'
#添加数据
view.add('A', 23)
view.add('B', 40)
view.add('C', 15)



其它饼图

# 空心圆饼图
view = pygal.Pie(inner_radius=0.4)


view = pygal.Pie()
#图表名
view.title = '多级饼图'
#添加数据
view.add('A', [20, 25, 30, 45])
view.add('B', [15, 19, 25, 50])
view.add('C', [18, 22, 28, 35])

雷达图

radar_chart = pygal.Radar()
radar_chart.title = 'NBA 各球员能力比拼'
radar_chart.x_labels = ['得分', '防守', '助攻', '失误', '篮板']
radar_chart.add('库里', [70, 98, 96, 85, 97])
radar_chart.add('詹姆斯', [60, 95, 50, 75, 99])
radar_chart.add('杜兰特', [94, 45, 88, 91, 98])

箱型图

box_plot = pygal.Box()
box_plot.title = '各浏览器的使用量'
box_plot.add('Chrome', [6395, 8212, 7520, 7218, 12464, 1660, 2123, 8607])
box_plot.add('Firefox', [7512, 8099, 11700, 2651, 6361, 1044, 8502, 9450])
box_plot.add('360安全卫士', [3472, 2933, 4203, 5510, 5810, 1828, 9013, 4669])
box_plot.add('Edge', [4310, 4109, 5935, 7902, 14404, 13608, 34004, 10210])

仪表盘

gauge_chart = pygal.Gauge(human_readable=True)
gauge_chart.title = '不同浏览器的性能差异'
gauge_chart.range = [0, 10000]
gauge_chart.add('Chrome', 8212)
gauge_chart.add('Firefox', 8099)
gauge_chart.add('360安全卫士', 2933)
gauge_chart.add('Edge', 2530)

热力图

treemap = pygal.Treemap()
treemap.title = 'Binary TreeMap'
treemap.add('A', [12, 15, 12, 40, 2, 10, 10, 13, 12, 13, 40, None, 19])
treemap.add('B', [4, 2, 5, 10, 30, 4, 2, 7, 4, -10, None, 8, 30, 10])
treemap.add('C', [3, 8, 3, 3, 5, 15, 3, 5, 4, 12])
treemap.add('D', [23, 18])
treemap.add('E', [11, 2, 1, 12, 3, 13, 1, 2, 13,
      14, 3, 1, 2, 10, 1, 10, 12, 1])
treemap.add('F', [31])
treemap.add('G', [15, 9.3, 8.1, 12, 4, 34, 2])
treemap.add('H', [12, 13, 3])
treemap.render_in_browser()

地图

# pip install pygal_maps_world

worldmap_chart = pygal.maps.world.World()
worldmap_chart.title = 'Some countries'
worldmap_chart.add('A countries', ['国家名称的缩写'])
worldmap_chart.add('B countries', ['国家名称的缩写'])
worldmap_chart.add('C countries', ['国家名称的缩写'])



# 我们也可以针对不同国家的计数来进行地图的绘制,例如不同国家重大疾病的死亡人数,代码如下
worldmap_chart = pygal.maps.world.World()
worldmap_chart.title = 'Minimum deaths by capital punishement (source: Amnesty International)'
worldmap_chart.add('In 2012', {
  '国家名称的缩写': 数量,
  '国家名称的缩写': 数量,
  .....
})
worldmap_chart.render_in_browser()

# 我们也可以绘制以五大洲为主的世界地图,代码如下
worldmap_continent = pygal.maps.world.SupranationalWorld()
worldmap_continent.add('Asia', [('asia', 1)])
worldmap_continent.add('Europe', [('europe', 1)])
worldmap_continent.add('Africa', [('africa', 1)])
worldmap_continent.add('North america', [('north_america', 1)])
worldmap_continent.add('South america', [('south_america', 1)])
worldmap_continent.add('Oceania', [('oceania', 1)])
worldmap_continent.add('Antartica', [('antartica', 1)])
worldmap_continent.render_in_browser()

您的支持将鼓励我继续创作!