22

I'd like to do something very much like Fill SVG path element with a background-image except that the solution offered there will tile the image to fill the the entire background area. I don't want that. If the image doesn't fill either the entire height or the entire width, then I'd just like it to center within the path shape and let that be that. If I try to restrict the behavior by changing the height/width attributes, then the rendering just scales the image until it fills at least one of the dimensions.

I guess this behavior somewhat makes sense since it uses patterns. I can see that what I want is not really a "pattern" per se. I just want to slap an image in the middle of my shape just as it is, not make a pattern out of it. However, I do want the shape boundaries defined by my SVG path to cut off the rendering of the image, whenever the image's size extends past those boundaries. I don't know else to get that behavior besides the use of a pattern for the fill attribute, as is done in the answer to that question.

In a similar question: Add a background image (.png) to a SVG circle shape , the user at the very bottom seems to indicate that he used a filter rather than a pattern to achieve what I'm seeking to achieve. However, when I try that, no regard is paid to the actual shape during rendering. The image is rendered without any regard to the shape boundaries, which seems pretty much useless.

Is there any way in SVG to get that pattern-like background image behavior but without actually tiling the image into a pattern?

Community
  • 1
  • 1
Michael
  • 325
  • 1
  • 3
  • 9

2 Answers2

39

Just make the x, y, width and height of the pattern match the bounding box of your path. You can just use "0","0","1" & "1" respectively here because the patternUnits defaults to objectBoundingBox, so the units are expressed relative to the bounding box. Then make the image in your pattern have the width and height of the path bounding box also. This time, you'll need to use "real" sizes though.

The image will be centred in the pattern automatically because the default value of preserveAspectRatio for <image> does exactly what you want.

<svg width="600" height="600">
  
  <defs>
      <pattern id="imgpattern" x="0" y="0" width="1" height="1">
        <image width="120" height="250"
               xlink:href="http://lorempixel.com/animals/120/250/"/>
      </pattern>
  </defs>
  
  
  
  <path fill="url(#imgpattern)" stroke="black" stroke-width="4"
        d="M 100,50 L 120,110 150,90 170,220 70,300 50,250 50,200 70,100 50,70 Z" />

</svg>
darronz
  • 903
  • 9
  • 17
Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
  • 1
    Thank you very much. That example seems to be what I want. I'm going to work right now on changing my project to use that and see how it goes. – Michael Feb 27 '15 at 21:24
  • 1
    Works just fine in my context. Exactly what I needed. Thanks again! – Michael Feb 27 '15 at 23:58
  • So really, in spite of the question being about _not_ using scaling or tiling, the answer is to have it auto-scale to 100%, and set a tile size that fills the entire width/height so you're only using a single tile. – brichins Nov 30 '16 at 17:06
  • 1
    How can I make it fill the whole div which the svg is inside? – Just A Question Aug 21 '20 at 11:59
  • @JustAQuestion If you are trying to fill the div, rather than an SVG element, then you should use something like `div { background: url(myImage.jpg); background-size: cover; }`. – Paul LeBeau Aug 21 '20 at 12:26
-1

I have tried to implement my first scale vector graphic extension file to github repository maintained as pages. I know the rollercoast to aim extra lines to make a fit within an environment. But i have to tell that it is not necessary to implement the pattern tagline to avoid automatic pattern. In my css folder i have a file named gradientellipse.svg with the content

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--?xml-stylesheet href="css/styles.css" type="text/css"?-->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs> 
  <ellipse id="myEllipse"
           cx="200"
           cy="70"
           rx="85"
           ry="55">
</ellipse>
    <linearGradient id="grad1"
                    x1="0%"
                    y1="0%"
                    x2="0%"
                    y2="100%">
      
    <stop offset="0%"
          style="stop-color:rgb(255,0,0);stop-opacity:1" />
    <stop offset="100%"
          style="stop-color:rgb(255,255,0);stop-opacity:1" />
</linearGradient>
</defs>
  <use x="5" y="5" href="#myEllipse" fill="url('#grad1')" />
</svg>

The tagline <use> also on the site <defs> has been noted with the sentence

element takes nodes from within the SVG document

and i like that a lot, because it gives me the opportunity to aim for something instead of thinking about XML server scripting.

ledlightjungled
  • 45
  • 1
  • 12