danicotra
danicotra

Reputation: 1433

Is it possible to center a SVG pattern image fill without using JavaScript?

I have the following SVG:

<?xml version="1.0" encoding="UTF-8"?>
<svg width="480" height="1080" version="1.1" viewBox="0 0 480 1080" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink">

     <defs>
  <pattern id="wpi" width="100%" height="100%" patternUnits="userSpaceOnUse">
   <image width="100%" height="100%" preserveAspectRatio="none" xlink:href="h_img.jpg" x="0" y="0"/>
  </pattern>
 </defs>
 <rect class="wallpaper" width="100%" height="250" fill="url(#wpi)"/>
</svg>

The h_img jpg might vary on time, loading different images, so I can't be aware of its size in advance, yet I know that, most of the time, its height value is greater than its width but I need to apply it to a rect element that has a smaller height compared to its own width and this is for sure (despite I'm using a relative 100% value for that one). I need the pattern to fill that rect with the image maintaining its aspect ratio and the height being crop (or hide overflow) centered. I know I can use JavaScript to calculate the image relative width, resize the height accordingly to maintain the aspect ratio and calculate the offset needed to provide the centering (and I did) but... Do you know maybe is there a way to do what I need simply using the right parameters on the SVG element and no JavaScript?

I tried with:

<pattern id="wpi" width="100%" height="100%" patternContentUnits="objectBoundingBox">
  <image width="1" height="1" preserveAspectRatio="xMidYMid" xlink:href="h_img.jpg" x="0" y="0"/>
</pattern>

But that doesn't get me the desired effect I need... Thanks for your help

SOLVED EDIT:

Thanks to @ccprog for his suggestion took me on the right direction, I managed to find a way to solve like this:

<?xml version="1.0" encoding="UTF-8"?>
<svg width="480" height="1080" viewBox="0 0 480 1080" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
 <defs>
  <pattern id="wpi" width="1" height="1">
   <image width="100%" height="250" preserveAspectRatio="xMidYMid slice" xlink:href="h_img.jpg"/>
  </pattern>
 </defs>
 <rect class="wallpaper" width="100%" height="250" fill="url(#wpi)"/>
</svg>

Notice: you need to set for the <image> just the same height and width values used for the pattern image container area (= that means the size of the element on which the pattern is going to be applied, in this case it's a <rect>).

As final words I'll say there are at least a couple of reasons for I wanted the image to stay applied within a pattern:

Upvotes: 2

Views: 3096

Answers (1)

ccprog
ccprog

Reputation: 21856

If you want to display an image once in a rectangular area, you do not need a pattern. Patterns are for repeating content more than once.

The attribute you were searching for is preserveAspectRatio="xMidYMid slice". See the spec.

<svg width="480" height="1080" viewBox="0 0 480 1080"
     xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink">
   <image class="wallpaper" width="100%" height="250"
          preserveAspectRatio="xMidYMid slice" xlink:href="h_img.jpg"/>
</svg>

Upvotes: 3

Related Questions