zoukankan      html  css  js  c++  java
  • SVG坐标系统

    SVG的画布、画布视区(viewBox)、浏览器视窗的概念

    画布

    画布是绘制SVG内容的一块区域,理论上在所有维度上都是无限的。(也有人称为“SVG世界”,但我觉得叫画布比较合适)

    画布视区(viewBox)

    就是截取画布某一块矩形区域作为显示的区域。(有人也称为“视野”或“视区盒子”,但我觉得不够形象。viewBox是与画布相关的,那既然是画布的可视区,那叫画布视区比较容易顾名思义。)

    控制画布视区有两个属性:viewBox、preserveAspectRatio。

    viewBox

    viewBox指定可视区的位置和大小,值有4个数字:viewBox="x, y, width, height" 。

    参数 描述
    x 左上角横坐标
    y 左上角纵坐标
    width 宽度
    height 高度

    preserveAspectRatio

    preserveAspectRatio指定viewbox在viewport中的缩放和对齐方式。preserveAspectRatio = "align meetOrSlice"    

    align参数的值有分为两个部分,第一个部分指定X坐标的对齐方式,第二个部分指定Y坐标的对齐方式。下面列出了所以的X和Y对齐方式:

    参数 描述
    xMin viewBox的最小X值对齐viewport的左边部
    xMid viewBox的X轴中点对齐viewport的X轴中点
    xMax viewBox的最大X值对齐viewport的右边部
    YMin viewBox的最小Y值对齐viewport的顶边
    YMid viewBox的Y轴中点对齐viewport的Y轴中点
    YMax viewBox的最大Y值对齐viewport的底边

    你可以将X对齐和Y对齐两两结合组成一个align参数,例如:xMaxYMax或xMidYMid。

    注意:

    1. 默认值是xMidYMid。

    2. 如果align设置为none,图形会被缩放以适应viewport大小,而不会管它的宽高比。

    meetOrSlice参数指明viewbox的缩放方式。

    参数 描述
    meet( 默认值) 保持纵横比缩放viewBox适应viewport。
    PS:整个viewBox包含在viewport里。
    slice 保持纵横比同时比例小的方向放大填viewport。
    PS:这里注意这个“满”,就是填充了。
    none 不保留宽高比。缩放图像适合整个viewport

    浏览器视窗(viewport)

    用户所能看到的区域,区域大小等于其设置的宽度和高度。(这里之所加上“浏览器”,是为了与画布视区区分开来。)

    示例:

    慕课网SVG教程对于ViewBox的示例,我觉得不错,可以自己实践操作,看看效果。

    SVG中的图形分组

    SVG用<g>标签来创建分组,分组元素用于在逻辑上对相关的图形元素进行分组。分组里面的元素会继承分组的属性,另外分组可嵌套使用。

    示例:

    <svg viewBox="0 0 95 50"
         xmlns="http://www.w3.org/2000/svg">
       <g stroke="green" fill="white" stroke-width="5">
         <circle cx="25" cy="25" r="15"/>
         <circle cx="40" cy="25" r="15"/>
         <circle cx="55" cy="25" r="15"/>
         <circle cx="70" cy="25" r="15"/>
       </g>
    </svg>
    效果:
     
    坐标系统概述

    SVG使用的是笛卡尔直角坐标系,为图形做一个统一的定位基准。笛卡尔坐标系就是直角坐标系和斜角坐标系的统称。相交于原点的两条数轴,构成了平面放射坐标系。两条数轴互相垂直的笛卡尔坐标系,称为笛卡尔直角坐标系。

    出于对阅读习惯(浏览器)的考虑和DOM的坐标的习惯,SVG使用的是y轴朝下的,所以角度的正方向是顺时针的。

    四个坐标系

    1. 用户坐标系(User Coordinate)

    也可以称为原始坐标系,是画布的坐标系。

    2. 自身坐标系(Current Coordinate)

    每个图形或分组都会产生一个自身坐标系,用于定义自己的一些图形属性,例如宽高、位置。

    3. 前驱坐标系(Previous Coordinate)

    即是父容器坐标系。

    4. 参考坐标系(Reference Coordinate)

    需要对某些图形进行观察、测量的一个坐标系。(例如需要是图形对齐时,就需要选取一个参考坐标系,一般是原始坐标系。)

    示例:

    <svg viewBox="0 0 95 50"
         xmlns="http://www.w3.org/2000/svg">
       <g stroke="green" fill="white" stroke-width="5">
         <circle cx="25" cy="25" r="15"/>
         <circle cx="40" cy="25" r="15"/>
         <circle cx="55" cy="25" r="15"/>
         <circle cx="70" cy="25" r="15"/>
       </g>
    </svg>

    1. <svg>使用原始坐标系。

    2. cx="25" cy="25" r="15"是circle的自身坐标系。

    3. <g>是<circle>前驱坐标系。

    坐标变换

    1. 坐标变换定义

    SVG中,坐标变换是对一个坐标系到另一个坐标系的变换的描述。

    2. 线性变换

    SVG的坐标变换是使用线性变换的。(线性代数里面有讲这东西)

    线性变换方程

    X' = aX + cY + e

    Y' = bX + dY + f

    变换矩阵(Matrix),记为M

    这样类似平移、旋转、缩放的操作都可以用矩阵来表示。

    3. 线性变换列表

    表示一系列的变换,结果为变换的矩阵的乘积。(注意后变换的要放在前面)

    例如:

    旋转30°之后,再向x、y正方向各平移10。

    4. transform属性

    transform属性:定义应用于元素及其子元素的变换列表,每个变换由空格或逗号分隔。

    PS:MDN关于transform属性的解释可能有一点错。

    原文:The transform attribute defines a list of transform definitions that are applied to an element and the element's children. The items in the transform list are separated by whitespace and/or commas, and are applied from right to left.

    “applied from right to left.”这里说变换应用是从右到左的,但其实应该是正常的从左到右,矩阵的计算才是从右到左。

    属性 描述 示例
    matrix(<a> <b> <c> <d> <e> <f>) 使用变换矩阵 向右平移10
    matrix(1,0,0,1,10,0)
    translate(<x> [<y>]) 平移
    PS:y默认是0
    向右平移10
    translate(10)
    scale(<x> [<y>]) 缩放
    PS:y未取值时,值等于x
    放大2倍
    scale(2)
    rotate(<a> [<x> <y>]) 旋转
    当x、y没值时,旋转的圆心是用户坐标系;
    当x、y有值时,旋转的圆心是(x,y);
    旋转30°
    rotate(30)
    skewX(<a>) 向x斜切a度 斜切45度
    skewX(45)
    skewY(<a>) 向y斜切a度 斜切45度
    skewY(45)

    注意:

    1. 都是没有单位的

    2. 进行了变换后,后续的变换都是基于我已经变换的自身坐标系进行的。

    示例:

    <html>
        <head>
            <title>transform</title>
            <style>
                body {
                    background: #eee;
                }
                svg {
                    position: absolute;
                    border: 1px solid green;
                    width: 300px;
                    height: 200px;
                    left: 50%;
                    top: 50%;
                    margin-top: -100px;
                    margin-left: -150px;
                    background: white;
                }
            </style>
        </head>
        <body>
              <svg id="svg" xmlns="http://www.w3.org/2000/svg">
                   <rect width="200" height="100" stroke="red" stroke-width="2" fill="none" transform="rotate(30) translate(50)"/>
              </svg>
        </body>
    </html>

    效果:

    这里可以看到,进行旋转30度后,再平移已经不是根据原先自身坐标系了,而是变换后的自身坐标系。蓝色的线段就是平移50的效果。

    总结

    该文章是SVG课程(慕课网)的学习笔记,以及查阅一些资料,加上我个人理解的一个总结。

     
    参考文献
     
    本文为原创文章,转载请保留原出处,方便溯源,如有错误地方,谢谢指正。
  • 相关阅读:
    第十章 迭代器模式 Iterator
    第四章:使用Proxy代理让客户端服务端分工合作。
    第三章:真正弄清楚一个Mod的组织结构
    第二章:开始开发mod前你需要知道的一些事情
    第一章:在IDEA里搭建基于Forge的Minecraft mod开发环境
    Android实现真正的ViewPager【平滑过渡】+【循环滚动】!!!顺带还有【末页跳转】。
    关于坑爹的PopupWindow的“阻塞”争议问题:Android没有真正的“阻塞式”对话框
    快排-Go版本
    链表翻转(按K个一组)(Go语言)
    牛客刷题-重建二叉树(GO语言版)
  • 原文地址:https://www.cnblogs.com/lovesong/p/5966752.html
Copyright © 2011-2022 走看看