您的位置:澳门新葡8455最新网站 > Web前端 > 澳门新葡8455最新网站了解SVG坐标种类和改动,

澳门新葡8455最新网站了解SVG坐标种类和改动,

发布时间:2019-11-04 10:57编辑:Web前端浏览(122)

    理解SVG坐标系统和变换: transform属性

    2015/09/23 · HTML5 · SVG

    原文出处: SaraSoueidan   译文出处:Blueed@Ivan_z3   

    SVG元素可以通过缩放,移动,倾斜和旋转来变换-类似HTML元素使用CSS transform来变换。然而,当涉及到坐标系时这些变换所产生的影响必然有一定差别。在这篇文章中我们讨论SVG的transform属性和CSS属性,包括如何使用,以及你必须知道的关于SVG坐标系变换的知识。

    这是我写的SVG坐标系统和变换部分的第二篇。在第一篇中,包括了任何要理解SVG坐标系统基础的需要知道的内容;更具体的是, SVG viewport, viewBox 和 preserveAspectRatio 属性。

    • 理解SVG坐标系和变换(第一部分)-viewport,viewBox,和preserveAspectRatio
    • 理解SVG坐标系和变换(第二部分)-transform属性
    • 理解SVG坐标系和变换(第三部分)-建立新视窗

    这一部分我建议你先阅读第一篇,如果没有,确保你在阅读这篇之前已经读了第一篇。

    理解SVG transform坐标变换

    2015/10/11 · HTML5 · SVG

    原文出处: 张鑫旭   

    transform属性值

    tranform属性用来对一个元素声明一个或多个变换。它输入一个带有顺序的变换定义列表的<transform-list>值。每个变换定义由空格或逗号隔开。给元素添加变换看起来如下:

    有效地SVG变换有:旋转缩放移动, 和倾斜transform属性中使用的变换函数类似于CSS中transform属性使用的CSS变换函数,除了参数不同。

    注意下列的函数语法定义只在transform属性中有效。查看section about transforming SVGs with CSS properties获取关于CSS变换属性中使用的语法信息。

    一、HTML transform和SVG transform

    SVG中自带transform属性,没错,是属性,例如:

    JavaScript

    <svg width="200" height="150"> <rect x="30" y="30" width="120" height="90" transform="rotate(45)"></rect> </svg>

    1
    2
    3
    <svg width="200" height="150">
        <rect x="30" y="30" width="120" height="90" transform="rotate(45)"></rect>
    </svg>

    普通的HTML元素没有transform属性,但是支持CSS3的transform, 好奇的小伙伴可能会疑问了,CSS3中的transform变换,跟SVG中的transform是什么关系呢?

    恩,有点类似于谢霆锋和陈冠希之间的关系,有些小复杂。

    澳门新葡8455最新网站 1

    OK, 先说说相似之处吧。
    一些基本的变换类型是一样的,包括:位移translate, 旋转rotate, 缩放scale, 斜切skew以及直接矩阵matrix. 但只局限于2D层面的变换。SVG似乎只支持二维变换(若有不对,欢迎指正),且类似translateXrotateX也都是不支持的。

    下面就是不一样的地方了:
    1. CSS3 transform一般用在普通元素上,虽然也可以应用在SVG元素上,但是IE浏览器(IE edge未测试)却不支持SVG元素;

    JavaScript

    rect { /* IE说:你这是弄啥来? */ transform:rotate(45deg); }

    1
    2
    3
    4
    rect {
        /* IE说:你这是弄啥来? */
        transform:rotate(45deg);
    }

    2. HTML元素的CSS3 transform和SVG的transform坐标系统大相径庭;

    平常我们使用transform其坐标是相对于当前元素而言的,默认是元素的中心点变换,我们可以通过transform-origin属性改变变换的中心点。而SVG中的transform的坐标变换的是相对于画布的左上角计算的,跟HTML的transform差别较大,理解上也更加麻烦。而本文就是彻底理清SVG中的transform到底是怎么工作的。

    3. 具体的语法细节有差异。SVG transform属性语法有些自带偏移。而CSS transform则更加纯粹些。

    //zxx: 据说CSS的transform和SVG的transform属性即将合并。

    Matrix

    你可以使用matrix()函数在SVG元素上添加一个或多个变换。matrix变换语法如下:

    matrix(<a> <b> <c> <d> <e> <f>)

    1
    matrix(<a> <b> <c> <d> <e> <f>)

    上述声明通过一个有6个值的变换矩阵声明一个变换。matrix(a,b,c,d,e,f)等同于添加变换matrix[a b c d e f]

    如果你不精通数学,最好不要用这个函数。对于那些精通的人,你可以在这里阅读更多关于数学的内容。因此这个函数很少使用-我将忽略来讨论其他变换函数。

    二、SVG transform translate位移

    我们先来看下最简单最基本的translate位移变换,例如,我们偏移(295,115)大小的位置,HTML元素的偏移(下图左)和SVG元素的偏移(下图右)就会不一样。一个是相对自己的中心点(下图左),一个是SVG的左上角(下图右)。

    澳门新葡8455最新网站 2

    虽然两者的相对位置不一样,但是,对于单纯地位移来讲,无论你相对于那个点位置,实际偏移的位置都是一样的,因此,从表现上讲,两者最终的位置看上去还是一样的。

    您可以狠狠地点击这里:HTML translate和SVG translate比对demo

    澳门新葡8455最新网站 3

    前面我们提到过,SVG元素也能使用CSS3的transform进行变换(非IE浏览器),但是只能支持2D层面的几个属性,例如translateX(tx),translateY(ty)以及translate(tx[, ty])translateZ(tz)则并不支持。

    如果我们使用SVG元素自带的transform属性进行变换,则仅支持translate(tx[ ty])这种用法(缺省使用0代替),当多个参数值的时候,可以使用逗号,或者直接空格分隔,但是不能包含单位,例如下面这种写法直接翘辫子:

    CSS

    transform="translate(30px 12px)"

    1
    transform="translate(30px 12px)"

    下面这种无单位写法才可以:

    CSS

    transform="translate(30 12)" transform="translate(30, 12)"

    1
    2
    transform="translate(30 12)"        
    transform="translate(30, 12)"

    另外,和CSS3的transform一样,SVG中的translate位移也是支持多声明累加的。例如:

    CSS

    transform="translate(30 12) translate(30 12)"

    1
    transform="translate(30 12) translate(30 12)"

    等同于:

    CSS

    transform="translate(60 24)"

    1
    transform="translate(60 24)"

    需要注意的是,俩个translate中间不要混有其他的transform变换。否则,最终的位移就不是简单的相加了。

    Translation

    要移动SVG元素,你可以用translate()函数。translate函数的语法如下:

    CSS

    translate(<tx> [<ty>])

    1
    translate(<tx> [<ty>])

    translate()函数输入一个或两个值得来声明水平和竖直移动值。tx代表x轴上的translation值;ty代表y轴上的translation值。

    ty值是可选的,如果省略,默认值为0txty值可以通过空格或者逗号分隔,它们在函数中不代表任何单位-它们默认等于当前用户坐标系单位。

    下面的例子把一个元素向右移动100个用户单位,向下移动300个用户单位。

    <circle cx="0" cy="0" r="100" transform="translate(100 300)" />

    1
    <circle cx="0" cy="0" r="100" transform="translate(100 300)" />

    上述代码如果以translate(100, 300)用逗号来分隔值的形式声明一样有效。

    三、SVG transform rotate旋转

    上面的位移变换,我们似乎没看到明显的不一样。但是,从这里的旋转变换开始,就可以看出明显的差异了。

    下面图示的是基本的45度旋转(来自css-tricks)(左HTML元素,右SVG元素):

    澳门新葡8455最新网站 4

    由于SVG元素的默认是SVG左上角为中心变换的,因此,矩形旋转的幅度就有了过山车的感觉。

    您可以狠狠地点击这里:HTML rotate和SVG rotate比对demo

    澳门新葡8455最新网站 5

    结果会发现,两者位置大相径庭了:

    CSS transform中的rotate语法比较直白:rotate(angle),就一个angle参数,表示角度大小,不过必须要有单位,比如deg(度), turn(圈), grad(百分度 – 一种角的测量单位,定义为一个圆周角的1/400。常用于建筑或土木工程的角度测量),甚至可以使用calc()计算,例如:calc(.25turn - 30deg).

    但是,SVG中的属性transform旋转就没有这么多花头,单位?哦,别逗了,毛线都没有,直接光秃秃的数值,表示角度deg,例如:

    CSS

    transform="rotate(45)"

    1
    transform="rotate(45)"

    具体语法为:rotate(angle[ x y]). 大家注意到没有,这里有个[ x y][]表示这个可选参数。也就是说,SVG中的rotate旋转比CSS的rotate多了一个可选参数,那这个可选参数[ x y]表示什么意思呢?

    告诉你,是非常有用的东西。用来偏移transform变换中心点的。

    为什么说非常有用呢?SVG元素默认是基于左上角的,但是我们的旋转元素往往都在SVG的中间区域,此时旋转跨度太大,智商余额不足的我们就脑补不过来,此时难免希望可以像CSS的transform变换一样,围绕元素的中心点变换。怎么办?

    我们可以借助CSS3 transform-origin修改SVG元素默认的变换中心点,然后配合CSS变换。但是,我们前面多次提到,IE浏览器的SVG元素不识别CSS中的transform. 所以,从兼容性上讲,CSS策略是不可行的。难道就没有其他办法了,有,就是这里的可选参数[ x y],通过对变换中心点的偏移修正,我们也能让SVG元素围绕自身的中心点旋转了。

    所以,上面的demo,我们稍微修改下,就能让矩形围绕自己旋转了,见下:

    JavaScript

    <rect x="30" y="30" width="120" height="90" rx="10" ry="10" fill="#a0b3d6" transform="rotate(45, 90 75)"></rect> <!-- 90 = 30 + 120/2 --> <!-- 75 = 30 + 90/2 -->

    1
    2
    3
    <rect x="30" y="30" width="120" height="90" rx="10" ry="10" fill="#a0b3d6" transform="rotate(45, 90 75)"></rect>
    <!-- 90 = 30 + 120/2 -->
    <!-- 75 = 30 +  90/2 -->

    您可以狠狠地点击这里:SVG元素也围绕自身中心点旋转demo

    澳门新葡8455最新网站 6

    使用原理图表示就是下面这样(左HTML旋转,右SVG元素偏移旋转):

    澳门新葡8455最新网站 7

    同样的,rotate旋转可以多个值并存,例如下面的CSS和attribute用法:

    CSS

    transform: rotate(45deg) rotate(-45deg); transform="rotate(45) rotate(-45)

    1
    2
    transform: rotate(45deg) rotate(-45deg);
    transform="rotate(45) rotate(-45)

    然而,需要注意的是,SVG属性的transform声明的中心变换坐标是不能共享的。

    因此,虽然transform="rotate(45, 90 75)"是中心点旋转,但是,后面再添加其他东西,例如:rotate(-45)则偏移值忽略,终中心点还是SVG的左上角(0,0)位置,好惨!

    例如原来的45度旋转,再加个-45度反向旋转:

    XHTML

    <rect x="30" y="30" width="120" height="90" rx="10" ry="10" fill="#a0b3d6" transform="rotate(45, 90 75) rotate(-45)"></rect>

    1
    <rect x="30" y="30" width="120" height="90" rx="10" ry="10" fill="#a0b3d6" transform="rotate(45, 90 75) rotate(-45)"></rect>

    结果位置回去了?才怪呢!澳门新葡8455最新网站 8

    CSS的是又回去了,但是SVG的确是挂在月球上了。究其原因是rotate(-45)又是相对SVG左上角变换的啦!

    澳门新葡8455最新网站 9

    您可以狠狠地点击这里:SVG连续旋转demo

    虽然乍看上去,好像SVG的坐标系统有些怪怪的,但是,实际上,在有些需求场景下,SVG这种看似独立的偏移系统更容易实现一些功能。

    比方说,我们希望某个SVG元素先以右下角为中心旋转90度,然后再以右上角为中心旋转90度,该怎么处理?

    对于SVG transform,我们直接面向需求写数值就可以了。假设我们的SVG元素的高宽是120*90, 左上角坐标是(30,30), 则,显然,右下角坐标是(150,120), 右上角坐标是(150,30),于是,我们的transform值就很简单:

    XHTML

    transform="rotate(90, 150 120) rotate(90 150 30)"

    1
    transform="rotate(90, 150 120) rotate(90 150 30)"

    参见下面的示意图(示意图的坐标与上面略有出入,但不影响原理示意):澳门新葡8455最新网站 10

    但是,如果我们使用之前容易理解的CSS3来实现,反而就复杂了,因为CSS3中的transform的变换点只能一次性指定,如果要实现不同变换点的旋转效果,只能通过translate再次偏移,例如,实现上面的右下角再右上角90度旋转,则要这样:

    CSS

    transform-origin: right bottom; /* 或者 100% 100% */ transform: rotate(90deg) translate(0, -100%) /* 从右下到右上 */ rotate(90deg) translate(0, 100%);

    1
    2
    3
    4
    5
    6
    transform-origin: right bottom; /* 或者 100% 100% */
    transform:
      rotate(90deg)
      translate(0, -100%) /* 从右下到右上 */
      rotate(90deg)
      translate(0, 100%);

    Gif示意下就是:澳门新葡8455最新网站 11

    显然要麻烦很多。可见,两种坐标系统没有绝对的优劣。

    您可以狠狠地点击这里:右下再右上旋转90度demo

    澳门新葡8455最新网站 12

    上图为两种变换的最终效果,虽然最终的效果是一样的,但是,从理解上而言,这回,是SVG的transform反而更容易理解。还是那句话,辩证看问题,凡事无绝对。

    Scaling

    你可以通过使用scale()函数变换来向上或者向下缩放来改变SVG元素的尺寸。scale变换的语法是:

    CSS

    scale(<sx> [<sy>])

    1
    scale(<sx> [<sy>])

    scale()函数输入一个或两个值来声明水平和竖直缩放值。sx代表沿x轴的缩放值,用来水平延长或者拉伸元素;sy代表沿y轴缩放值,用来垂直延长或者缩放元素。

    sy值是可选的,如果省略默认值等于sxsxsy可以用空格或者逗号分隔,它们是无单位值。

    下面例子把一个元素的尺寸根据最初的尺寸放大两倍:

    XHTML

    <rect width="150" height="100" transform="scale(2)" x="0" y="0" />

    1
    <rect width="150" height="100" transform="scale(2)" x="0" y="0" />

    下列例子把一个元素缩放到最初宽度的两倍,并且把高度压缩到最初的一半:

    XHTML

    <rect width="150" height="100" transform="scale(2 0.5)" x="0" y="0" />

    1
    <rect width="150" height="100" transform="scale(2 0.5)" x="0" y="0" />

    上述例子使用逗号分隔的值例如scale(2, .5)仍然有效。

    这里需要注意当SVG元素缩放时,整个坐标系被缩放,导致元素在视窗中重新定位,现在不用担心这些,我们会在下一节中讨论细节。

    四、SVG transform scale缩放

    SVG中的缩放的语法就比较单纯了,就scale(sx[, sy])sx表示横坐标缩放比例,sy表示纵坐标缩放比例。其中sy是可缺省的,如果缺失,表示使用和sx一样的值,也就是等比例缩放。其中,sxsy两个参数可以逗号分隔,也可以使用空格分隔。这和CSS3中的使用有所不同,两外,SVG transform属性值缩放是不支持scaleXscaleY这些鬼的。

    同样的,CSS控制的transform和SVG元素属性控制的transform的坐标系统是不一样的。一个默认元素中心(下图左),一个是SVG画布左上角(下图右),于是(from css-tricks):澳门新葡8455最新网站 13

    因此,当我们对SVG元素scale缩放时候,发现位置也有出乎我们意料,就应该知道是怎么回事了。

    rotate旋转虽然也是迥异坐标,但是其参数自带偏移参数,我们我们移个花接个木,还是可以得到我们想要的结果。但是,scale缩放这里,就要悲惨很多了,没有自带偏移参数,于是,当我们要实现SVG元素居中缩放的效果,还需要使用translate手动偏移。

    怎么个手动偏移法呢?即使先translate其中心点位置到元素的中心坐标位置,然后缩放,然后坐标再反方向还原回去。例如,某元素中心点坐标是(95, 75), 垂直缩放1.5倍的效果则是:

    CSS

    transform="translate(95 75) scale(1, 1.5) translate(-95 -75)"

    1
    transform="translate(95 75) scale(1, 1.5) translate(-95 -75)"

    您可以狠狠地点击这里:CSS transform和SVG transform scale缩放demo

    对应的CSS代码就简单多了,直接:

    CSS

    .scale { transform: scale(1, 1.5); }

    1
    2
    3
    .scale {
        transform: scale(1, 1.5);
    }

    然后最终效果都是一样的:澳门新葡8455最新网站 14

    使用Gif原理示意如下:

    澳门新葡8455最新网站 15

    Skew

    SVG元素也可以被倾斜,要倾斜一个元素,你可以使用一个或多个倾斜函数skewX 和 skewY

    skewX(<skew-angle>) skewY(<skew-angle>)

    1
    2
    skewX(<skew-angle>)
    skewY(<skew-angle>)

    函数skewX声明一个沿x轴的倾斜;函数skewY声明一个沿y轴的倾斜。

    倾斜角度声明是无单位角度的默认是度。

    注意倾斜一个元素可能会导致元素在视窗中重新定位。在下一节中有更多细节。

    五、SVG transform skew斜切

    先来了解下CSS中的斜切,斜切,如果单纯切一个方向,我们可以看成把矩形变成了平行四边形,其总面积不变化。

    以纯X轴变换举例,skewX(-45deg)则下面这样子(灰色方块为原始位置):

    澳门新葡8455最新网站 16

    skewX(45deg)则下面这样子:澳门新葡8455最新网站 17

    对于SVG的skew斜切变换,表现效果原理是一样的。但是,使用的语法却相当有意思。

    在前面的一些变换中,例如位移、缩放之类是不支持translateXscaleX这种CSS常见用法的,但是这里的skew却有点让人哭笑不得:不支持skew(x[, y])这种语法,而只能是skewX或者skewY.

    别问我为什么?我只是大自然的搬运工,我不生产语法。

    因此,没有:

    JavaScript

    <del datetime="2015-10-10T12:49:32+00:00">transform="skew(45, 0)"</del>

    1
    <del datetime="2015-10-10T12:49:32+00:00">transform="skew(45, 0)"</del>

    只有:

    CSS

    transform="skewX(45)"

    1
    transform="skewX(45)"

    同样的,由于变换中心点的差异,CSS实现的变换和SVG属性变换往往最后的位置是不一样的:

    澳门新葡8455最新网站 18

    不仅如此,如果元素的中心点不是就是SVG的左上角,则skewX(α1) skewX(α2)的最终位置和skewX(α1 + α2)是不一样的(位移和旋转不会这样子)。

    您可以狠狠地点击这里:CSS SVG transform skew斜切差异及连续斜切差异demo

    正如demo所示,CSS的和SVG的位置差异很大:澳门新葡8455最新网站 19

    SVG的连续变换和一次性变换的位置也是不一样的:澳门新葡8455最新网站 20

    可能有人要疑问,为何连续斜切变换和一次性变换位置会不一样?其实原因很简单,因为斜切的角度和元素偏移大小并不是线性的,比方说,从70到80度和80度到90度之间的位移大小(虽然都是10度的变化区间)是显然不是一个档次的。因此,分开多次连续斜切最终的坐标偏移要比一次性偏移来得小。

    最后,和缩放一样,你想要让SVG元素中心点斜切,可以先translate偏移,在skew变换。就不重复举例演示了。

    Rotation

    你可以使用rotate()函数来旋转SVG元素。这个函数的语法如下:

    CSS

    rotate(<rotate-angle> [<cx> <cy>])

    1
    rotate(<rotate-angle> [<cx> <cy>])

    rotate()函数对于给定的点和 旋转角度值执行旋转。不像CSS3中的旋转变换,不能声明除degress之外的单位。角度值默认无单位,默认单位是度。

    可选的cxcy值代表无单位的旋转中心点。如果没有设置cxcy,旋转点是当前用户坐标系的原点(查看第一部分如果你不知道用户坐标系是什么。)

    在函数rotate()中声明旋转中心点一个快捷方式类似于CSS中设置transform: rotate()transform-origin。SVG中默认的旋转中心是当前使用的用户坐标系的左上角,这样也许你无法创建想要的旋转效果,你可以在rotate()中声明一个新的中心点。如果你知道元素在SVG画布中的尺寸和定位,你可以把它的中心设置为旋转中心。

    下面的例子是以当前用户坐标系中的(50,50)点为中心进行旋转一组元素:

    XHTML

    <g id="parrot" transform="rotate(45 50 50)" x="0" y="0"> <!-- elements making up a parrot shape --> </g>

    1
    2
    3
    <g id="parrot" transform="rotate(45 50 50)" x="0" y="0">
        <!-- elements making up a parrot shape -->
    </g>

    然而,如果你想要一个元素围绕它的中心旋转,你也许想要像CSS中一样声明中心为50% 50%;不幸的是,在rotate()函数中这样做是不允许的-你必须用绝对坐标。然而,你可以在CSS的transform属性中使用transform-origin属性。这篇文章后面会讨论更多细节。

    六、其他居中变换处理

    像缩放、斜切这些SVG变换,想要如CSS transform-origin:50% 50%一样的中心点变换效果,需要事先位移,我们有没有其他办法呢?

    这里有两个思路可供大家参考下。

    1. 原始中心位置乃SVG左上角
    拿45度旋转举例,我们可以把元素默认就放在中心点和SVG左上角重合的位置上,参见下面的gif演示:澳门新葡8455最新网站 21

    于是,我们原来的3步曲就变成了2步曲:

    CSS

    translate(140 105) rotate(45) translate(-140 -105) → translate(140 105) rotate(45)

    1
    translate(140 105) rotate(45) translate(-140 -105) → translate(140 105) rotate(45)

    2. 通过viewBox调整
    viewBox可以用来改变SVG画布的视区,这个我之前专门撰文介绍过,是SVG学习必备被深入理解的基础知识,参见:“理解SVG的viewport,viewBox,preserveAspectRatio”一文。

    我们可以把元素默认挂在左上角,然后,通过viewBox做手脚,让元素呈现的位置并不是真正的左上角,例如应用viewBox='-140 -105 280 210',则变化如下示意图:

    澳门新葡8455最新网站 22

    此时,我们只需要让元素旋转就可以了,无需额外的做translate位移,见下gif:澳门新葡8455最新网站 23

    坐标系变化

    现在我们已经讨论了所有可能的SVG变换函数,我们深入挖掘视觉部分和对SVG元素添加每个变换的效果。这是SVG变换最重要的部分。因此它们被称为“坐标系统变换”而不仅仅是“元素变换”。

    在这个说明中,transform属性被定义成两个在被添加的元素上建立新用户空间(当前坐标系)之一-viewBox属性是创建新用户空间的两个属性中的另一个。所以到底是什么意思呢?

    这个行为类似于在HTML元素上添加CSS变换-HTML元素坐标系发生了变换,当你把变换组合使用时最明显。虽然在很多方面很相似,HTML和SVG的变换还是有一些不同。

    澳门新葡8455最新网站,主要的不同是坐标系。HTML元素的坐标系建立在元素自身智商。然而,在SVG中,元素的坐标系最初是当前坐标系或使用中的用户空间。

    当你在一个SVG元素上添加transform属性,元素获取当前使用的用户坐标系的一个“副本”。你可以当做给发生变换的元素创建一个新“层”,新层上是当前用户坐标系的副本(the viewBox)。

    然后,元素新的当前坐标系被在transform属性中声明的变换函数改变,因此导致元素自身的变换。这看起来好像是元素在变换后的坐标系中重新绘制。

    要理解如何添加SVG变换,让我们从可视化的部分开始。下面图片是我们要研究的SVG画布。

    澳门新葡8455最新网站 24

    鹦鹉和小狗使我们要变换的元素(组<g>)。

    XHTML

    <svg width="800" height="800" viewBox="0 0 800 600"> <g id="parrot"> <!-- shapes and paths forming the parrot --> </g> <g id="dog"> <!-- shapes and paths forming the dog --> </g> </svg>

    1
    2
    3
    4
    5
    6
    7
    8
    <svg width="800" height="800" viewBox="0 0 800 600">
        <g id="parrot">
            <!-- shapes and paths forming the parrot -->
        </g>
        <g id="dog">
            <!-- shapes and paths forming the dog -->
        </g>
    </svg>

    灰色坐标是通过viewBox建立的画布的初始坐标系。为了方便起见,我将不改变初始坐标系-我用一个和视窗相同尺寸的viewBox,如你在上述代码中看到的一样。

    现在我们建立了画布和初始用户空间,让我们开始变换元素。首先让我们把鹦鹉向左移动150单位,向下移动200个单位。

    当然,鹦鹉是由若干路径和形状组成的。只要把transform属性添加到包含它们的组<g>上就行了;这会对整个形状和路径添加变换,鹦鹉会作为一个整体进行变换。查看 article on structuring and grouping SVGs获取更多信息。

    XHTML

    <svg width="800" height="800" viewBox="0 0 800 600"> <g id="parrot" transform="translate(150 200)"> <!-- shapes and paths forming the parrot --> </g> <!-- ... --> </svg>

    1
    2
    3
    4
    5
    6
    <svg width="800" height="800" viewBox="0 0 800 600">
        <g id="parrot" transform="translate(150 200)">
            <!-- shapes and paths forming the parrot -->
        </g>
        <!-- ... -->
    </svg>

    下面图片展示了上述变换后的结果。鹦鹉的半透明版本是变换前的初始位置。澳门新葡8455最新网站 25

    SVG中的变换和HTML元素上CSS中的一样简单直观。我们之前提到在元素上添加transform属性时会在元素上创建一个新的当前用户坐标系。下面图片显示了初始坐标系的“副本”,它在鹦鹉元素发生变换时被建立。注意观察鹦鹉当前坐标系是如何变换的。澳门新葡8455最新网站 26

    这里需要注意的非常重要的一点是建立在元素上的新的当前坐标系是初始用户坐标系的复制,在里面元素的位置得以保持。这意味着它不是建立在元素边界盒上,或者新的当前坐标系的尺寸受制于元素的尺寸。这就是HTML和SVG坐标系之间的区别。

    建立在变换元素上的新当前坐标系不是建立在元素边界盒上,或者新的当前坐标系的尺寸受制于元素的尺寸。

    我们把小狗变换到画布的右下方时会更加明显。试想我们想要把小狗向右移动50单位,向下移动50单位。这就是狗的最初的坐标以及新的当前坐标系(也因为狗改变)会如何显示。注意小狗的新的坐标系统的原点不在狗边界盒子的左上角。另外注意狗和它新的坐标系看起来它们好像移动到画布新的一层上。澳门新葡8455最新网站 27

    现在我们试一试其他事情。不再移动,试着缩放。我们将鹦鹉放大到两倍尺寸:

    XHTML

    <svg width="800" height="800" viewBox="0 0 800 600"> <g id="parrot" transform="scale(2)"> <!-- shapes and paths forming the parrot --> </g> <!-- ... --> </svg>

    1
    2
    3
    4
    5
    6
    <svg width="800" height="800" viewBox="0 0 800 600">
        <g id="parrot" transform="scale(2)">
            <!-- shapes and paths forming the parrot -->
        </g>
        <!-- ... -->
    </svg>

    放缩SVG元素和放缩HTML元素的结果不一样。缩放后SVG元素的在视窗中的位置随着缩放改变。下面图片展示了把鹦鹉放大到两倍时的结果。注意初始位置和尺寸,以及最终位置和尺寸。澳门新葡8455最新网站 28

    从上面图片中我们可以注意到不只鹦鹉的尺寸(宽和高)变成了两倍,鹦鹉的坐标(xy)也乘以了缩放因子(这里是两倍)。

    这个结果的原因我们之前已经提到了:元素当前坐标系发生变化,鹦鹉在新系统中绘制。所以,在这个例子中,当前坐标系被缩放。这个效果类似于使用viewBox = "0 0 400 300",等于“放大”了坐标系,因此把里面的内容放大到双倍尺寸(如果你还没有读过请查看这个系列的第一部分)。

    所以,如果我们把坐标系变换形象化来展现当前变换系统中的鹦鹉,我们会得到以下结果:澳门新葡8455最新网站 29

    鹦鹉的新的当前坐标系统被缩放,同时“放大”鹦鹉。注意,在它当前的坐标系中,鹦鹉没有重新定位-只有缩放坐标系统才会导致它在视窗中重定位。鹦鹉在新的缩放后的系统中按初始的xy坐标被重绘。

    让我们尝使用不同因子在两个方向上缩放鹦鹉。如果我们添加transform="scale(2 0.5)缩放鹦鹉,我们把宽度变为两倍高度为原来的一半。效果和添加viewBox="0 0 400 1200"类似。澳门新葡8455最新网站 30

    注意一下鹦鹉在倾斜后的坐标系中的位置,并且把它和初始系统(半透明的鹦鹉)中的位置做比较:xy位置坐标保持不变。

    在SVG中倾斜元素也导致元素被“移动”,因为它当前的坐标系统被倾斜了。

    试想我们使用skewX函数沿x轴给一只狗增加一个倾斜变化。我们在垂直方向上把狗倾斜了25度。

    XHTML

    <svg width="800" height="800" viewBox="0 0 800 600"> <!-- ... --> <g id="dog" transform="skewX(25)"> <!-- shapes and paths forming the dog --> </g> </svg>

    1
    2
    3
    4
    5
    6
    <svg width="800" height="800" viewBox="0 0 800 600">
        <!-- ... -->
        <g id="dog" transform="skewX(25)">
            <!-- shapes and paths forming the dog -->
        </g>
    </svg>

    下列图片展示了对小狗添加倾斜变换的结果。澳门新葡8455最新网站 31

    注意到狗的位置对比初始位置也改变了,因为它的坐标系也被倾斜了。

    下面的图片展示了同样角度的情况下使用skewY()而不是skewX倾斜狗的情况:澳门新葡8455最新网站 32

    最后,让我们尝试旋转鹦鹉。旋转默认的中心是当前用户坐标系的左上角。新的建立在旋转元素上的当前系统也被旋转了。在下面的例子中,我们将把鹦鹉旋转45度。旋转方向为顺时针。

    XHTML

    <svg width="800" height="800" viewBox="0 0 800 600"> <g id="parrot" transform="rotate(45)"> <!-- shapes and paths forming the parrot --> </g> <!-- ... --> </svg>

    1
    2
    3
    4
    5
    6
    <svg width="800" height="800" viewBox="0 0 800 600">
        <g id="parrot" transform="rotate(45)">
            <!-- shapes and paths forming the parrot -->
        </g>
        <!-- ... -->
    </svg>

    添加上述变换的结果如下:澳门新葡8455最新网站 33

    你很可能想要围绕默认坐标系原点之外的点来旋转一个元素。在transform属性中使用rotate()函数,你可以声明这个点。试想在这个例子中我们想按照它自己的中心旋转这个鹦鹉。根据鹦鹉的宽、高以及位置,我精确计算出它的中心在(150,170)。这个鹦鹉可以围着它的中心旋转。

    XHTML

    <svg width="800" height="800" viewBox="0 0 800 600"> <g id="parrot" transform="rotate(45 150 170)"> <!-- shapes and paths forming the parrot --> </g> <!-- ... --> </svg>

    1
    2
    3
    4
    5
    6
    <svg width="800" height="800" viewBox="0 0 800 600">
        <g id="parrot" transform="rotate(45 150 170)">
            <!-- shapes and paths forming the parrot -->
        </g>
        <!-- ... -->
    </svg>

    在这个时候,这只鹦鹉会被旋转并且看起来如下:澳门新葡8455最新网站 34

    我们说变换添加在坐标系上,因此,元素最终被影响并且发生变换。那么究竟如何改变旋转中心工作在坐标系的原点(0,0)的点呢?

    当你改变中心或者旋转时,坐标系被变换或者旋转特定角度,然后再次根据声明的旋转中心产生特定变换。在这个例子中:

    XHTML

    <g id="parrot" transform="rotate(45 150 170)">

    1
    <g id="parrot" transform="rotate(45 150 170)">

    被浏览器当成一系列的移动和旋转等同于:

    XHTML

    <g id="parrot" transform="translate(150 170) rotate(45) translate(-150 -170)">

    1
    <g id="parrot" transform="translate(150 170) rotate(45) translate(-150 -170)">

    当前坐标系变换到你想要的中心店。然后旋转声明的角度。最终系统被负值变换。上述添加到系统的变换如下:澳门新葡8455最新网站 35

    在我们进行下一部分讨论嵌套和组合变换前,我想请大家注意建立在变换元素上的当前用户坐标系是独立于建立在其他变换元素之上的其他坐标系的。下列图片展示了建立在狗和鹦鹉上的两个坐标系,以及它们之间是如何保持独立的。澳门新葡8455最新网站 36

    另外注意每个当前坐标系仍然处于在外层<svg>容器中使用viewBox属性建立的画布的主要坐标系中。任何添加到viewBox上的变换会影响整个画布以及所有里面的元素,不管它们是否建立了自己的坐标系。

    例如,以下是把整个画布的用户空间从viewBox="0 0 800 600"改成 viewBox="0 0 600 450"的结果。整个画布被缩放,保持任何添加到独立元素上的变换。澳门新葡8455最新网站 37

    七、结束语

    本文介绍的内容实际上都还是非常基本的。实际SVG应用的时候,可能是多个变换参杂在一起,所以,如果本文介绍的几个基本变换都没搞清楚,到时候,想必是想破脑袋都不明白怎么元素跑这里了,怎么变成这样了!

    本文的这些知识点虽然基本,但是相当重要的。再加上,不同的变换方法的语法细节还不一样。有的自带偏移,有的需要手动偏移等等;不同变换的前后位置不同,甚至同一变换分开连续变换和一次性变换的结果都不一样等等;都要求大家要细心耐心阅读。

    本文内容和结构参考自:Transforms on SVG Elements. 但要比原文要精炼很多,同时,每一个变换都有亲自实践认证,因此,从品质上讲,可能还要略高一筹。

    对了,矩阵matrix没有细说过,这个可以参考我之前的文章:“理解CSS3 transform中的Matrix(矩阵)”,一脉相承的。

    我也是初学者,出错在所难免,欢迎指正!

    感谢阅读,欢迎交流!澳门新葡8455最新网站 38

    1 赞 收藏 评论

    澳门新葡8455最新网站 39

    嵌套和组合变换

    很多时候你可能想要在一个元素上添加多个变换。添加多个变换意味着“组合”变换。

    当变换组合时,最重要的是意识到,和HTML元素变换一样,当这个系统发生了之前的变换后在添加下一个变换到坐标系中。

    例如,如果你要在一个元素上添加旋转,接下来移动,移动变换会根据新的坐标系统,而不是初始的没有旋转时的系统。

    下面了例子就是做了这件事。我们先添加旋转,然后沿x轴使用transform="rotate(45 150 170) translate(200)"把鹦鹉移动200个单位。澳门新葡8455最新网站 40

    取决于最终的位置和变换,你可以根据需要组合变换。总是记住坐标系。

    注意当你倾斜一个元素-以及它的坐标系统-坐标系统不再是最初的那个,坐标系不再会按照最初的来计算-它将会是倾斜后的坐标系。简单来说,这意味着坐标系原点不再是90度的角,新的坐标会根据新的角度来计算。

    当变换元素的子元素也需要变换时会发生变换嵌套。添加到子元素上的变换会累积父元素上添加的变换和它本身的变换。

    所以,效果上来说,嵌套变化类似于组合:唯一区别是不像在一个元素上添加一系列的变化,它自动从父元素上获得变换,最后执行添加在它自身的变换,就像我们在上面添加的变换一样-一个接一个。

    这对于你想要根据另外一个元素变换一个元素时尤其有用。例如,试想你想要给小狗的尾巴设定一个动画。这个尾巴是#dog组的后代。

    XHTML

    <svg width="800" height="800" viewBox="0 0 800 600"> <!-- ... --> <g id="dog" transform="translate(..)"> <!-- shapes and paths forming the dog --> <g id="head"> <!-- .. --> </g> <g id="body" transform="rotate(.. .. ..)"> <path id="tail" d="..." transform="rotate(..)"> <!-- animateTransform here --> </path> <g id="legs"> <!-- ... --> </g> </g> </g> </svg>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <svg width="800" height="800" viewBox="0 0 800 600">
        <!-- ... -->
        <g id="dog" transform="translate(..)">
            <!-- shapes and paths forming the dog -->
            <g id="head">
                <!-- .. -->
            </g>
            <g id="body" transform="rotate(.. .. ..)">
                <path id="tail" d="..." transform="rotate(..)">
                    <!-- animateTransform here -->
                </path>
                <g id="legs">
                    <!-- ... -->
                </g>
            </g>
        </g>
    </svg>

    试想我们变换dog组;围绕某一点把它的身体旋转一定角度,然后我们想要再把尾巴旋转一定角度。

    当尾巴被旋转后,它从祖先(#body)身上“继承”了变换坐标系,也从祖先(#dog)身上继承了变换坐标系,然后旋转(和#body组一样的旋转)然后在发生自身的旋转。这里添加的一系列变换的效果类似于我们之前在上述组合变换例子中解释的。

    所以,你看,在#tail上嵌套变换实际上和组合变换有一样的效果。

    使用CSS属性变换SVGs

    在SVG2中,transform属性简称transform属性;因为SVG变换已经被引入CSS3变换规范中。后者结合了SVG变化,CSS2 2D变换和CSS 3D变换规范,并且把类似transform-origin 和 3D transformations引入了SVG。

    声明在CSS变换规范中的CSS变换属性可以被添加到SVG元素上。然而,transform属性函数值需要遵循CSS规范中的语法声明:函数参数必须逗号隔开-空格隔开是不允许的,但是你可以在逗号前后引用一两个空格;rotate()函数不接受<cx><cy>值-旋转中心使用transform-origin属性声明。另外,CSS变换函数接受角度和坐标单位,例如角度的rad(radians)和坐标的px,em等。

    使用CSS来旋转一个SVG元素看起来如下:

    CSS

    #parrot { transform-origin: 50% 50%; /* center of rotation is set to the center of the element */ transform: rotate(45deg); }

    1
    2
    3
    4
    #parrot {
        transform-origin: 50% 50%; /* center of rotation is set to the center of the element */
        transform: rotate(45deg);
    }

    SVG元素也可以使用CSS 3D变换在三维空间中变换。依然要注意坐标系,然而,不同于建立在HTML元素上的坐标系。这意味着3D旋转看起来也不同除非改变旋转中心。

    CSS

    #SVGel { transform: perspective(800px) rotate3d(1, 1, 0, 45deg); }

    1
    2
    3
    #SVGel {
        transform: perspective(800px) rotate3d(1, 1, 0, 45deg);
    }

    因为通过CSS来变换SVG元素非常类似于通过CSS来变换HTML元素-语法层面-在这篇文章中我将跳过这个部分。

    另外,在写这篇文章的时候,在一些浏览器中实现一些特性是不可能的。因为浏览器支持改变很快,我建议你实验一下这些属性来决定哪些可以工作哪些不可以,决定什么现在可以用什么不可以。

    注意一旦CSS变换可以完全实现在SVG上,我依然建议你使用CSS变换函数语法即使你用transform属性的形式添加变换。也就是说,上面提到的transform属性函数的语法还是有效的。

    动画transform

    SVG变换可以变成动画,就像CSS变换一样。如果你使用CSS transform属性来产生SVG变换,你可以像在HTML元素上创建CSS变换动画一样使用CSS动画把这些变换变成动画。

    SVGtransform属性可以用SVG<animateTransform>元素来做成动画。<animateTransform>元素是SVG中三个用来给不同的SVG属性设置动画的元素之一。

    关于<animateTransform>元素的详细内容不在本片文章的讨论范围内。阅读我写的关于不同SVG动画元素的文章,包括<animateTransform>

    最后的话

    学习SVGs一开始可能非常困惑,如果对于坐标系变换里的内容不是很清楚,尤其是如果你带着CSS HTML变换的背景知识,自然而然希望SVG元素和HTML元素的变换一样。

    然而,一旦你意识到它们的工作方式,你能更好得控制SVG画布,并且轻易操纵元素。

    这一系列的最后部分,我将讨论嵌套SVGs和建立新的viewports和viewboxes。敬请关注!

    1 赞 1 收藏 评论

    澳门新葡8455最新网站 41

    本文由澳门新葡8455最新网站发布于Web前端,转载请注明出处:澳门新葡8455最新网站了解SVG坐标种类和改动,

    关键词: