5

In this example, I set up a filter that textures the given element with a checkboard pattern using SVG filter effects:

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  
  <defs>
    <filter id="texture" x="0" y="0" width="100%" height="100%">
      <feImage width="16" height="16" result="checkerboard-image"
               xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEXMzMzLy8v////+/v7l
9thZAAAAO0lEQVR4ASXIUQ3AIBAFsJKcACQxu4/kBCAJFUu2ftbUYeWYI8G51kqU3VSCm68l
hpyH/nuWHaQH2eoF1bMYGK3LF0IAAAAASUVORK5CYII="/>
      <feTile in="checkerboard-image" result="texture" />
      <feBlend in="SourceGraphic" in2="texture" mode="multiply" />
      <feTile/>
    </filter>
  </defs>

  <image xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"
      x="0" y="0" width="100%" height="100%" style="filter:url(#texture);"/>
</svg>

Is there a way I can rotate the whole texture, so that I get e.g. a 45-degree rotated checkboard pattern applied on the same image?

3 Answers 3

5

I figured it out. You need to wrap the image in several nested <g> groups. From the innermost group:

  1. Rotate the image in the negative desired angle
  2. Apply the filter
  3. Rotate the image in the positive desired angle

The image will remain in the original rotation, but the effect will have been applied on the rotated image, thus making the effect itself rotated.

Here's the code itself:

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  
  <defs>
    <filter id="texture" x="0" y="0" width="100%" height="100%">
      <feImage width="16" height="16" result="texture-image"
               xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEXMzMzLy8v////+/v7l
9thZAAAAO0lEQVR4ASXIUQ3AIBAFsJKcACQxu4/kBCAJFUu2ftbUYeWYI8G51kqU3VSCm68l
hpyH/nuWHaQH2eoF1bMYGK3LF0IAAAAASUVORK5CYII="/>
      <feTile in="texture-image" result="texture" />
      <feBlend in="SourceGraphic" in2="texture" mode="multiply" />
      <feTile/>
    </filter>
  </defs>

  
  <g transform="rotate(30)">
    <g filter="url(#texture)" >
      <g transform="rotate(-30)">
        <image xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" x="0" y="0" width="100%" height="100%"/>
      </g>
    </g>
  </g>
</svg>

0
3

Theoretically, you could do it with a feDisplacementMap, but generating the right displacement map is quite difficult, so practically speaking, you have to rotate the checkerboard outside the filter (by redoing the checkerboard image, or using a patternTransform). Here is an example that inverts the filter inputs - it pulls in the main image via a feImage, and makes the rotated checkerboard the SourceGraphic.

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  
  <defs>
    <pattern id="checker-pattern" x="0" y="0" width="16" height="16" patternTransform="rotate(45) translate(-4 4)" patternUnits="userSpaceOnUse">
      <image x="0" y="0" height="16" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEXMzMzLy8v////+/v7l9thZAAAAO0lEQVR4ASXIUQ3AIBAFsJKcACQxu4/kBCAJFUu2ftbUYeWYI8G51kqU3VSCm68l
hpyH/nuWHaQH2eoF1bMYGK3LF0IAAAAASUVORK5CYII="/>
    </pattern>
    
    
    <filter id="texture" x="0" y="0" width="100%" height="100%">
      <feImage x="0%" y="0%" width="100%" height="100%" result="original-image"
xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"/>
      <feBlend in="SourceGraphic" mode="multiply" />
    </filter>
  </defs>
<g filter="url(#texture)">
  <rect x="0%" y="0%" width="100%" height="100%" fill="url(#checker-pattern)"/>
  </g>
</svg>

2

A different solution would be using an SVG pattern, like so:

<svg viewBox='0 0 200 200' width='200' height='200' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
  <defs>
    <pattern id='_texture' width='16' height='16' patternUnits='userSpaceOnUse'  patternTransform="rotate(45)">
      <g fill='rgba(0,0,0,.3)'>
        <rect width='8' height='8'/>
        <rect x='8' y='8' width='8' height='8'/>
      </g>
    </pattern>
  </defs> 
  
  
  <image xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"
      x="0" y="0" width="100%" height="100%" />
  
  <rect width='100%' height='100%' fill='url(#_texture)'/>
</svg>

UPDATE

this time I'm using an SVG dataURI image instead instead of your dataURI. The filter is still there. I hope it helps.

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"> 
  <defs>
    <filter id="texture" x="0" y="0" width="100%" height="100%">
      <feImage width="11.31" height="11.31" result="checkerboard-image"
               xlink:href="data:image/svg+xml,%3Csvg viewBox='0 0 11.31 11.31' width='11.31' height='11.31' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cg fill='rgba(0,0,0,.3)' transform='rotate(45 5.655 5.655)'%3E%3Crect width='8' height='8' x='1.655' y='1.655'/%3E%3C/g%3E%3C/svg%3E"/>
      <feTile in="checkerboard-image" result="texture" />
      <feBlend in="SourceGraphic" in2="texture" mode="multiply" />
      <feTile/>
    </filter>
  </defs>

  <image xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"
      x="0" y="0" width="100%" height="100%" style="filter:url(#texture);"/>
</svg>

6
  • 1
    Thanks for the answer! However, I'm looking for a way to make this working with feTile and feImage specifically, since those are part of a larger filter logic in my application.
    – the21st
    Commented Oct 23, 2018 at 16:00
  • 1
    Thanks for updating your answer! That is really cool. I tried changing the angle of rotation to 35 degrees though, and the effect fell apart. I am looking for a way to get this working with an arbitrary texture image and an arbitrary angle.
    – the21st
    Commented Oct 25, 2018 at 9:36
  • Of coarse it falls apart. It's calculated for 45 degs. If you take a look at the feImage xlink:href you'll se 11.31 everywhere. this is the size of the repeating box. Inside this box there is a square, in fact a lozenge, with 8 units sides. The height and width of this lozenge is 11.31. Had no idea you need 35 degs.
    – enxaneta
    Commented Oct 25, 2018 at 9:49
  • In my question, I asked: "Is there a way I can rotate the whole texture, so that I get e.g. a 45-degree rotated checkboard pattern". The 45 degrees was just an example. Sorry, I should have been clearer in the question.
    – the21st
    Commented Oct 26, 2018 at 9:44
  • 1
    Unfortunately not, because by making the checkerboard image the SourceGraphic, that completely changes the semantics of the SVG. In other words, I need to rotate the filter's texture, not the image the filter is being applied to.
    – the21st
    Commented Oct 26, 2018 at 10:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.