SVG学习(2)

SVG中的坐标系统与坐标变换

SVG的世界、视野、视窗的概念

视野与世界

  • 世界是无穷大的
  • 视野是观察世界的一个矩形区域 viewbox

  • width,height - 控制视窗

  • SVG代码 - 定义世界
  • viewBox,preserveAspectRatio - 控制视野
1
2
3
4
5
6
<svg xmlns="http://www.w3.org/2000/svg"
width="800px" height="400px"
viewBox="0 0 400 300"
preserveAspectRatio="xMidYMid meet">
<!--SVG content-->
</svg>

世界是客观的,视野是可以改变的,svg中提供了viewbox控制视野的范围
<svg>标签中可以指定宽高属性,表示svg文件渲染的区域大小,也可以使用样式表定义,这个区域就是浏览器中的视窗
视窗是指浏览器开辟的用来渲染svg内容的区域,是根据样式上下文来进行,可能改变;视野是svg文件的编写者定义的要以多大的视野来观察定义的世界,理想的情况下视野和世界尺寸相同,如果定义的视野和视窗的大小不一致,如何进行填充,用preserveAspectRatio属性进行指定

SVG中的图形分组

  • <g>标签来创建分组 (可以对分组进行整体操作)
  • 属性继承
  • transform属性定义坐标变换
  • 可以嵌套使用
1
2
3
4
5
6
7
8
9
10
11
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="200">
<g stroke="green" fill="none" transform="translate(150,0)">
<rect x="100" y="50" width="100" height="50">
</rect>
<rect x="140" y="100" width="20" height="120">
</rect>
</g>
<g>
<polygon points="100,10 40,180 190,60 10,60 160,180" style="fill:red;stroke:blue;stroke-width:3;fill-rule:evenodd;">
</g>
</svg>

坐标系统概述

  • 笛卡尔直角坐标系
  • 原点
  • 互相垂直的两条数轴
  • 角度定义

坐标系统的作用是为图形提供一个基本的定位基准
基于原点和数轴的定义又可以定义角度,数学上,x轴方向水平向右,y轴方向水平向上,角度的正方向是逆时针方向,由于svg的阅读媒介一般都是屏幕,出于对人的阅读习惯的考虑和大多数浏览器上其他动元素的坐标的习惯,svg使用的坐标系是y轴方向水平向下的,角度的正方向是顺时针的
角度的正方向是笛卡尔坐标系中从x轴正方向到y轴正方向旋转的方向

四个坐标系

用户坐标系(User Coordinate)

世界的坐标系

viewBox视野大小就是观察用户坐标系中的区域,用户坐标系是最原始的坐标系,即svg标签的坐标系,其他的坐标系都是从用户坐标系产生的,也被称为原始坐标系

自身坐标系(Current Coordinate)

每个图形元素或分组独立与生俱来

前驱坐标系(Previous Coordinate)

父容器的坐标系

坐标变换就是前驱坐标系经过了元素变换之后得到的自身坐标系

1
2
3
4
5
6
7
8
9
<svg>
<rect id="a"
x="0"
y="0"
width="100"
height="50"
transform="translate(50,50)">
</rect>
</svg>

自身坐标系和前驱坐标系.例子

1
2
3
4
5
6
7
8
<svg id="A" xmlns="...">
<g id="B" transform="translate(0,50)">
<rect id="C" x="100" y="50" width="100" height="50">
</rect>
<rect id="D" x="140" y="100" width="20" height="120">
</rect>
</g>
</svg>

分别定义对应的坐标系OA、OB、OC、OD
世界坐标系 OA

#B的前驱坐标系 用户坐标系 OA

#C和#D的图形定义是基于坐标系 OC和OD (所有的图形,关于它自身图形描述的属性都是基于它自己的自身坐标系来进行定义)

#C和#D的前驱坐标系 OB
分组#B的自身坐标系 OB
分组#B上的transform属性表示分组#B的自身坐标系OB是从它的前驱坐标系OA经过transform变换来的
OB、OC、OD坐标系重合了,因为OB是OC和OD的前驱坐标系,而#C和#D都没有定义transform属性,#C和#D的自身坐标系和前驱坐标系重合

参考坐标系(Reference Coordinate)

使用其他坐标系来考究自身的情况下使用

坐标变换

定义

  • 数学上,坐标变换是采用一定的数学方法将一个坐标系的坐标变换为另一个坐标系的坐标的过程
  • SVG中,坐标变换是对一个坐标系到另一个坐标系的变换的描述

线性变换

  • 线性变换方程
    X‘ = aX + cY + e
    Y‘ = bX + dY + f
  • 变换矩阵,记为M
    「a c e
    b d f
    0 0 1」

原坐标系中的每个点经过线性运算之后得到新坐标系中的每个点

平移
「1 0 10
0 1 10
0 0 1」
X’ = 1X + 0Y + 10 = X + 10
Y’ = 0X + 1Y + 10 = Y + 10

旋转

  • 使用极坐标求变换矩阵
    极坐标方程:
    X = rcos(α)
    Y = r
    sin(α)
    旋转θ度后:
    X’ = rcos(α+θ)
    Y’ = r
    sin(α+θ)
    展开:
    X’ = rcos(α)cos(θ) - rsin(α)sin(θ) = cos(θ)X - sin(θ)Y + 0
    Y’ = rcos(α)sin(θ) + rsin(α)cos(θ) = sin(θ)X + cos(θ)Y + 0
    「cos(30o) -sin(30o) 0
    sin(30o) cos(30o) 0
    0 0 1」

缩放

  • a和c直观控制缩放
    「2 0 0
    0 2 0
    0 0 1」

线性变换列表

  • 表示一系列的变换,结果为变换的矩阵的乘积
    M = Mn Mn-1 M2 M1 * M0
  • 后面的变换乘在前面
    「1 0 10 「cos(30o) -sin(30o) 0
    0 1 10 sin(30o) cos(30o) 0
    0 0 1」 0 0 1」
    Mtranslate
    Mrotate

transform属性

  • 前驱坐标系:父容器的坐标系
  • transform属性:定义前驱坐标系到自身坐标系到线性变换
  • 语法:
    ratate()
    translate(,)

    scale(,)
    matrix(,,,,,)
  • demo
    viewBox加0.5的偏移,之后的坐标是对齐到整数的话(画线?)会比较锐利 浏览器渲染svg的1像素偏差

根据慕课网课程整理