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

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

Я обнаружил, что onclick не имеет эффекта при размещении внутри тега object или embed.

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

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

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

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

Ответ 1

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

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

то в качестве атрибута rect добавьте 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

Ответ 2

Это началось с комментария к решению 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>

Ответ 3

Я работал над последними версиями 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

Он работал, просто заменив тег <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, и я надеюсь, что в других браузерах тоже.

Ответ 5

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

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

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

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

Ответ 6

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

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

Например:

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

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

Ответ 7

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

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

Ответ 8

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

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

Ответ 9

При встраивании 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!');
});

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

Ответ 10

Если вы просто используете inline 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>