缩放和镜像SVG对象。

97

如何最简单地将一个对象缩放,例如将其当前大小增加2倍,然后垂直和水平翻转或同时进行?

目前,我可以通过设置“scale(2,2)”来使其宽度和高度变大两倍,但我无法在同时进行垂直翻转使用“scale(-1,1)”。

我正在以编程方式创建SVG对象,作为导出格式。


11
现在所需的只有 transform: scale(-1, 1); transform-origin: center; - brandito
2
@brandito 在 scale 后面有一个不必要的空格。 - Ian Y.
5个回答

158

要同时应用缩放和翻转,请在你的变换中列出它们:

transform="scale(2,2) scale(-1,1)"

或者简单地将这些值组合起来:

transform="scale(-2,2)"
当然,使用负比例尺的问题在于对象会在SVG的原点(左上角)的另一侧翻转,导致它们可能超出文档的边缘。你需要通过添加平移操作来纠正这个问题。
因此,例如,想象一下我们有一个100×100的文档。
<svg width="100" height="100">
    <polygon points="100,0,100,100,0,100"/>
</svg>

要垂直翻转,请执行以下操作:

<polygon points="100,0,100,100,0,100" transform="scale(2,-2)"/>

为了纠正屏幕外的运动,你可以选择以下两种方式之一:

(选项1) 在翻转之前向负方向移动它(这样它就会被翻转回来显示在屏幕上):


(选项1)在翻转之前将其向负方向移动(这样它将被翻转回屏幕上)。
<polygon points="100,0,100,100,0,100" transform="scale(2,-2) translate(0,-100)"/>

(将翻译列在此处是因为转换列表按从右到左的顺序有效应用)

(选项2)或者,您可以在缩放后将其向正方向移动(按比例大小):

<polygon points="100,0,100,100,0,100" transform="translate(0,200) scale(-2,2)"/>

这里是一个演示,展示了垂直翻转、水平翻转和两种翻转的效果

更新

要在屏幕上某个已存在的对象中执行翻转(位置不变),首先确定其边界框(minX, minY, maxX, maxY)或者如果您已经知道centreX, centreY的话,则用它们代替。

然后在其变换之前加入以下内容:

translate(<minX+maxX>,0) scale(-1, 1)   // for flip X
translate(0,<minY+maxY>) scale(1, -1)   // for flip Y

或者如果你有中心,你可以使用它

translate(<2 * centreX>,0) scale(-1, 1)   // for flip X

所以以您的例子为例:

<rect x="75" y="75" width="50" height="50"  transform="translate(-100, -100) scale(2, 2) scale(1, 1) rotate(45, 100, 100)" />

minX+maxX之和为200。因此,要水平翻转,我们在其前面添加:

translate(200,0) scale(-1, 1)

所以最终的对象变成:

<rect x="75" y="75" width="50" height="50"  transform="translate(200,0) scale(-1, 1) translate(-100, -100) scale(2, 2) scale(1, 1) rotate(45, 100, 100)" />

这里演示


这很有帮助。但我仍然有困难,无法弄清楚如何以SVG格式正确保存它们。在每个对象上,您可以:垂直镜像或水平镜像。其中,垂直线是宽度的一半,而水平线则在高度的一半处。在左侧绘制了某些内容后,它应该出现在右侧。这很简单,直到每个对象被缩放或未缩放,从其原始的“x”和“y”=平移或旋转。我不确定如何将其制作成SVG变换属性。我知道对象的中心,文档的大小等信息以及Transform、Scale、Rotate值+ V或H镜像。 - Deukalion
你当然回答了这个问题,这只是一个扩展问题,把所有的问题都解决了。现在当这个问题被解决后,我似乎无法将所有其他值放入方程式中。 - Deukalion
翻译 缩放 翻转 旋转 平移?没有特定的顺序。在文档中给定坐标创建一个矩形,将其旋转一些度数,移动一些坐标,将其缩放到与原始大小不同的尺寸,最后将其全部翻转,使其垂直翻转或水平翻转或两者兼而有之。唯一的问题是将我的值转换为SVG格式。当然,正如我可能之前所述,其中一个这些值不需要包含,也许每个值都有不同的情况。比如我排除旋转或缩放;在SVG格式中可能看起来不同。 - Deukalion
我想我解决了它。将所有内容映射出来。我从中制定了一些算法。也许这个链接可以更好地解释:http://pastebin.com/z7PDbusN - Deukalion
谢谢。我错过了您在帖子上进行的更新 - 网站并没有告诉你这个。无论如何,现在似乎可以正常工作了。唯一剩下的问题是文本,因为每个TextSpan似乎都需要单独进行转换。 - Deukalion
显示剩余8条评论

49

只需在SVG的路径标签中添加以下属性即可

transform="scale (-1, 1)" transform-origin="center"

例如:<path transform="scale(-1, 1)" transform-origin="center" ......./>


6
为什么这没有得到更多的投票?似乎避免了不必要的“翻译”复杂性。 - Tunn
这对我在编辑SVG文件方面非常有效。非常出色的快速回答。 - Chris - Jr
1
这可以直接应用于<svg,以防有人试图将其应用于每个路径。 - titusfx

