Rendre un objet image svg cliquable avec onclick, en évitant le positionnement absolu
j'ai essayé de changer les images sur mon site de img
à svg
, en changeant img
tags à embed
et object
tags. Mais la mise en œuvre de la fonction onclick
, qui était auparavant contenue dans la balise img
, s'avère très difficile.
j'ai trouvé onclick
n'a eu aucun effet lorsqu'il est placé à l'intérieur de la object
ou embed
tag.
donc, j'ai fait un div
exclusivement pour le svg, et placé onclick
dans cette étiquette div
. Mais, aucun effet à moins que le visiteur clique sur les bords/rembourrage de l'image.
j'ai lu à propos de la superposition d'un div
, mais j'essaie d'éviter d'utiliser des "1519140920 positionnement", ou en spécifiant position
.
y a-t-il une autre façon d'appliquer onclick à une svg?
quelqu'un A rencontré ce problème? Les questions et les suggestions sont les bienvenues.
10 réponses
Vous pouvez avoir un événement onclick dans le svg lui-même, je le fais tout le temps dans mon travail. faites un rect sur l'espace de votre svg, (donc définissez-le en dernier, rappelez-vous svg utilise le modèle des peintres)
rect.btn {
stroke:#fff;
fill:#fff;
fill-opacity:0;
stroke-opacity:0;
}
puis comme attribut au rect ajouter le onclick (cela peut être fait avec js ou jquery aussi).
<div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<circle ... //your img svg
<rect class="btn" x="0" y="0" width="10" height="10" onclick="alert('click!')" />
</g>
</svg>
</div>
cela fonctionnera dans la plupart des navigateurs modernes, http://caniuse.com/svg ...si vous avez besoin de la croix compatibilité, Vous pouvez mettre en œuvre Google Chrome Frame. http://www.google.com/chromeframe
cela a commencé comme un commentaire sur la solution de RGB, mais je n'ai pas pu l'insérer, donc je l'ai converti en réponse. L'inspiration est entièrement de RGB.
la solution de RGB a fonctionné pour moi. Cependant, j'ai tenu à noter quelques points qui peuvent aider d'autres arrivées à ce post (comme moi) qui ne sont pas aussi familiers que SVG et qui peuvent très bien avoir généré leur fichier SVG à partir d'un paquet graphique (comme je l'ai fait).
pour appliquer les solutions de RGB J'ai utilisé:
The CSS
<style>
rect.btn {
stroke:#fff;
fill:#fff;
fill-opacity:0;
stroke-opacity:0;
}
</style>
Le script jquery
<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>
le code HTML pour coder l'inclusion de votre fichier SVG préexistant dans la balise de groupe à l'intérieur du code SVG.
<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>
cependant, dans mon cas, j'ai plusieurs icônes SVG que je souhaite être cliquable et l'intégration de chacun d'eux dans la balise SVG commençait à devenir encombrante.
comme alternative approche où je pourrais employer des Classes que j'ai utilisé jquery.svg. C'est probablement une application honteuse de ce plugin qui peut faire toutes sortes de choses avec SVG. Mais il a fonctionné en utilisant le code suivant:
<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>
où HTML
<div class="svgload" style="width: 10px; height: 10px;"></div>
L'avantage de ma pensée est que je peux utiliser la classe appropriée où jamais les icônes sont nécessaires et éviter beaucoup de code dans le corps du HTML qui favorise la lisibilité. Et j'ai seulement besoin de incorporez le fichier SVG préexistant une fois.
Edit: Ici est un plus propre version du script de courtoisie de Keith Bois: à l'aide .le réglage de l'URL de chargement de svg.
<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>
j'ai obtenu ce travail à travers les dernières versions de Firefox, Chrome, Safari et Opéra.
il s'appuie sur un div transparent devant l'objet qui a la position absolue et définit la largeur et la hauteur de sorte qu'il couvre la balise objet ci-dessous.
le voici, j'ai été un peu paresseux et utilisé des styles inline:
<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>
j'ai utilisé le JavaScript suivant pour connecter un événement à lui:
<script type="text/javascript">
var toolbar = document.getElementById("toolbar");
toolbar.onclick = function (e) {
alert("Hello");
};
</script>
il a fonctionné en remplaçant simplement la balise <embed/>
par <img/>
et en supprimant l'attribut type.
par exemple, dans mon code, au lieu de:
<embed src=\"./images/info_09c.svg\" type=\"image/svg+xml\" width=\"45\" onClick='afiseaza_indicatie($i, \"$indicatii[$i]\")'>
qui ne répond pas au clic, j'ai écrit:
<img src=\"./images/info_09c.svg\" height=\"25\" width=\"25\" onClick='afiseaza_indicatie($i, \"$indicatii[$i]\")'>
il fonctionne dans Internet Explorer et Google Chrome, et j'espère que dans les autres navigateurs aussi.
vous pouvez utiliser le code suivant:
<style>
.svgwrapper {
position: relative;
}
.svgwrapper {
position: absolute;
z-index: -1;
}
</style>
<div class="svgwrapper" onClick="function();">
<object src="blah" />
</div>
b3ng0 a écrit un code similaire mais il ne fonctionne pas. l'index z du parent doit être automatique.
avez-vous cherché à utiliser la propriété CSS z-index
pour que le conteneur dev soit" en haut " de la svg? Parce que la div est (probablement) transparente, vous verrez toujours l'image exactement comme avant.
C'est, je crois, la meilleure pratique, non-hack, destinée à résoudre votre problème. z-index
est seulement utile pour les éléments qui ont une position
propriété de fixed
, relative
, ou, comme vous l'avez entendu, absolute
. Cependant, vous n'avez pas en fait déplacer l'objet.
par exemple:
<style>
.svgwrapper {
position: relative;
z-index: 1;
}
</style>
<div class="svgwrapper" onClick="function();">
<object src="blah" />
</div>
pour ce que cela vaut, il serait également un peu plus élégant et sûr de ne pas utiliser onClick du tout, mais à la place de lier l'événement de clic en utilisant javascript. C'est une autre question tout à fait, si.
en supposant que vous n'avez pas besoin de support de navigateur croisé (ce qui est impossible sans un plugin pour IE), avez-vous essayé d'utiliser svg comme une image de fond ?
Expérimental, c'est sûr, mais j'ai pensé le mentionner.
peut-être que ce que vous recherchez est la propriété pointer-events de SVG element, que vous pouvez lire à propos de la propriété du groupe de travail SVG W3C docs .
vous pouvez utiliser CSS pour définir ce qui arrive à L'élément SVG quand il est cliqué, etc.
lors de l'intégration de SVG d'origine identique en utilisant <object>
, vous pouvez accéder au contenu interne en utilisant objectElement.contentDocument.rootElement
. De là, vous pouvez facilement attacher les gestionnaires d'événements (par exemple via onclick
, addEventListener()
, etc.)
par exemple:
var object = /* get DOM node for <object> */;
var svg = object.contentDocument.rootElement;
svg.addEventListener('click', function() {
console.log('hooray!');
});
notez qu'il s'agit de pas possible pour les éléments cross-origin <object>
sauf si vous contrôlez également le serveur <object>
et que vous pouvez y placer des en-têtes CORS. Pour cas d'origine croisée sans en-têtes CORS, l'accès à contentDocument
est bloqué.
si vous utilisez simplement inline svg, il n'y a aucun problème.
<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>