1

I'm attempting to append a PNG or JPG background image to a SVG. Currently the background image does not show up, after trying multiple different methods of attaching it.

I am using jQuery.panzoom as well as jquery.svg (only if I need to for this issue).

The zoom and pan feature is working for the <g> element which then moves all the polygons and text elements inside of it together. What I want to have is a background image that is essentially attached to the <g> (or <svg>), so that it moves when I move the <g> and its children. (I know you cannot attach a background image to a <g> element).

Basic SVG markup

My basic grouping of SVG elements looks like this...

<svg id="pnlShapes" width="640" height="480">
    <svg id="shapes" width="640" height="480">
        <g id="shapes-group" width="640" height="480">
            <polygon id="svgSection_Floor" points="222.61,199.75,222.61,295.19,380.62,295.19,380.62,199.75,222.61,199.75,368.46,283.92,233.54,283.92,233.54,209.12,368.46,209.12,368.46,283.92" title="Floor" link="Primary" style="color: rgb(211, 211, 211); font-size: 0px; left: 0px; top: 0px; opacity: 0.82; fill: rgb(211, 211, 211); cursor: not-allowed;"></polygon>
            <text x="302.61" y="289.4705" fill="white" font-size="9" font-weight="bold" text-anchor="middle">Floor</text>
            <!-- plus a bunch more polygon and text element... -->
        </g>
    </svg> 
</svg>

What I've Tried...

I have tried to use a pattern fill to attach a background image. jsFiddle

    <svg id="pnlShapes" width="640" height="480">
        <defs xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg">
            <pattern id="image" x="0" y="0" patternunits="userSpaceOnUse" height="480" width="640">
                <image x="0" y="0" width="640" height="480" xlink:href="http://localhost:44000/Content/images/theImage.jpg"></image>
            </pattern>
       </defs>
        <svg id="shapes" width="640" height="480" fill="url(#image)">
            <g id="shapes-group" width="640" height="480">
                <polygon id="svgSection_Floor" points="222.61,199.75,222.61,295.19,380.62,295.19,380.62,199.75,222.61,199.75,368.46,283.92,233.54,283.92,233.54,209.12,368.46,209.12,368.46,283.92" title="Floor" link="Primary" style="color: rgb(211, 211, 211); font-size: 0px; left: 0px; top: 0px; opacity: 0.82; fill: rgb(211, 211, 211); cursor: not-allowed;"></polygon>
                <text x="302.61" y="289.4705" fill="white" font-size="9" font-weight="bold" text-anchor="middle">Floor</text>
            </g>
        </svg> 
    </svg>

I also tried using jquery.svg to attach a background image jsFiddle:

$('#shapes').svg();
var foo = $('#shapes').svg('get');
foo.filters.image(null, '', "http://localhost:44000/Content/images/theImage.jpg");


Here's my pan & zoom code also (using jquery.panzoom), if it helps:
var $section = $('#svg-container').first();
$section.find('g').panzoom({
    $zoomIn: $section.find(".zoom-in"),
    $zoomOut: $section.find(".zoom-out"),
    $zoomRange: $section.find(".zoom-range"),
    $reset: $section.find(".reset")
});

Final Thoughts

If using a plugin is the best way to accomplish that then I have no problem using it. I just need to have a background image on the <svg id="shapes"> or inside of that or the <g> element.

james
  • 5,006
  • 8
  • 39
  • 64

2 Answers2

1

SVG doesn't support CSS background images. You can simulate it by creating a <rect> element that occupies the whole space as the first child though

<svg id="pnlShapes" width="640" height="480">
    <defs>
        <pattern id="image" patternUnits="userSpaceOnUse" height="480" width="640">
            <image width="640" height="480" xlink:href="https://octodex.github.com/images/octoliberty.png"></image>
        </pattern>
    </defs>
    <svg id="shapes" width="640" height="480">
        <rect width="100%" height="100%" fill="url(#image)"/>
        <g id="shapes-group">
            <polygon id="svgSection_Floor" points="222.61,199.75,222.61,295.19,380.62,295.19,380.62,199.75,222.61,199.75,368.46,283.92,233.54,283.92,233.54,209.12,368.46,209.12,368.46,283.92" title="Floor" link="Primary" style="color: rgb(211, 211, 211); font-size: 0px; left: 0px; top: 0px; opacity: 0.82; fill: rgb(211, 211, 211); cursor: not-allowed;"></polygon>
            <text x="302.61" y="289.4705" fill="white" font-size="9" font-weight="bold" text-anchor="middle">Floor</text>
        </g>
    </svg>
</svg>
Robert Longson
  • 118,664
  • 26
  • 252
  • 242
  • Works great. I moved the `` inside of the `` element, so it is included when dragging and zooming. Thanks! – james Apr 27 '15 at 14:37
  • This solution is more complicated than it needs to be. You don't need to use a pattern to add an image to a rect. Just use an image. https://jsfiddle.net/ss4ba5ox/ – Paul LeBeau Jul 02 '16 at 13:07
0

SVG does have some support for CSS background images. For your code above, you could add a background image to <svg id="pnlShapes"> by saying:

<!DOCTYPE html>

 <html>
  <head>
    <style>
       #pnlShapes {
          background-image: url('https://octodex.github.com/images/octoliberty.png');
          background-repeat: no-repeat;
          background-size: contain;
          background-position: center;
       }
   </style>
   </head>

   

 <body>
 <svg id="pnlShapes" width="640" height="480">
  <svg id="shapes" width="640" height="480">
    <g id="shapes-group" width="640" height="480">
        <polygon id="svgSection_Floor" points="222.61,199.75,222.61,295.19,380.62,295.19,380.62,199.75,222.61,199.75,368.46,283.92,233.54,283.92,233.54,209.12,368.46,209.12,368.46,283.92" title="Floor" link="Primary" style="color: rgb(211, 211, 211); font-size: 0px; left: 0px; top: 0px; opacity: 0.82; fill: rgb(211, 211, 211); cursor: not-allowed;"></polygon>
        <text x="302.61" y="289.4705" fill="white" font-size="9" font-weight="bold" text-anchor="middle">Floor</text>
        <!-- plus a bunch more polygon and text element... -->
    </g>
  </svg> 
  </svg>
  </body>
  </html>
truly-daunting
  • 75
  • 1
  • 13
  • This is because the root `` element here is effectively being treated as an HTML element by the browser. But this is special treatment only because it is in an HTML document. This is not true in general. For example, this won't work in a standalone SVG, and it won't work if you try to apply the background image to the inner `` element. – Paul LeBeau Jul 02 '16 at 13:19