19

来见见我们的企鹅“Tux”。为了这个练习,我在他的脚上画了字母“L”和“R”。

Tux the pinguin

首先,让我们把Tux画在我们画布的中心。如果画布的大小为500x500,而Tux的大小为100x100,我们必须将它定位在(200,200)(即中心减去一半的大小。)

  <svg width="500" height="500">
    <!-- marking our border and a cross through the center -->
    <rect x="0" y="0" width="500" height="500" stroke-width="2" stroke="red" fill="none"></rect>
    <line x1="0" y1="0" x2="500" y2="500" stroke="red" stroke-width="2"></line>
    <line x1="500" y1="0" x2="0" y2="500" stroke="red" stroke-width="2"></line>

    <!-- our pinguin in the center -->
    <image x="200" y="200" width="100" height="100" href="assets/pinguin.png"></image>
  </svg>

The result

现在,如果我们想水平翻转我们的企鹅(左右交换),很容易就会使用 scale(-1 1) 进行变换。然而,当我们尝试这样做时,我们的企鹅就会消失。

  <svg width="500" height="500">
    ...
    <image ... transform="scale(-1 1)"></image>
  </svg>

pinguin is gone

原因是我们的变换默认反射点(所谓的“转换原点”)不在图像中心,而实际上仍然在(0,0)点。

最明显的解决方案是将反射点移动到图像中心(250,250)。(在这种情况下,我们画布的中心)。

  <svg width="500" height="500">
    ...
    <image ... transform="scale(-1 1)" transform-origin="250 250"></image>
  </svg>

更改变换原点

缩放的方法完全相同。 你可以使用两个比例尺进行操作,也可以将它们结合成一个比例尺。

  <svg width="500" height="500">
    <!-- use 2 scales -->
    <image x="200" y="200" width="100" height="100" href="assets/pinguin.png"
           transform="scale(-1 1) scale(2 2)" transform-origin="250 250">
    </image>    
    <!-- or just multiply the values of both scales -->
    <image x="200" y="200" width="100" height="100" href="assets/pinguin.png"
           transform="scale(-2 2)" transform-origin="250 250">
    </image>
  </svg>

还是只有两个选项


1
没有一个解决方案适用于我,我将发布我发现的内容:
您可以使用矩阵或类似CSS的转换。它们的行为不同。
看一下这个非常基本的示例,其中包含一个原始形状和不同的水平翻转方式。请注意,根据翻译(您可能希望将其保留在相同的x轴上)和您使用的转换类型,您需要设置不同的x轴转换。
观察:
- 矩阵
- 相同位置(浅绿色):使用正面宽度大小进行翻译。 - X翻译(深绿色):期望的行为(与浅绿色相同)。
- 类似CSS的
- 相同位置(浅蓝色):使用负宽度大小进行翻译,并放置在缩放后。相反的顺序超出了viewBox(请注意粉色形状)。 - X翻译(深蓝色):使用负宽度大小加正翻译进行翻译,并放在缩放之前。相反的顺序超出了viewBox(请注意橙色形状)。

<svg 
  viewBox="0 0 15 30" 
  width="150" 
  height="300" 
  xmlns="http://www.w3.org/2000/svg"
>
  <defs>
    <path 
      id="triangle"
      d="M0,5 l5,5 V0z" 
    />
  </defs>
  <use 
    href="#triangle"
    fill="red" 
  />
  <use
    y="5"
    href="#triangle"
    transform="scale(-1, 1) translate(-5, 0)"
    fill="lightBlue" 
  />
  <use
    y="5"
    href="#triangle"
    transform="translate(-5, 0) scale(-1, 1)"
    fill="pink" 
  />
  <use
    y="15"
    href="#triangle"
    transform="matrix(-1 0 0 1 5 0)"
    fill="lightGreen" 
  />
  <use
    href="#triangle"
    transform="translate(10, 0) scale(-1, 1)"
    fill="darkBlue" 
  />
  <use
    href="#triangle"
    transform="scale(-1, 1) translate(10, 0)"
    fill="orange" 
  />
  <use
    href="#triangle"
    transform="matrix(-1 0 0 1 15 0)"
    fill="darkGreen" 
  />
</svg>


0

这里是Livescript-ish代码片段,展示如何水平翻转和按任意因子缩放:

    # scale is 1 by default

    if mirror or scale isnt 1
        [minx, miny, width, height] = svg.attributes.viewBox |> split-by ',' |> cast-each-as (Number)

        s = scale
        # container is the root `g` node 
        container.attributes.transform = if mirror
            "translate(#{s * (width + minx) + minx}, #{-miny * (s-1)}) scale(#{-s},#{s})"
        else
            "translate(#{-minx * (s-1)}, #{-miny * (s-1)}) scale(#{s},#{s})"

        if scale isnt 1
            svg.attributes
                ..viewBox = "#{minx},#{miny},#{width * scale},#{height * scale}"
                ..width = "#{width * scale}"
                ..height = "#{height * scale}"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接