transform:表示对图形进行平移、旋转、缩放等形变
svg的形变和css的形变用的都是transform,而且属性也几乎没差(是几乎)。
如下:
translate
transform="translate(x-value, y-value)"
简单来说,就是偏移。沿x轴方向偏移x-value个单位长度,沿y轴方向偏移y-value个单位长度。
<symbol id="rect">
<line x1="0" y1="0" x2="300" y2="0" stroke="grey"></line>
<line x1="0" y1="0" x2="0" y2="150" stroke="grey"></line>
<rect x="20" y="20" width="50" height="50"></rect>
</symbol>
<use xlink:href="#rect" stroke="grey" fill="none"></use>
<use xlink:href="#rect" transform="translate(100,50)" stroke="black" fill="none"></use>
复杂来说,svg处理偏移的时候,其实是对元素所在的坐标系做整体偏移。那上面例子来说,#rect内的所有元素在偏移后,坐标数值没有变化,两条代表坐标轴线的直线起始位置还是(0,0)。只是这个(0,0)所在的坐标系已经被偏移到了原坐标系的(100,50)位置。
scale
transform="scale(x-value, y-value)"
简单来说,就是缩放。x轴方向上的长度变为原来的x-value倍,y轴方向上的长度变为原来的y-value倍。允许只有一个参数scale(n),表示x和y轴方向上的长度同时变为原来的n倍。
<line x1="0" y1="0" x2="150" y2="0" stroke="grey"></line>
<line x1="0" y1="0" x2="0" y2="150" stroke="grey"></line>
<symbol id="rect">
<rect x="20" y="20" width="50" height="50" stroke-width="5"></rect>
</symbol>
<use xlink:href="#rect" stroke="grey" fill="none"></use>
<use xlink:href="#rect" transform="scale(2,2)" stroke="black" fill="none"></use>
复杂来说,缩放的并不是元素本身的长度,而是原来的单位长度。上例中的正方形不仅自身变大了一倍,而且发生了偏移。就是说,rect所有的属性值都变成了原来的2倍,包括作为起点坐标的x和y、作为宽度长度的width和height,还有作为线条粗细值得stroke-width。
rotate
transform="rotate(angle,[centerX, centerY])"
默认以坐标系中(0,0)原点为圆心,顺时针旋转angle度。0度为水平从左向右方向。
<line x1="0" y1="0" x2="200" y2="0" stroke="grey"></line>
<line x1="0" y1="0" x2="0" y2="200" stroke="grey"></line>
<symbol id="rect">
<polygon points="50 10, 100 10, 150 60, 100 60"></polygon>
</symbol>
<use xlink:href="#rect" stroke="grey" fill="none"></use>
<use xlink:href="#rect" transform="rotate(45)" stroke="black" fill="none"></use>
rotate的第二和第三个参数为可选参数,用于指定旋转中心坐标,默认即为0,0。所以如果向让某个元素围绕自己的中点旋转,只要以它的中点坐标的x和y值作为第二和第三个参数即可。
<line x1="0" y1="0" x2="150" y2="0" stroke="grey"></line>
<line x1="0" y1="0" x2="0" y2="150" stroke="grey"></line>
<symbol id="rect2">
<rect x="50" y="50" width="50" height="50"></rect>
</symbol>
<use xlink:href="#rect2" stroke="grey" fill="none"></use>
<use xlink:href="#rect2" transform="rotate(45, 75, 75)" stroke="black" fill="none"></use>
skewX和shewY
transform="skewX(angle) skewY(angle)"
skewX和shewY可以使x轴和Y轴歪斜
<line x1="0" y1="0" x2="300" y2="0" stroke="grey" stroke-dasharray="5 5"></line>
<line x1="0" y1="0" x2="0" y2="200" stroke="grey" stroke-dasharray="5 5"></line>
<g transform="skewX(45)" stroke-width="10" stroke="grey">
<line x1="0" y1="0" x2="100" y2="0" ></line>
<line x1="0" y1="0" x2="0" y2="100"></line>
<text x="0" y="110" stroke-width="1" stroke="black">skewX</text>
</g>
<g transform="translate(175) skewY(45)" stroke-width="10" stroke="grey">
<line x1="0" y1="0" x2="100" y2="0"></line>
<line x1="0" y1="0" x2="0" y2="100"></line>
<text x="0" y="110" stroke-width="1" stroke="black">skewY</text>
</g>
直观感受是,用了skewX,变歪的却是y轴。我觉得可以这么理解,上例中代表y轴直线起始位置的(0,0)和结束位置的(0,100)两个坐标,x轴坐标没有改变,但形成的直线却不是一条笔直的竖线。被歪斜过后的坐标(0,100)位置处于原坐标系中(100,100)的位置,被歪斜的是x的坐标。
书里没提歪斜角度的问题,简单做了几个demo,得出的结论还挺简单的(不知道是不是因为简单所以书里懒得写了。。。所以想了想也不写了,自己做demo试试看就懂了,角度可以是负数,可以超过90度)
形变的次序
transform="translate(100,100) scale(2)"和transform="scale(2) translate(100,100)"形变后的结果是否完全一致?
如果弄清楚了“复杂来说”的transform和scale,应该不难得出结论。
<svg height="300" width="300">
<line x1="0" y1="0" x2="200" y2="0" stroke="grey"></line>
<line x1="0" y1="0" x2="0" y2="150" stroke="grey"></line>
<symbol id="rect">
<rect x="20" y="20" width="50" height="50"></rect>
</symbol>
<use xlink:href="#rect" stroke="grey" fill="none"></use>
<use xlink:href="#rect" transform="translate(50,25) scale(2)" stroke="black" fill="none"></use>
</svg>
<svg height="300" width="300">
<line x1="0" y1="0" x2="300" y2="0" stroke="grey"></line>
<line x1="0" y1="0" x2="0" y2="150" stroke="grey"></line>
<symbol id="rect">
<rect x="20" y="20" width="50" height="50"></rect>
</symbol>
<use xlink:href="#rect" stroke="grey" fill="none"></use>
<use xlink:href="#rect" transform="scale(2) translate(50,25)" stroke="black" fill="none"></use>
</svg>
transform="translate(50,25) scale(2)"是先将rect所在坐标系的原点偏移至(50,25),再将单位长度放大两倍,等同于在原坐标中画这样一个正方形:
<rect x="50+2*20" y="25+2*20" width="2*50" height="2*50" stroke="black" fill="none"></rect>(将计算结果代入即可运行)
transform="scale(2) translate(50,25)"是先将单位长度放大两倍,再将rect所在坐标系原点偏移至放大后坐标系的(50,25),等同于:
<rect x="2*(50+20)" y="2*(25+20)" width="2*50" height="2*50" stroke="black" fill="none"></rect>(将计算结果代入即可运行)
所以再使用联合形变的时候,顺序弄错导致的结果就会出问题。