SVG的坐标系变换transform的translate,scale,skew,rotate转换
2017-03-16 00:43

svg的坐标系

svg的坐标系没有单位,只有数值,你可以认为他就是相对单位,正因为如此才能造就svg的可缩放不失真的矢量图形特性。

svg的坐标系跟web页面的坐标系是一样的,都是左上角为0,0原点,x轴向右延伸,y轴向下延伸。

blob.png

我们先用svg代码实现一个粗糙的坐标刻度线,每个刻度间隔为10个单位。

<svg width="200" height="200" viewBox="0 0 200 200">
    <g>
    <rect x="5" y="5" fill="none" stroke="#FBEE1E" stroke-width="5" width="190" height="190"></rect>
        <path d="M10,5L10,20 M20,5L20,20 M30,5L30,20 M40,5L40,20 
        M50,5L50,20 M60,5L60,20 M70,5L70,20 M80,5L80,20 M90,5L90,20
         M100,5L100,20 M110,5L110,20 M120,5L120,20 M130,5L130,20 
         M140,5L140,20 M150,5L150,20 M160,5L160,20 M170,5L170,20 M180,5L180,20
         M190,5L190,20" stroke-width="1" stroke="#F33030">
        </path>
        <path d="M5,10L20,10 M5,20L20,20 M5,30,L20,30 M5,40L20,40 M5,50L20,50 
        M5,60L20,60 M5,70L20,70 M5,80L20,80 M5,90L20,90 M5,100L20,100
        M5,110,L20,110 M5,120L20,120 M5,130L20,130 M5,140L20,140 
        M5,150L20,150 M5,160L20,160 M5,170L20,170 M5,180L20,180 M5,190L20,190 M5,200L20,200"
                stroke-width="1" stroke="#F33030">
        </path>
    </g>
</svg>

代码如上,就是画了一个方块,然后用path画了N多短线。为了简便,就没有标注刻度值了。

有了坐标系的形象模型,下面我们来看SVG的transform变换。

svg Transform变换

网上有很多关于svg的transfrom变换讲解。网上的讲解也看过几篇,但是感觉都有点照本宣科的意味,


主要的不同是坐标系。HTML元素的坐标系建立在元素自身之上。然而,在SVG中,元素的坐标系最初是当前坐标系或使用中的用户空间。

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

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

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
原文: http://www.w3cplus.com/html5/svg-transformations.html © w3cplus.com

上面是从其他网站摘录的一段描述SVG坐标系的变换,和HTML中的CSS变换进行比较,意图很明显,就是想借着大家都CSS得transform变换的熟悉来引导大家更好的理解SVG的变换。目的是好的,但是呢,这段文字的描写,实在让人感到头大。反而阻碍了大家对SVG坐标变换的理解。


下面我按照我的理解,跟大家说说SVG的transfrom变换。

一句话,SVG的transform变换跟CSS的transform变换一样,没有区别,没有不同。
最多就是说有几个注意点而已。

我们先分别用svg和div+css实现两个类似的图形。

blob.png

左边的是SVG实现的,右边的是DIV实现的。基本相同。

transform:translate变换

我们先用translate分别对他们进行变换

//svg变换
<g transform="scale(2,3)">
    <rect x="15" y="15" fill="none" stroke="#14F15D" stroke-width="10" 
    opacity="0.5" width="170" height="170"></rect>
    <circle r="10" cx="50" cy="50" fill="#6AD116"></circle>
</g>

//div的css变换
.css_trans0{
    transform-origin: 0 0;
    transform: translate(50px,50px);
}

效果如下:

blob.png

transform:skew变换

//svg变换
<g transform="skewX(15) skewY(15)">
    <rect x="15" y="15" fill="none" stroke="#14F15D" 
    stroke-width="10" opacity="0.5" width="170" height="170"
            ></rect>
    <circle r="10" cx="50" cy="50" fill="#6AD116"></circle>
</g>

//div的css变换
.css_trans2{
    transform-origin: 0 0;
    transform: skewX(15deg) skewY(15deg);
}

效果如下:

blob.png

transform:rotate(15)变换

//svg变换
<g transform="rotate(15)">
    <rect x="15" y="15" fill="none" stroke="#14F15D" 
    stroke-width="10" opacity="0.5" width="170" height="170"
            ></rect>
    <circle r="10" cx="50" cy="50" fill="#6AD116"></circle>
</g>

//div的css变换
.css_trans3{
    transform-origin: 0 0;
    transform: rotate(15deg);
}

效果如下:

blob.png

transform:rotate(15,50,50)变换

//svg变换
<g transform="rotate(15,50,50)">
    <rect x="15" y="15" fill="none" stroke="#14F15D" 
    stroke-width="10" opacity="0.5" width="170" height="170"
            ></rect>
    <circle r="10" cx="50" cy="50" fill="#6AD116"></circle>
</g>

//div的css变换
.css_trans4{
    transform-origin: 50px 50px;
    transform: rotate(15deg);
}

效果如下:

blob.png

transform:scale变换

//svg变换
<g transform="scale(2,3)">
    <rect x="15" y="15" fill="none" stroke="#14F15D" 
    stroke-width="10" opacity="0.5" width="170" height="170"></rect>
    <circle r="10" cx="50" cy="50" fill="#6AD116"></circle>
</g>

//div的css变换
.css_trans1{
    transform-origin: 0 0;
    transform: scale(2,3);
}

效果如下:

blob.png

svg transform变换的理解

如果从根本上说,上面的引用是对的,svg的变换是针对元素自身的坐标系进行变换的。但这样不好记忆。

从上面我们svg变换和div+css的变换对比可以看出,除了scale变换,其他的变换结果都是相同的。

那么这里我们可以理解为,SVG的变换的transform-origin原点是视窗的左上角0,0。如果CSS的transform-origin也是原点,那么变换结果是一致的。

通常,我们使用CSS变换中的transform都是transform-origin:center center取元素的中心位置。即使是transform-origin:0 0也是取的元素盒子的左上角。

SVG的transform跟CSS变换一样,只是他的transform-origin一直是视窗的原点位置。

这样记忆,SVG的transform变换就好理解了,你就不会再疑问为什么我的svg rotate旋转连元素的位置都变了。


而scale变换中SVG和css有一些差异,那就是css只是变大了,位置没有变;svg中不只变大了,而且位置也偏移了。这个有两种理解方式:

@1:SVG的scale变换针对元素的坐标系,scale放大了坐标系,放大后的一个X轴刻度变为原来X轴刻度的2倍,一个Y轴的刻度变为原来Y轴刻度的3倍,所以向右向下偏移了。(正规理解)

@2:SVG的scale放大缩小,不只放大缩小了元素本身,连带它的位置值也放大了。left值为原来left的2倍,top值为原来top值的3倍。


上面的demo中之所以DIV+CSS的transform变换跟SVG类似,是因为我们将DIV的左上角看作视窗原点对待的。


svg的transform有一个rotate(15,50,50),这个rotate的后两个值,是用来表示这个transform变换的transform-origin原点的位置。根据上面代码中CSS的对应变换样式,可以看出。


原创文章,转载请注明来自:妹纸前端-www.webfront-js.com.
阅读(6653)
辛苦了,打赏喝个咖啡
微信
支付宝
妹纸前端
妹纸前端工作室 | 文章不断更新中
京ICP备16005385号-1