it-swarm.com.ru

Делаем объект изображения svg кликабельным с помощью onclick, избегая абсолютного позиционирования

Я попытался изменить изображения на своем сайте с img на svg, изменив теги img на теги embed и object. Но реализация функции onclick, которая ранее содержалась в теге img, оказывается наиболее сложной.

Я обнаружил, что onclick не действует, когда помещается внутри тега object или embed.

Итак, я создал div исключительно для svg и поместил onclick в этот тег div. Но, никакого эффекта, если посетитель не нажимает на края/отступы изображения.

Я читал о наложении div, но стараюсь избегать использования позиционирования absolute или указания position вообще.

Есть ли другой способ применить onclick к svg?

Кто-нибудь сталкивался с этой проблемой? Вопросы и предложения приветствуются.

47
user256410

Вы можете иметь событие onclick в самой SVG, я делаю это все время в своей работе. сделайте прямоугольник над пространством вашего svg (так определите его в последнюю очередь, помните, что svg использует модель художников) 

rect.btn {
  stroke:#fff;
  fill:#fff;
  fill-opacity:0;
  stroke-opacity:0;
}

затем в качестве атрибута к прямоугольнику добавьте onclick (это также можно сделать с помощью js или jquery).

<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>

это будет работать в большинстве современных браузеров, http://caniuse.com/svg ... хотя, если вам нужна перекрестная совместимость, вы можете реализовать Google Chrome Frame. http://www.google.com/chromeframe

55
RGB

Это началось с комментария к решению RGB, но я не смог его вписать, поэтому преобразовал его в ответ. Источником вдохновения для которого являются исключительно RGB.

Решение RGB сработало для меня. Тем не менее, я хотел бы отметить пару моментов, которые могут помочь другим, приходящим на этот пост (таким как я), которые не настолько знакомы с тем, какой SVG, и которые вполне могли сгенерировать свой файл SVG из графического пакета (как я это сделал).

Поэтому для применения решений RGB я использовал:

CSS

 <style>
    rect.btn {
        stroke:#fff;
        fill:#fff;
        fill-opacity:0;
        stroke-opacity:0;
    }
</style>

Скрипт 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>

HTML-код для кодирования включения вашего ранее существующего файла SVG в тег group внутри кода 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>

Тем не менее, в моем случае у меня есть несколько значков SVG, на которые я хочу кликать, и включение каждого из них в тег SVG становилось громоздким.

Поэтому в качестве альтернативного подхода, где я мог бы использовать классы, я использовал jquery.svg. Вероятно, это позорное применение этого плагина, который может делать всякие вещи с 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").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>

где HTML

<div class="svgload" style="width: 10px; height: 10px;"></div>

Преимущество моего мышления заключается в том, что я могу использовать соответствующий класс там, где когда-либо нужны значки, и избегать большого количества кода в теле HTML, что способствует удобочитаемости. И мне нужно только включить ранее существующий файл SVG один раз.

Правка: Вот более точная версия скрипта, любезно предоставленная Китом Вудом: используется настройка URL загрузки .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>
6
codepuppy

Я получил это работает в последних версиях Firefox, Chrome, Safari и Opera.

Он опирается на прозрачный div перед объектом, который имеет абсолютную позицию и устанавливает ширину и высоту, поэтому он закрывает тег объекта ниже.

Вот он, я немного ленивый и использовал встроенные стили:

<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>

Я использовал следующий JavaScript для подключения к нему события:

<script type="text/javascript">
    var toolbar = document.getElementById("toolbar");
    toolbar.onclick = function (e) {
        alert("Hello");
    };
</script>
4
Richard Garside

Это сработало, просто заменив тег <embed/> на <img/> и удалив атрибут type. 

Например, в моем коде вместо:

<embed src=\"./images/info_09c.svg\" type=\"image/svg+xml\" width=\"45\" onClick='afiseaza_indicatie($i, \"$indicatii[$i]\")'> 

который не отвечает на нажатие, я написал:

<img src=\"./images/info_09c.svg\" height=\"25\" width=\"25\" onClick='afiseaza_indicatie($i, \"$indicatii[$i]\")'> 

Он работает в Internet Explorer и Google Chrome, и я надеюсь, что и в других браузерах.

3
Mihai Daniel Frumușelu

Вы можете использовать следующий код:

<style>
    .svgwrapper {
        position: relative;
    }
    .svgwrapper {
        position: absolute;
        z-index: -1;
    }
</style>

<div class="svgwrapper" onClick="function();">
    <object src="blah" />
</div>

b3ng0 написал похожий код, но он не работает. Z-индекс родителя должен быть автоматическим.

1
Oleg Torbasow

Если вы просто используете встроенный svg, это не проблема.

<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>
  

0
peter

Возможно, вы ищете свойство pointer-events элемента SVG, о котором вы можете прочитать в документации рабочей группы SVG w3C .

Вы можете использовать CSS, чтобы установить, что происходит с элементом SVG при его нажатии и т.д.

0
Danny Bullis

Нажмите на элемент SVG <g> в <object> с событием click. Работает на 100%. Посмотрите на вложенный JavaScript в <svg>. Не забудьте вставить window.parent.location.href=, если вы хотите перенаправить родительскую страницу.

https://www.tutorialspoint.com/svg/svg_interactivity.htm

0
Imeksbank

Вы рассматривали использование свойства CSS z-index, чтобы сделать контейнер dev "поверх" svg? Поскольку div (предположительно) прозрачен, вы все равно увидите изображение точно так же, как и раньше.

Я полагаю, что это лучший, не взломанный, намеченный способ решения вашей проблемы. z-index полезен только для элементов, которые имеют свойство positionfixed, relative или, как вы слышали, absolute. Тем не менее, вам не нужно перемещать объект.

Например:

<style>
    .svgwrapper {
        position: relative;
        z-index: 1;
    }
</style>
<div class="svgwrapper" onClick="function();">
    <object src="blah" />
</div>

Для чего бы это ни стоило, было бы немного элегантнее и безопаснее вообще не использовать onClick, а вместо этого связывать событие click с помощью javascript. Впрочем, это еще одна проблема.

0
b3ng0

При встраивании SVG одинакового происхождения с использованием <object>, вы можете получить доступ к внутреннему содержимому с помощью objectElement.contentDocument.rootElement. Оттуда вы можете легко прикрепить обработчики событий (например, через onclick, addEventListener() и т.д.)

Например:

var object = /* get DOM node for <object> */;
var svg = object.contentDocument.rootElement;
svg.addEventListener('click', function() {
  console.log('hooray!');
});

Обратите внимание, что это невозможно для кросс-исходных элементов <object>, если только вы не управляете сервером <object> и не можете устанавливать заголовки CORS там. В случаях перекрестного происхождения без заголовков CORS доступ к contentDocument заблокирован.

0
candu

Предполагая, что вам не нужна кросс-браузерная поддержка (что невозможно без плагина для IE), вы пытались использовать svg в качестве фонового изображения ?

Экспериментальный материал наверняка, но подумал, что упомяну об этом.

0
Russell Leggett