Home > Mobile >  Proportional SVG filter?
Proportional SVG filter?

Time:12-19

I try to generate SVGs that are composed of filters and I would like to have exactly the same rendering when the same image is resized (with ratio kept).

I use two filters: feTurbulence and feDisplacementMap

My problem is that I can't get the same rendering when the same image is resized.

I was hoping that it would be enough to change the values of the attributes of the effects proportionally but it doesn't work.

In this case, if I change the "scale" and "baseFrequency" values proportionally it doesn't work.

How can I calculate the values of "scale" and "baseFrequency" to get exactly the same rendering whatever the size of the image?

IMAGE 1 - 300x132px

enter image description here

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="132">
    <defs>
        <filter id="filter1" x="0%" y="0%" width="100%" height="100%" filterUnits="userSpaceOnUse">
            <feTurbulence baseFrequency="0.05" result="NOISE" type="turbulence" />
            <feDisplacementMap in="SourceGraphic" in2="NOISE" result="RESULT" scale="10" xChannelSelector="R" yChannelSelector="R"></feDisplacementMap>
        </filter>
    </defs>
    <image x="0" y="0" width="300" height="132" href="https://i.stack.imgur.com/osUI3.png" filter="url(#filter1)"></image>
</svg>

RESULT 1:

enter image description here

IMAGE 2 - 600x264px (x2)

enter image description here

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="600" height="264">
    <defs>
        <filter id="filter2" x="0%" y="0%" width="100%" height="100%" filterUnits="userSpaceOnUse">
            <feTurbulence baseFrequency="0.05" result="NOISE" type="turbulence" />
            <feDisplacementMap in="SourceGraphic" in2="NOISE" result="RESULT" scale="10" xChannelSelector="R" yChannelSelector="R"></feDisplacementMap>
        </filter>
    </defs>
    <image x="0" y="0" width="600" height="264" href="https://i.stack.imgur.com/MNepH.png" filter="url(#filter2)"></image>
</svg>

RESULT 2:

enter image description here

We can see that the effect is different on RESULT 1 and RESULT 2.

The example is on this page: https://jsfiddle.net/qbvp8x1r/

CodePudding user response:

If you use the same viewBox for both SVGs you get the same result. The viewBox defines the "inner coordinate system" for the image.

In this example I moved the filter to a separate SVG to show that it can be reused. To make the image fit in the SVG I set the width to 100%. So, everything is relative except the viewBox.

<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <filter id="filter1" x="0%" y="0%" width="100%" height="100%" filterUnits="userSpaceOnUse">
      <feTurbulence baseFrequency="0.05" result="NOISE" type="turbulence" />
      <feDisplacementMap in="SourceGraphic" in2="NOISE" result="RESULT" scale="10" xChannelSelector="R" yChannelSelector="R"></feDisplacementMap>
    </filter>
  </defs>
</svg>

<svg xmlns="http://www.w3.org/2000/svg" width="300"
  viewBox="0 0 300 132">
  <image width="100%" href="https://i.stack.imgur.com/osUI3.png"
    filter="url(#filter1)" />
</svg>

<svg xmlns="http://www.w3.org/2000/svg" width="600"
  viewBox="0 0 300 132">
  <image width="100%" href="https://i.stack.imgur.com/SS7N6.png"
    filter="url(#filter1)" />
</svg>

  • Related