Is an SVG image purely vectorial or can we combine bitmap images into an SVG image ?
How about transforms applied on the bitmap images (perspective, mappings, etc.) ?
Edit: Images may be included in an SVG by link reference. See http://www.w3.org/TR/SVG/struct.html#ImageElement. My question was in fact if bitmap images may be included inside the svg so that the svg image would be self contained. Otherwise, whenever the svg image is displayed the link must be followed and the image downloaded. Apparently .svg files are simply xml files.
Yes, you can reference any image from the image element. And you can use data URIs to make the SVG self-contained. An example:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
...
<image
width="100" height="100"
xlink:href="data:image/png;base64,IMAGE_DATA"
/>
...
</svg>
The svg element attribute xmlns:xlink declares xlink as a namespace prefix and says where the definition is. That then allows the SVG reader to know what xlink:href means.
The IMAGE_DATA is where you'd add the image data as base64-encoded text. Vector graphics editors that support SVG usually have an option for saving with images embedded. Otherwise there are plenty of tools around for encoding a byte stream to and from base64.
Here's a full example from the SVG testsuite.
I posted a fiddle here, showing data, remote and local images embedded in SVG, inside an HTML page:
http://jsfiddle.net/MxHPq/
<!DOCTYPE html>
<html>
<head>
<title>SVG embedded bitmaps in HTML</title>
<style>
body{
background-color:#999;
color:#666;
padding:10px;
}
h1{
font-weight:normal;
font-size:24px;
margin-top:20px;
color:#000;
}
h2{
font-weight:normal;
font-size:20px;
margin-top:20px;
}
p{
color:#FFF;
}
svg{
margin:20px;
display:block;
height:100px;
}
</style>
</head>
<body>
<h1>SVG embedded bitmaps in HTML</h1>
<p>The trick appears to be ensuring the image has the correct width and height atttributes</p>
<h2>Example 1: Embedded data</h2>
<svg id="example1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="0" y="0" width="5" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="/>
</svg>
<h2>Example 2: Remote image</h2>
<svg id="example2" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="0" y="0" width="275" height="95" xlink:href="http://www.google.co.uk/images/srpr/logo3w.png" />
</svg>
<h2>Example 3: Local image</h2>
<svg id="example3" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="0" y="0" width="136" height="23" xlink:href="/img/logo.png" />
</svg>
</body>
</html>
You could use a Data URI to supply the image data, for example:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image width="20" height="20" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="/>
</svg>
The image will go through all normal svg transformations.
But this technique has disadvantages, for example the image will not be cached by the browser
You can use a data: URL to embed a Base64 encoded version of an image. But it's not very efficient and wouldn't recommend embedding large images. Any reason linking to another file is not feasible?
If you want to use that image multiple times inside SVG (Ref.):
<image id="img" xlink:href="data:image/png;base64,BASE64_DATA" />
<use href="#img" />
<use href="#img" />
It is also possible to include bitmaps. I think you also can use transformations on that.
Related
I see that you can reference the svg by id in some css/svg properties, as in:
<!-- the logo svg -->
<svg id="rect-container" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- left squares -->
<rect fill="url(#rect-fill)"/>
</svg>
does anyone know if we can use a svg from the page, in a css bg for example? to avoid encoding it on the css.
Something like this, which I already tried but did not seem to work the same way.
.myel {
background-image: url(#rect-svg-image);
}
First, there is a misconception to clear up.
fill: url(#source);
does not reference arbitrary SVG content, but a paint server, namely a gradient or pattern. Other uses of the CSS url() notation in SVG include the clip-path, mask and marker-start|mid|end properties that all also can only reference specific elements.
Currently, background-image needs an actual self-contained image resource or a CSS gradient. Referencing a SVG paint server with url() does not work.
But the CSS Images Module Level 4 also defines a element() functional notation that can reference fragments inside the page.
If you look at the text of the specification, there are still a lot of open questions listed to solve before this can become mainstream. There currently is only a Firefox implementation with vendor prefix, -moz-element(). You can point it to paint servers; that means you can (mis)use a <pattern> element. Although experimenting, I found there are some tradeoffs to make:
patternContentUnits="objectBoundingBox" needs all content drawn into a 1px*1px square, but makes the content scalable. Preserving the aspect ratio is not supported.
patternContentUnits="userSpaceOnUse" gives you preservation of the aspect ratio, but scaling is not supported.
svg {
display: block;
width: 0;
height: 0;
}
div {
width: 200px;
height: 150px;
border: 1px solid black;
background-image: -moz-element(#image);
background-size: cover;
}
<svg>
<pattern patternContentUnits="objectBoundingBox"
preserveAspectRatio="xMidYMid meet"
width="100%" height="100%" id="image">
<rect width=".5" height=".5" fill="red"/>
<rect width=".5" height=".5" x=".5" fill="yellow"/>
<rect width=".5" height=".5" y=".5" fill="green"/>
<rect width=".5" height=".5" x=".5" y=".5" fill="blue"/>
<circle r=".5" cx=".5" cy=".5" fill="white" opacity=".5"/>
</pattern>
</svg>
<div>
I know external svg files can be linked to background images:
background-image: url(Icon.svg);
and symbols id's can be targeted from an external svg file:
background-image: url(Icons.svg#Icon-Menu);
but how can I set a background image to an inline svg symbol? (As below)
My svg is at the top of my web page body and not in an external file.
I want .test background image to be the #Icon-Menu symbol.
.test{
background:#ddd url('../#Icon-Menu');
height:100px;
width:100px;
display:block;
}
<div style="height: 0; width: 0; position: absolute; visibility: hidden;">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="Icon-Menu" viewBox="0 0 512 512">
<title>Menu</title>
<path d="M93.417,5.333H6.583c-1.654,0-3,1.346-3,3v13.334c0,1.654,1.346,3,3,3h86.833c1.654,0,3-1.346,3-3V8.333 C96.417,6.679,95.071,5.333,93.417,5.333z" />
<path d="M93.417,40.333H6.583c-1.654,0-3,1.346-3,3v13.334c0,1.654,1.346,3,3,3h86.833c1.654,0,3-1.346,3-3V43.333 C96.417,41.679,95.071,40.333,93.417,40.333z" />
<path d="M93.417,75.333H6.583c-1.654,0-3,1.346-3,3v13.334c0,1.654,1.346,3,3,3h86.833c1.654,0,3-1.346,3-3V78.333 C96.417,76.679,95.071,75.333,93.417,75.333z" />
</symbol>
</svg>
</div>
<div class="test"></div>
#Robert Longson
thats right. But you can do it this way.
But symbol is not the way it will work. Unfortunatly you have to use "g" or something like that to reference.
body {
background: url(http://www.broken-links.com/tests/images/faces.svg#devil-view);
}
http://codepen.io/Type-Style/pen/ByvKJq
It will not work if the svg is in the Markup.
An image must be a complete file.
From the SVG specification...
The ‘image’ element indicates that the contents of a complete file are to be rendered...
The same is true for background-image etc.
(1) one possible way with inline SVG would be to use symbols and DIV absolute layering:
<a class="preview-modal__device-icon-link" ng-click="setPreviewWidth('phone')">
<svg class="preview-modal__device-icon"><use xlink:href="#icon-phone">
</use></svg>
</a>
(2) Second solution would be to use a Data URI:
there is a good info here: https://css-tricks.com/using-svg/
using this tool: Mobilefish.com online conversion tool
CSS:
.logo {
background: url("data:image/svg+xml;base64,[data]");
}
HTML:
<img src="data:image/svg+xml;base64,[data]">
Background
I have an SVG data URL as a background-image property of an HTML element inside a <foreignObject> inside an SVG data URL which serves as the source of an <img> element.
Problem
In Google Chrome, that inner SVG is not rendered at all; while if this whole business wasn't inside an image, it would have rendered. How can I solve this?
Wait, what? Why?
A why will be below, but first I want to complete the question by adding a tree structure and a code sample, to clarify the above convoluted paragraph.
Tree:
<img src="data:image/svg+xml;utf8, (exhibit A)
<svg> (exhibit B)
<foreignObject>
<html>
<div style="background: url('data:image/svg+xml;utf8,
<svg> (exhibit C)
Exhibit C is not rendered at all, as if it's not there. If I cut exhibit A out, though, so that exhibit B is the top-level element, then exhibit C is rendered fine.
Small code sample:
<div>Standalone:</div>
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="50" style="position:relative"><circle cx="25" cy="25" r="25" fill="red" /><foreignObject style="width: 100%; height: 100%"><html xmlns="http://www.w3.org/1999/xhtml"><style>.x {position: absolute;background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='50'><circle cx='50' cy='25' r='25' fill='blue'/></svg>"); width: 100%; height: 100%;}</style><div class="x"></div></html></foreignObject></svg>
<div>As image source:</div>
<img style="position:relative" src='data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="75" height="50" style="position:relative"><circle cx="25" cy="25" r="25" fill="red" /><foreignObject style="width: 100%; height: 100%"><html xmlns="http://www.w3.org/1999/xhtml"><style>.x {position: absolute;background: url("data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="50"><circle cx="50" cy="25" r="25" fill="blue"/></svg>"); width: 100%; height: 100%;}</style><div class="x"></div></html></foreignObject></svg>'>
One final note: using a PNG data URL instead of an SVG data URL works well; it's when using SVG when this becomes broken.
Why?
Placing HTML inside an <img> allows that HTML to be rendered on a canvas by context.drawImage - and I follow that up by canvas.toDataURL in order to generate an image from the HTML, which is my ultimate goal. This is a terrible though standard approach, also employed by widely-used libraries such as https://github.com/tsayen/dom-to-image.
My HTML comes with its own embedded SVG, though, which creates the problem mentioned in the question. Until now I bypassed this by first repeating this flow for the innermost SVG data URLs, replacing them with PNG data URLs, and only then rendering the top-level HTML element. But now I want to add scaling to the mix, which greatly complicates things, since those PNGs won't scale smoothly and I can't scale first because then the images will be too big for their elements.
(well it works okay with background-image which scales, but not with clip-path which doesn't scale and I'm also converting).
Other browsers
IE and Edge do not support HTML inside <foreignObject>, so this is irrelevant for them.
Firefox does support it but for some reason its "standalone" version doesn't work either - which I would also like to solve but it might belong in a separate question.
Related but not duplicates:
Append foreignObject containing some HTML inside an SVG element - is about a missing namespace declaration.
img Inside a foreignObject Inside an svg Inside an img - is about external images, not data URLs.
You need to encode special characters, I don't know exactly which one was the culprit, but when using encodeURIComponent on the whole <CSSImage url>, then encoding again the whole markup to pass it in the <img>, everything works fine in Chrome.
<div>Standalone:</div>
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="50" style="position:relative"><circle cx="25" cy="25" r="25" fill="red" /><foreignObject style="width: 100%; height: 100%"><html xmlns="http://www.w3.org/1999/xhtml"><style>.x {position: absolute;background: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'100'%20height%3D'50'%3E%3Ccircle%20cx%3D'50'%20cy%3D'25'%20r%3D'25'%20fill%3D'blue'%2F%3E%3C%2Fsvg%3E"); width: 100%; height: 100%;}</style><div class="x"></div></html></foreignObject></svg>
<div>As image source:</div>
<img style="position:relative" src="data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2275%22%20height%3D%2250%22%20style%3D%22position%3Arelative%22%3E%3Ccircle%20cx%3D%2225%22%20cy%3D%2225%22%20r%3D%2225%22%20fill%3D%22red%22%20%2F%3E%3CforeignObject%20style%3D%22width%3A%20100%25%3B%20height%3A%20100%25%22%3E%3Chtml%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%3E%3Cstyle%3E.x%20%7Bposition%3A%20absolute%3Bbackground%3A%20url(%22data%3Aimage%2Fsvg%2Bxml%3Butf8%2C%253Csvg%2520xmlns%253D'http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg'%2520width%253D'100'%2520height%253D'50'%253E%253Ccircle%2520cx%253D'50'%2520cy%253D'25'%2520r%253D'25'%2520fill%253D'blue'%252F%253E%253C%252Fsvg%253E%22)%3B%20width%3A%20100%25%3B%20height%3A%20100%25%3B%7D%3C%2Fstyle%3E%3Cdiv%20class%3D%22x%22%3E%3C%2Fdiv%3E%3C%2Fhtml%3E%3C%2FforeignObject%3E%3C%2Fsvg%3E">
Also note that <foreingObject>'s width and height attributes are mandatory in SVG1.1, and thus, omitting them will work only in Chrome.
So for other browsers that still have to implement this new feature
<div>Standalone:</div>
<svg xmlns="http://www.w3.org/2000/svg" width="75" height="50" style="position:relative"><circle cx="25" cy="25" r="25" fill="red" /><foreignObject width="100%" height="100%"><html xmlns="http://www.w3.org/1999/xhtml"><style>.x {position: absolute;background: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'100'%20height%3D'50'%3E%3Ccircle%20cx%3D'50'%20cy%3D'25'%20r%3D'25'%20fill%3D'blue'%2F%3E%3C%2Fsvg%3E"); width: 100%; height: 100%;}</style><div class="x"></div></html></foreignObject></svg>
<div>As image source:</div>
<img style="position:relative" src="data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2275%22%20height%3D%2250%22%20style%3D%22position%3Arelative%22%3E%3Ccircle%20cx%3D%2225%22%20cy%3D%2225%22%20r%3D%2225%22%20fill%3D%22red%22%20%2F%3E%3CforeignObject%20width%3D%22100%%22%20height%3D%22100%%22%3E%3Chtml%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%3E%3Cstyle%3E.x%20%7Bposition%3A%20absolute%3Bbackground%3A%20url(%22data%3Aimage%2Fsvg%2Bxml%3Butf8%2C%253Csvg%2520xmlns%253D'http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg'%2520width%253D'100'%2520height%253D'50'%253E%253Ccircle%2520cx%253D'50'%2520cy%253D'25'%2520r%253D'25'%2520fill%253D'blue'%252F%253E%253C%252Fsvg%253E%22)%3B%20width%3A%20100%25%3B%20height%3A%20100%25%3B%7D%3C%2Fstyle%3E%3Cdiv%20class%3D%22x%22%3E%3C%2Fdiv%3E%3C%2Fhtml%3E%3C%2FforeignObject%3E%3C%2Fsvg%3E">
I know external svg files can be linked to background images:
background-image: url(Icon.svg);
and symbols id's can be targeted from an external svg file:
background-image: url(Icons.svg#Icon-Menu);
but how can I set a background image to an inline svg symbol? (As below)
My svg is at the top of my web page body and not in an external file.
I want .test background image to be the #Icon-Menu symbol.
.test{
background:#ddd url('../#Icon-Menu');
height:100px;
width:100px;
display:block;
}
<div style="height: 0; width: 0; position: absolute; visibility: hidden;">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="Icon-Menu" viewBox="0 0 512 512">
<title>Menu</title>
<path d="M93.417,5.333H6.583c-1.654,0-3,1.346-3,3v13.334c0,1.654,1.346,3,3,3h86.833c1.654,0,3-1.346,3-3V8.333 C96.417,6.679,95.071,5.333,93.417,5.333z" />
<path d="M93.417,40.333H6.583c-1.654,0-3,1.346-3,3v13.334c0,1.654,1.346,3,3,3h86.833c1.654,0,3-1.346,3-3V43.333 C96.417,41.679,95.071,40.333,93.417,40.333z" />
<path d="M93.417,75.333H6.583c-1.654,0-3,1.346-3,3v13.334c0,1.654,1.346,3,3,3h86.833c1.654,0,3-1.346,3-3V78.333 C96.417,76.679,95.071,75.333,93.417,75.333z" />
</symbol>
</svg>
</div>
<div class="test"></div>
#Robert Longson
thats right. But you can do it this way.
But symbol is not the way it will work. Unfortunatly you have to use "g" or something like that to reference.
body {
background: url(http://www.broken-links.com/tests/images/faces.svg#devil-view);
}
http://codepen.io/Type-Style/pen/ByvKJq
It will not work if the svg is in the Markup.
An image must be a complete file.
From the SVG specification...
The ‘image’ element indicates that the contents of a complete file are to be rendered...
The same is true for background-image etc.
(1) one possible way with inline SVG would be to use symbols and DIV absolute layering:
<a class="preview-modal__device-icon-link" ng-click="setPreviewWidth('phone')">
<svg class="preview-modal__device-icon"><use xlink:href="#icon-phone">
</use></svg>
</a>
(2) Second solution would be to use a Data URI:
there is a good info here: https://css-tricks.com/using-svg/
using this tool: Mobilefish.com online conversion tool
CSS:
.logo {
background: url("data:image/svg+xml;base64,[data]");
}
HTML:
<img src="data:image/svg+xml;base64,[data]">
I have ImageMagick 6.8.5-6 up and running on MediaWiki 1.20.2 (Running on Server 2008 R2, IIS 7.5). It's doing it's thing and appears to be functioning perfectly. I'm trying to figure out how I can pass parameters to the SVG, either in wikicode or using the html tag to wrap the svg in an object tag.
Here is the SVG I'm using. (created on http://svg-edit.googlecode.com/) This is just a simple arrow or tag I'm going to use to point at stuff and label stuff.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 100" width="100%" height="100%">
<path stroke="#000000" id="Arrow" d="m2.749992,2.750002l106.118515,0l88.431496,47.250097l-88.431496,47.249901l-106.118515,0l0,-94.499998z" stroke-width="3"/>
</svg>
I need to figure out how to pass the width, height, and fill parameters, so I can set the size and color of the tag.
Wikicode doesn't work from what I've tried, so I've enabled raw html and I'm calling it like this.
<html>
<object type="image/svg+xml" data="/wiki/images/3/32/Arrow.svg">
</object>
</html>
How I get those parameters from a wiki page into that svg I have no idea?
Edit:
Desktops in my environment are running IE8, which doesn't support SVG. I just have to figure out how to tell ImageMagick to 'fill' the svg with a given color before it generates the png thumbnail.
You can't pass parameters into SVG, but you can manipulate it with Javascript. If you just want to position it, you can just position the svg element in the right place just as if it was an image.
<html>
<head>
<script>
function pointAtMe(e) {
var svg = document.getElementById("arrow");
svg.style.display = "block";
svg.style.position = "absolute";
svg.style.top = (e.target.offsetTop - 40) + "px";
svg.style.left = (e.target.offsetLeft - 110) + "px";
}
</script>
<style>
OBJECT { position: absolute; display: none } /* hide initially */
BUTTON { display: block; margin: 100 auto }
</style>
</head>
<body>
<object id="arrow" width="100px" height="100px">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 200 100" width="100%" height="100%">
<path stroke="#000000" id="Arrow" d="m2.749992,2.750002l106.118515,0l88.431496,47.250097l-88.431496,47.249901l-106.118515,0l0,-94.499998z" stroke-width="3"/>
</svg>
</object>
<div>
<button onclick="pointAtMe(event)">Button 1</button>
<button onclick="pointAtMe(event)">Button 2</button>
</div>
</body>
</html>
Note that we have to wrap it in an object element because svg elements cannot be styled.
If you want to be more clever, such as altering the contents of the SVG dynamically, you can also do that with JS.