DEV Community

Po-Hsiang (Matthew) Lu
Po-Hsiang (Matthew) Lu

Posted on

feDisplacementMap Explained

feDisplacementMap is one of the SVG filters that always seems daunting for me to understand. But once I looked into it, it is not so complicated and is actually fun to play with.

Let's first see what this SVG filter can do.

Diagram of how feDisplacementMap works

feDisplacementMap takes in two input source in and in2. in is the image to be displaced, and in2 is used to calculated how in will be displaced. In this case, we used a forest image for in and an image created with feTurbulence. We can therefore create a ripple-like effect on the forest image.

In essence, what feDisplacementMap is doing is looping through each pixel on an image and move the pixel around based on a transformation formula.

Transformation Formula

P'(x,y) ← P( x + scale * (XC(x,y) - 0.5), y + scale * (YC(x,y) - 0.5))
Enter fullscreen mode Exit fullscreen mode

Here's a breakdown of the formula:

  • P'(x, y) on the left is the coordinates after transformation
  • The right part is how it is transformed
  • XC(x,y) and YC(x,y) means the RGB value of the given coordinates on the in2 image divided by 255, so it will be between 0 and 1
  • The larger the scale is, the more a pixel is displaced

Example

<filter>
    <!-- ... -->
    <feDisplacementMap in2="turbulence" in="SourceGraphic" scale="50" 
        xChannelSelector="R" yChannelSelector="G"/>
</filter>
Enter fullscreen mode Exit fullscreen mode

If we compare the syntax of feDisplacementMap and the transformation formula, we realize that:

  • scale corresponds to scale
  • xChannelSelector specifies which color channel to look at for XC(x,y)
  • yChannelSelector specifies which color channel to look at for YC(x,y)

Note: SourceGraphic is the original input to the SVG filter, which is the forest image.

Here's the full example:

<svg>
  <defs>
    <filter id="displace">
      <feTurbulence id="turbulence" baseFrequency="0.1 0.1" result="turbulence" />
      <feDisplacementMap in2="turbulence" in="SourceGraphic" scale="10" xChannelSelector="A" yChannelSelector="A"/>
    </filter>
  </defs>
  <image href="https://images.unsplash.com/photo-1441974231531-c6227db76b6e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1171&q=80" height="100%" width="100%" filter="url(#displace)"/>
</svg>
Enter fullscreen mode Exit fullscreen mode

Now that we understand feDisplacementMap

We can go creative to experiment with interesting graphics with feDisplacementMap!

GIF of a Glitch Text effect using feDisplacementMap

Top comments (1)

Collapse
 
lopu profile image
Nikolaj Frey

What value do I use to only displace the X using Green for example and not Y at all? because yChannelSelector cannot be undefined so..

For example I attempted to set X to R, which goes from 128 to 255, so 0.5 -> 1 ? But then set Y to G which I've left at 128, so this should equate to 0.5 correct? But it still seems to displace the Y pixels by a bit..

<linearGradient id="lg" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(-45, 0.5, 0.5)">
  <stop offset="0%" stop-color="rgba(128, 128, 128, 1)"></stop>
  <stop offset="25%" stop-color="rgba(128, 128, 128, 1)"></stop>
  <stop offset="100%" stop-color="rgba(255, 128, 128, 1)"></stop>
</linearGradient>
Enter fullscreen mode Exit fullscreen mode