SVG path background image autoscale with aspect-ratio - html
I want to fill a path in my svg with a background image, that autoscales to fill the entire path while maintaining the aspect-ratio of the image, thus as if you'd use the css background-size: cover, I've managed to get this working with clipPath or making a pattern from the image (would also like to know which of these is the option with best browser support) but I can't get the auto scaling to use.
If anyone would have some tips or solutions I would appreciate.
Here's a jsfiddle with an example of what i've got to work.
https://jsfiddle.net/shd50cvt/
The svg:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="341.722px" height="267.549px" viewBox="0 0 341.722 267.549" style="enable-background:new 0 0 341.722 267.549;"
xml:space="preserve">
.st0{fill:#FF0000;}
.st1{fill: url(#pattern);}
In the pattern element, you can use patternUnits="objectBoundingBox" and x="0" and y="0" and width="1" and height="1" to auto scale a single pattern tile to the size of the path. You can use preserveAspectRatio="xMidYMid slice" to maintain the aspect ratio of the tile while covering the entire path. You may need to also set preserveAspectRatio on the image element in case the jpg size does not match the image element size.
Refer to the SVG reference for more information on patterns.
http://www.w3.org/TR/SVG/pservers.html#Patterns
I have modified your example to scale the image to fill the path.
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="341.722px" height="267.549px" viewBox="0 0 341.722 267.549" style="enable-background:new 0 0 341.722 267.549;"
xml:space="preserve">
<pattern id="pattern" patternUnits="objectBoundingBox" preserveAspectRatio="xMidYMid slice"
x="0" y="0" width="1" height="1" viewbox="0 0 400 300">
<image xlink:href="https://static.pexels.com/photos/909/flowers-garden-colorful-colourful.jpg"
x="0" y="0" width="400" height="300" preserveAspectRatio="xMidYMid slice"/>
</pattern>
<style type="text/css">
.st0{fill:#FF0000;}
.st1{fill: url(#pattern);}
</style>
<path class="st1" d="M199.668,52.98c-17.815,0-32.711,12.454-36.484,29.128c23.783,3.473,43.093,20.685,49.641,43.322
c14.174-5.325,24.262-18.998,24.262-35.033C237.086,69.732,220.334,52.98,199.668,52.98z"/>
<circle class="st0" cx="154.305" cy="142.384" r="60.927"/>
</svg>
Related
How do you get HTML to adjust to SVG scaling
When I scale an SVG using the scale transform, the surrounding html does not respect this scale and fails to adjust its size. I have the following SVG: <div> <svg height="300" width="300" viewbox="0 0 300 300" transform="scale(1.55)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xml="http://www.w3.org/XML/1998/namespace" version="1.1"> <circle r="150px" cx="150px" cy="150px" fill="orange"/> </svg> </div> <div> <svg height="300" width="300" viewbox="0 0 300 300" transform="scale(1.55)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xml="http://www.w3.org/XML/1998/namespace" version="1.1"> <circle r="150px" cx="150px" cy="150px" fill="green"/> </svg> </div> For some reason the surrounding html doesn't adjust for the scaled up Svg. All my testing so far has been on chrome and using primarily Svg declared in millimeter units. When tested, the above example with the scale transform, the two circles overlap. Without the transform they do not. I want them NOT to overlap when scaled. How can I get the Html to correctly adjust with the scaling of Svg? Thanks in advance.
You have set fixed height and width and fixed pixels for your svg. You have to change the properties of your svg and the actual circle path to correct it like in my example. the transform property is something you don't need here in my opinion! Try to change that and your HTML will surround like you want. <div> <svg height="100" width="100" viewbox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xml="http://www.w3.org/XML/1998/namespace" version="1.1"> <circle r="100px" cx="100px" cy="100px" fill="orange"/> </svg> </div> <div> <svg height="100" width="100" viewbox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xml="http://www.w3.org/XML/1998/namespace" version="1.1"> <circle r="100px" cx="100px" cy="100px" fill="green"/> </svg> </div> That should do the job!
I think the problem is that, in SVG 1.1, I believe it wasn't properly defined how a transform attribute behaved when placed on a root <svg> element. In SVG2 it has been. The behavior is defined in the CSS Transforms specification. Chrome seems to have implemented that, but Firefox hasn't yet done so for SVGs. The behaviour in Chrome seems correct. transform on <svg> elements behaves the same as an HTML element (see example below). <div> <svg height="300" width="300" viewbox="0 0 300 300" transform="scale(1.55)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xml="http://www.w3.org/XML/1998/namespace" version="1.1"> <circle r="150px" cx="150px" cy="150px" fill="orange"/> </svg> </div> <div> <div style="width:300px; height:300px; background-color:green; border-radius:50%; transform:scale(1.55)"> </div> </div>
My svg circle repeats image background
What am I doing wrong ? The background doesn't set properly. <svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1101px" height="617px" viewBox="0 0 1101 617" enable-background="new 0 0 1101 617" xml:space="preserve"> <defs> <pattern id="image" patternUnits="userSpaceOnUse" height="150" width="150"> <image x="30" y="0" height="150" width="150" xlink:href="http://i.imgur.com/7Nlcay7.jpg"></image> </pattern> </defs> <circle fill="url(#image)" stroke="#676467" stroke-width="3" stroke-miterlimit="10" cx="186.051" cy="489.94" r="63.29"/> </svg> Sample: http://prntscr.com/amjogg
You are using the image as a fill pattern, so it doesn't stretch or anything. You use x and y in the image to set the image position in the pattern, which can set a padding in the pattern so to speak. Then the pattern gets applied. In your case you have a 150x150 pattern with a 150x150 image that is offset 30 pixels to the right, so the pattern looks like 120 pixels of image with a 30 pixel white padding to the left. Without knowing what your intention was, I don't know what "properly" means in your context.
How to make SVG the same size as its internal <switch> element?
I have an svg of an eye, and am using it as an icon. This svg has a <switch> element inside that contains all the path drawing stuff. When you inspect this <switch> element in the javascript console it shows its dimensions as 700px X 500px. The SVG containing it, however is 707px X 707px. I.e. The SVG has a load of blank space at the top. I would like to know how to make the SVG the same size as the element contained in it. I need to do this because I want to add a bootstrap tooltip to the image, but the tooltip gets placed much too high above the image because it is padded with all this white space! I'm new to this SVG stuff - I tried changing the size of the viewport on the SVG, but that just cut the bottom off the image, and left the blank space at the top. Here is the code for the SVG image: <svg xmlns:x="http://ns.adobe.com/Extensibility/1.0/" xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/" xmlns:graph="http://ns.adobe.com/Graphs/1.0/" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> <switch> <foreignobject requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/" x="0" y="0" width="1" height="1"></foreignobject> <g i:extraneous="self"> <g> <path d="M98.066,57.193c-0.177-0.209-3.629-4.26-9.421-9.081l9.468-11.834l-4.226-3.381l-9.502,11.878 c-0.088-0.065-0.172-0.13-0.261-0.195c-4.013-2.935-8.08-5.37-12.147-7.306l7.502-15.005l-4.841-2.42L66.99,35.146 c-3.896-1.456-7.768-2.423-11.569-2.904l-4.959-17.064l-5.196,1.51l4.418,15.202c-5.41,0.042-11.018,1.142-16.674,3.256 l-7.648-15.297l-4.841,2.42l7.502,15.005c-4.067,1.936-8.134,4.371-12.147,7.306c-0.089,0.065-0.172,0.13-0.261,0.195 L6.113,32.897l-4.226,3.381l9.468,11.834c-5.792,4.82-9.244,8.872-9.421,9.081L0.456,58.94l1.478,1.747 c0.219,0.259,5.455,6.406,13.942,12.613C27.234,81.608,39.034,86,50,86s22.766-4.392,34.124-12.699 c8.487-6.207,13.723-12.354,13.942-12.613l1.478-1.747L98.066,57.193z M71.647,58.94c0,11.514-9.036,20.954-20.388,21.608 c-0.419,0.014-0.837,0.039-1.259,0.039s-0.84-0.025-1.259-0.039C37.389,79.894,28.353,70.454,28.353,58.94 c0-11.936,9.711-21.646,21.647-21.646c0.422,0,0.84,0.025,1.259,0.04C62.611,37.988,71.647,47.427,71.647,58.94z M7.666,58.941 c3.102-3.247,10.491-10.35,20.2-15.537c-3.098,4.401-4.925,9.757-4.925,15.536c0,5.773,1.823,11.126,4.916,15.524 c-3.277-1.745-6.214-3.656-8.681-5.455C13.808,65.097,9.762,61.139,7.666,58.941z M80.824,69.01 c-2.467,1.798-5.404,3.71-8.681,5.455c3.093-4.398,4.916-9.751,4.916-15.524c0-5.773-1.823-11.125-4.916-15.523 c3.277,1.745,6.214,3.656,8.681,5.454c5.37,3.914,9.415,7.872,11.511,10.069C90.24,61.138,86.193,65.096,80.824,69.01z"></path> <path d="M39.179,58.94c0,5.98,4.845,10.825,10.818,10.825c5.98,0,10.825-4.845,10.825-10.825c0-5.98-4.845-10.825-10.825-10.825 C44.024,48.114,39.179,52.96,39.179,58.94z M45.941,61.646c-2.239,0-4.056-1.817-4.056-4.055c0-2.246,1.817-4.063,4.056-4.063 c2.239,0,4.056,1.817,4.056,4.063C49.997,59.829,48.18,61.646,45.941,61.646z"></path> </g> </g> </switch> </svg> I've included it here in a PLNKR so you can see what is happening: http://plnkr.co/edit/gw1k0vQGon3dxUOVvuDB Here is the current look of the picture, with new colours for clarity: Here is how I would like the image to look (again - ignore the poxy colours...): I want to strip all the blank space from the top and the bottom. Any ideas?
Like so? I've added a rect background so it's easy to see the extent of the SVG. All I've done is modify the viewBox so that values match the shape extents. <svg viewBox="0 14 100 73" width="100" height="71" xmlns:x="http://ns.adobe.com/Extensibility/1.0/" xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/" xmlns:graph="http://ns.adobe.com/Graphs/1.0/" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" enable-background="new 0 0 100 100" xml:space="preserve" overflow="hidden"> <rect width="100" height="100" fill="lightblue"/> <switch> <foreignObject requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/" x="0" y="0" width="1" height="1"></foreignobject> <g i:extraneous="self"> <g> <path d="M98.066,57.193c-0.177-0.209-3.629-4.26-9.421-9.081l9.468-11.834l-4.226-3.381l-9.502,11.878 c-0.088-0.065-0.172-0.13-0.261-0.195c-4.013-2.935-8.08-5.37-12.147-7.306l7.502-15.005l-4.841-2.42L66.99,35.146 c-3.896-1.456-7.768-2.423-11.569-2.904l-4.959-17.064l-5.196,1.51l4.418,15.202c-5.41,0.042-11.018,1.142-16.674,3.256 l-7.648-15.297l-4.841,2.42l7.502,15.005c-4.067,1.936-8.134,4.371-12.147,7.306c-0.089,0.065-0.172,0.13-0.261,0.195 L6.113,32.897l-4.226,3.381l9.468,11.834c-5.792,4.82-9.244,8.872-9.421,9.081L0.456,58.94l1.478,1.747 c0.219,0.259,5.455,6.406,13.942,12.613C27.234,81.608,39.034,86,50,86s22.766-4.392,34.124-12.699 c8.487-6.207,13.723-12.354,13.942-12.613l1.478-1.747L98.066,57.193z M71.647,58.94c0,11.514-9.036,20.954-20.388,21.608 c-0.419,0.014-0.837,0.039-1.259,0.039s-0.84-0.025-1.259-0.039C37.389,79.894,28.353,70.454,28.353,58.94 c0-11.936,9.711-21.646,21.647-21.646c0.422,0,0.84,0.025,1.259,0.04C62.611,37.988,71.647,47.427,71.647,58.94z M7.666,58.941 c3.102-3.247,10.491-10.35,20.2-15.537c-3.098,4.401-4.925,9.757-4.925,15.536c0,5.773,1.823,11.126,4.916,15.524 c-3.277-1.745-6.214-3.656-8.681-5.455C13.808,65.097,9.762,61.139,7.666,58.941z M80.824,69.01 c-2.467,1.798-5.404,3.71-8.681,5.455c3.093-4.398,4.916-9.751,4.916-15.524c0-5.773-1.823-11.125-4.916-15.523 c3.277,1.745,6.214,3.656,8.681,5.454c5.37,3.914,9.415,7.872,11.511,10.069C90.24,61.138,86.193,65.096,80.824,69.01z"></path> <path d="M39.179,58.94c0,5.98,4.845,10.825,10.818,10.825c5.98,0,10.825-4.845,10.825-10.825c0-5.98-4.845-10.825-10.825-10.825 C44.024,48.114,39.179,52.96,39.179,58.94z M45.941,61.646c-2.239,0-4.056-1.817-4.056-4.055c0-2.246,1.817-4.063,4.056-4.063 c2.239,0,4.056,1.817,4.056,4.063C49.997,59.829,48.18,61.646,45.941,61.646z"></path> </g> </g> </switch> </svg>
Can I preserve the aspect ratio of an image element in an SVG document?
I have an SVG document with an emebedded image element like so: <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 200 200"> <image xlink:href="hannibal.jpg" x="0" y="0" width="200" height='200' /> </svg> I can't know ahead of time the width and height of the linked image. How can I set the width of the image to be the same as the viewBox, and allow the height to autoscale? Failing this, can I align the image content to the top of the image element?
If you want the image to be at the top of the viewBox, rather than the centre, you just have to set preserveAspectRatio="xMidYMin". <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 200 200"> <image xlink:href="hannibal.jpg" x="0" y="0" width="200" height="200" preserveAspectRatio="xMidYMin"/> </svg> This should work as long as the height is never greater than the width.
SVG appearing outside of viewport
I've tried to make the SVG viewport take up 100% of the width and height of the page here: http://jsfiddle.net/XZ57u/2/ However it seems to appear only when I change this: <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve" id="city"> To this (viewport size): <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1400 1400" enable-background="new 0 0 1400 1400" xml:space="preserve" id="city"> My understanding was that the 100 meant it was taking up the whole viewport percentage so why then does it appear off the page?
viewBox="0 0 100 100" Simply put viewbox defines the coordinate-system limits of your SVG...it has nothing (really) to do with the dimensions of the element in the HTML which you can either set in the SVG itself or in your CSS. By changing the viewbox you are effectively saying, I only want to see the top left 100x100 section of my 1400x1400 SVg. EDIT: JSfiddle demo with original 1400 viewbox and any CSS dimensions.
The viewbox numbers stand for pixels, not for percentatge. If you want to cover the whole container you have to set the SVG elements width and height to 100% use this instead: <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="100%" y="100%" xml:space="preserve" id="city"> here is the fiddle: http://jsfiddle.net/t5rhp/
you have to define the viewBox attribute as well. In addition you could also use Preserving Aspect Ratio as well. svg { width:100%; height:100%; } <svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid none"> <circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" /> </svg>