I have tried to change the images on my site from img
to svg
, changing img
tags to embed
and object
tags. Bu
Assuming you don't need cross browser support (which is impossible without a plugin for IE), have you tried using svg as a background image?
Experimental stuff for sure, but thought I would mention it.
I got this working accross the latest versions of Firefox, Chrome, Safari and Opera.
It relies on a transparent div before the object that has absolute position and set width and height so it covers the object tag below.
Here it is, I've been a bit lazy and used inline styes:
<div id="toolbar" style="width: 600px; height: 100px; position: absolute; z-index: 1;"></div>
<object data="interface.svg" width="600" height="100" type="image/svg+xml">
</object>
I used the following JavaScript to hook up an event to it:
<script type="text/javascript">
var toolbar = document.getElementById("toolbar");
toolbar.onclick = function (e) {
alert("Hello");
};
</script>
When embedding same-origin SVGs using <object>
, you can access the internal contents using objectElement.contentDocument.rootElement
. From there, you can easily attach event handlers (e.g. via onclick
, addEventListener()
, etc.)
For example:
var object = /* get DOM node for <object> */;
var svg = object.contentDocument.rootElement;
svg.addEventListener('click', function() {
console.log('hooray!');
});
Note that this is not possible for cross-origin <object>
elements unless you also control the <object>
origin server and can set CORS headers there. For cross-origin cases without CORS headers, access to contentDocument
is blocked.
If you just use inline svg there is no problem.
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" style="width: 3.5in; height: 1in">
<circle id="circle1" r="30" cx="34" cy="34" onclick="circle1.style.fill='yellow';"
style="fill: red; stroke: blue; stroke-width: 2"/>
</svg>
This started as a comment on RGB's solution but I could not fit it in so have converted it to an answer. The inspiration for which is entirely RGB's.
RGB's solution worked for me. However, I wished to note a couple of points which may help others arriving at this post (like me) who are not that familiar which SVG and who may very well have generated their SVG file from a graphics package (as I had).
So to apply RGB's solutions I used:
The CSS
<style>
rect.btn {
stroke:#fff;
fill:#fff;
fill-opacity:0;
stroke-opacity:0;
}
</style>
The jquery script
<script type="text/javascript" src="../_public/_jquery/jquery-1.7.1.js"></script>
<script type="text/javascript">
$("document").ready(function(){
$(".btn").bind("click", function(event){alert("clicked svg")});
});
</script>
The HTML to code the inclusion of your pre-existing SVG file in the group tag inside the SVG code.
<div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<image x="0" y="0" width="10" height="10"
xlink:href="../_public/_icons/booked.svg" width="10px"/>
<rect class="btn" x="0" y="0" width="10" height="10"/>
</g>
</svg>
</div>
However, in my case I have several SVG icons which I wish to be clickable and incorporating each of these into the SVG tag was starting to become cumbersome.
So as an alternative approach where I could employ Classes I used jquery.svg. This is probably a shameful application of this plugin which can do all sorts of stuff with SVG's. But it worked using the following code:
<script type="text/javascript" src="../_public/_jquery/jquery-1.7.1.js"></script>
<script type="text/javascript" src="jquery.svg.min.js"></script>
<script type="text/javascript">
$("document").ready(function(){
$(".svgload").bind("click", function(event){alert("clicked svg")});
for (var i=0; i < 99; i++) {
$(".svgload:eq(" + i + ")").svg({
onLoad: function(){
var svg = $(".svgload:eq(" + i + ")").svg('get');
svg.load("../_public/_icons/booked.svg", {addTo: true, changeSize: false});
},
settings: {}}
);
}
});
</script>
where HTML
<div class="svgload" style="width: 10px; height: 10px;"></div>
The advantage to my thinking is that I can use the appropriate class where ever the icons are needed and avoid quite a lot of code in the body of the HTML which aids readability. And I only need to incorporate the pre-existing SVG file once.
Edit: Here is a neater version of the script courtesy of Keith Wood: using .svg's load URL setting.
<script type="text/javascript" src="../_public/_jquery/jquery-1.7.1.js"></script>
<script type="text/javascript" src="jquery.svg.min.js"></script>
<script type="text/javascript">
$("document").ready(function(){
$('.svgload').on('click', function() {
alert('clicked svg new');
}).svg({loadURL: '../_public/_icons/booked.svg'});
});
</script>
Have you looked into using the CSS z-index
property to make the container dev be "on top" of the svg? Because the div is (presumably) transparent, you will still see the image exactly as before.
This, I believe, is the best-practice, non-hack, intended way of solving your problem. z-index
is only useful for elements that have a position
property of fixed
, relative
, or, as you've heard, absolute
. However, you don't actually have to move the object.
For example:
<style>
.svgwrapper {
position: relative;
z-index: 1;
}
</style>
<div class="svgwrapper" onClick="function();">
<object src="blah" />
</div>
For what it's worth, it would also be a little more elegant and safe to not use onClick at all, but instead to bind the click event using javascript. That's another issue altogether, though.