Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i scale a shape without scaling its pattern?

Tags:

svg

I have an svg shape which uses a pattern. I want the pattern to NOT scale when i scale the shape.

Here's a fiddle with a minimal example, the bigger circle should show the pattern like the smaller one:

http://jsfiddle.net/cTMrQ/6/

<svg style="position: absolute" width="100%" height="100%" version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events">
    <defs>
        <pattern id="checkerPattern" patternUnits="userSpaceOnUse" x="0" y="0" width="4" height="4">
            <image x="0" y="0" xlink:href="http://inwonderland.at/new/lines.png" width="4" height="4" />
        </pattern>
        <circle fill="url(#checkerPattern)" id="c" cx="50" cy="50" r="50" />
    </defs>
    <use x="100" y="100" xlink:href="#c" />
    <use x="200" y="100" xlink:href="#c" transform="scale(2)" />
</svg>

In the end the shape will be a complex path and the image in the pattern will be a scan of a piece of paper, so just drawing a bigger circle instead of scaling it won't work.

Update

To clarify what i want, here are two images:

this is what it looks like, no matter what i try, when i scale the shape: http://inwonderland.at/new/ihave.png

this is what i want: http://inwonderland.at/new/iwant.png

i want the background image (bitmap image) to always have its natural size.

like image 266
rossi Avatar asked Jan 18 '14 19:01

rossi


2 Answers

You can't get what you want using a pattern, the transform always happens after the fill, and you can't just move the pattern fill into a wrapper either. My suggestion is to use a filter and apply the filter on a wrapper - like so:

<svg style="position: absolute" width="100%" height="100%" version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events">
    <defs>

 <circle fill="url(#checkerPattern)" id="c1" cx="50" cy="50" r="50" />

 <filter id="linepattern" x="0%" y="0%" height="100%" width="100%">
 <feImage xlink:href="http://inwonderland.at/new/lines.png" result="pattern" width="4" height="4"/>
   <feTile/>
   <feComposite operator="in" in2="SourceGraphic"/>
      </filter>
    </defs>

    <use filter="url(#linepattern)" x="100" y="100" xlink:href="#c1" />

    <use filter="url(#linepattern)" x="200" y="100" xlink:href="#c1" transform="scale(2)" />

    <g filter="url(#linepattern)"> 
    <use x="50" y="100" xlink:href="#c1" transform="scale(2)" />
</g> 
</svg>
like image 186
Michael Mullany Avatar answered Nov 09 '22 23:11

Michael Mullany


Using viewport

1:1 no zoom

<svg width="800" height="400" viewBox="0 0 800 400"> 

2:1 zoom double size

<svg width="800" height="400" viewBox="0 0 400 200"> 

The following elements can use the viewBox attribute

<svg>
<symbol>
<image>
<marker>
<pattern>
<view>

viewbox is fully animatable; and you can zoom into any center point.

 <animate attributeName="viewBox" begin="1s" dur="1s"
           values="0 0 600 400; 250 180 300 200" fill="freeze" />

Transform a parent tag

Yes an SVG can be a child element but more commonly shapes made with multible tags are placed inside a group tag.

Transform scale can be used with tags which are parents IE the group tag.

<g transform="scale(1.5)">
/* draw your shape inside the g tag */
<use x="100" y="100" xlink:href="#c" />
<use x="200" y="100" xlink:href="#c" />
</g>

So using your above example scale the shape in a parent tag.

Update

To scale image but not patterns in other words move patterns, or icons, on background image that scales.

<g transform="scale(2)">
/* draw your shape inside the g tag */
<use x="100" y="100" xlink:href="#c" transform="scale(.5)" />
<use x="200" y="100" xlink:href="#c" transform="scale(.5)"/>
</g>

Update full svg

I had to move things around a bit, One full size, (lets call it a map), with an overlay of 1 half size map in the upper left corner. setting the full screen to render between 0 and max of 600. Setting a viewport the same but with the width set to 300 scales it down. I do need to double the radius for this example of scaling.

<svg viewBox="0 0 600 600" style="position: absolute" width="100%" height="100%" version="1.1" baseProfile="full" 

xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events">
    <defs>
        <pattern id="checkerPattern" patternUnits="userSpaceOnUse" x="0" y="0" width="4" height="4">
            <image x="0" y="0" xlink:href="http://inwonderland.at/new/lines.png" width="4" height="4" />
        </pattern>
        <circle fill="url(#checkerPattern)" id="c" cx="50" cy="50" r="50" />
        <circle fill="url(#checkerPattern)" id="c2" cx="50" cy="50" r="100" />
    </defs>
<use x="100" y="100" xlink:href="#c" transform="scale(.5)"/>
<use x="200" y="100" xlink:href="#c" transform="scale(1)"/>
<rect width="600" height="600" style="fill: none; stroke: black;" />

<svg viewBox="0 0 600 600" width="300" height="300"  x="300">
<use x="100" y="100" xlink:href="#c2" transform="scale(.5)"/>
<use x="200" y="100" xlink:href="#c2" transform="scale(1)"/>
<rect width="600" height="600" style="fill: none; stroke: black;" />
</svg>
</svg>

This example is scaled using the same circle pattern. The radius does not need to be changed here because the location is not in the tag being scaled. I'm making use of svg tags here but other tags can be used.

<svg viewBox="0 0 600 600" style="position: absolute" width="100%" height="100%" version="1.1" baseProfile="full" 

xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events">
    <defs>
        <pattern id="checkerPattern" patternUnits="userSpaceOnUse" x="0" y="0" width="4" height="4">
            <image x="0" y="0" xlink:href="http://inwonderland.at/new/lines.png" width="4" height="4" />
        </pattern>
        <circle fill="url(#checkerPattern)" id="c" r="50" cx="50" cy="50" />
    </defs>


<svg x="100" y="100"><use xlink:href="#c" transform="scale(.5)"/></svg>
<svg x="200" y="100"><use xlink:href="#c" transform="scale(1)"/></svg>
<rect width="600" height="600" style="fill: none; stroke: black;" />

<svg viewBox="0 0 600 600" width="300" height="300"  x="300">
<svg x="100" y="100"><use xlink:href="#c" transform="scale(1)"/></svg>
<svg x="200" y="100"><use xlink:href="#c" transform="scale(2)"/></svg>
<rect width="600" height="600" style="fill: none; stroke: black;" />
</svg>
</svg>
like image 35
Wayne Avatar answered Nov 09 '22 22:11

Wayne