Scale and mirror SVG object

纵饮孤独 提交于 2019-11-26 12:28:42

问题


How do I most easily first scale an object, say 2 * times it\'s current size and then flip it vertically and horizontally, or both?

As of now, I can either set \"scale(2,2)\" for it to become 2 times as big as it\'s width and height but I can\'t flip it at the same with scale(-1, 1) for vertical flip.

I\'m creating SVG objects programmatically, as a format to export to.


回答1:


To apply both scale and flip, just list both in your transform.

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

or simply combine the values

transform="scale(-2,2)"

Of course, the issue you have with negative scales is that the objects get flipped across the origin (top left) of the SVG, so they can go off the edge of the document. You need to correct this by adding a translate as well.

So, for example, imagine we had a document that is 100x100.

<svg width="100" height="100">
    <polygon points="100,0,100,100,0,100"/>
</svg>

To flip this vertically we do:

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

and to correct the movement off screen we either shift it negative before the flip (so it gets flipped back on screen):

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

(The translate is listed second here because transform lists are effectively applied right to left)

or we can shift it positive (by the scaled size) afterwards:

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

Here is a demo showing vertical flip, horizontal flip and both flips

Update

To flip (in position) an already existing object that is somewhere on screen. First determine its bounding box (minX, minY, maxX, maxY), or centreX,centreY if you already know that instead.

Then prepend the following to its transform:

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

or if you have the centre you can use

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

So in your example:

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

The minX+maxX comes to 200. So to flip horizontally, we prepend:

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

So the final object becomes:

<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)" />

Demo here




回答2:


Here is the Livescript-ish code snippet how you can horizontally flip and scale by any factor:

    # 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}"


来源:https://stackoverflow.com/questions/23899718/scale-and-mirror-svg-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!