Как сделать прозрачную часть SVG кликабельной?

У меня есть SVG, который использует :hover для изменения цвета. Это работает только при наведении курсора на сплошную часть SVG, а не на прозрачную часть. Мне интересно, как вы могли бы заставить SVG взаимодействовать с мышью, зависающей в любом месте над всем SVG. Смысл этого в том, чтобы сделать SVG ссылкой, а ссылку можно щелкнуть только в определенных частях SVG. Мне нужно не просто решение для этого конкретного случая, а решение, которое работает для многих случаев (если бы я хотел, чтобы разные части SVG были интерактивными). Элементы в моем SVG напрямую связаны с CSS и сгруппированы с помощью тега ‹g> для группировки кликабельных элементов.

Редактировать: SVG находится в теге объекта

SVG

<?xml-stylesheet type="text/css" href="svg.css" ?>
<svg xmlns:osb="http://www.openswatchbook.org/uri/2009/osb" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" id="svg3036" version="1.1" inkscape:version="0.48.2 r9819" width="58" height="58">
         <g class="test">
  <path d="M 8.1 32.8 C 7.1 30.1 0.3 -4.6 11.1 4.9 21.9 14.5 15.9 12.8 29 12.8 42.1 12.9 36.1 14.6 46.9 5.1 57.7 -4.5 50.9 30.3 49.9 32.9 48.9 35.6 37.6 54.8 29 54.7 20.4 54.6 9.1 35.4 8.1 32.8 z" id="path3119" inkscape:connector-curvature="0" sodipodi:nodetypes="zzzzzzz" class="wolf"/>
  <path d="M 31.5 23.3 46.6 21" id="path5212" inkscape:connector-curvature="0" sodipodi:nodetypes="cc" class="eyes"/>
  <path d="M 33 23 C 32.3 33.9 45 22 45.2 21" id="path5260" inkscape:connector-curvature="0" sodipodi:nodetypes="cc" class="eyes"/>
  <path sodipodi:nodetypes="cc" inkscape:connector-curvature="0" id="path5262" d="M 26.5 23.3 11.4 21" class="eyes"/>
  <path sodipodi:nodetypes="cc" inkscape:connector-curvature="0" id="path5264" d="M 25 23 C 25.7 33.9 13 22 12.8 21" class="eyes"/>
  </g>
</svg>

CSS

.wolf{
    fill:   none;
    fill-opacity:   0;
    stroke-width:   3.672px;
    stroke-linejoin:    round;
} /*.wolf:hover {
    stroke: #777777;
}*/

.eyes{
    fill:   none;
    fill-opacity: 0;
    stroke-width:   1.26708329px;
}

.test {
    stroke: #5ff6ff;
} .test:hover {
    stroke: #555555;
}     

JSfiddle


person Sam Sabin    schedule 15.03.2014    source источник
comment
поставить :hover на элемент svg? (если я что-то не упустил)   -  person Michael Mullany    schedule 15.03.2014
comment
Извините, я забыл добавить это в тег объекта   -  person Sam Sabin    schedule 15.03.2014
comment
Живой пример, jsfiddle или что-то в этом роде?   -  person CBroe    schedule 15.03.2014
comment
Установите высоту и ширину.   -  person itsclarke    schedule 15.03.2014
comment
Тег объекта имеет высоту и ширину. Почему это важно?   -  person Sam Sabin    schedule 15.03.2014
comment
Окружить его div-оболочкой и навести на него курсор?   -  person nickspiel    schedule 15.03.2014
comment
Это будет работать, но сделает все это ссылкой, не указанной в какой-либо определенной области.   -  person Sam Sabin    schedule 15.03.2014
comment
jsfiddle не существует   -  person Ram Tobolski    schedule 02.07.2020


Ответы (6)


SVG2 добавляет новое ключевое слово bounding-box к 'pointer-events', чтобы упростить эту задачу. Это относится как к группам, так и к фигурам, в вашем примере это будет:

.test {
  pointer-events: bounding-box;
  stroke: #5ff6ff;
}
.test:hover {
  stroke: #555555;
}

См. jsfiddle. Сейчас это должно работать в сборках Chrome Canary или Opera Dev.

Это зависит от форм, но его можно заставить работать и в браузерах, поставляемых в настоящее время. Например, используя pointer-events="all" на самой большой фигуре, а затем творчески используя селекторы CSS, чтобы нанести обводку там, где вы хотите. Это немного сложно, поскольку вы, вероятно, хотите, чтобы обводка применялась к группе, хотя на самом деле зависший элемент — это фигура внутри группы.

Другой альтернативой является сценарий, использующий события mouseenter и mouseleave для элемента ‹g>.

person Erik Dahlström    schedule 17.03.2014

Существующие ответы на этот вопрос «события указателя» помогли мне найти это решение:

<svg id="example" pointer-events="bounding-box" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 300">

pointer-events="bounding-box" лучше всего размещать внутри тега SVG, если у вас есть прозрачные области, которые вы хотите активировать, например, со значком или (как указано выше) логотипом, ведущим на домашнюю страницу веб-сайта со встроенной ссылкой (определяемой как xlink:href).

person Henry's Cat    schedule 17.12.2018

Вы можете включить pointer-events="visible" в тест <g> и вызов функции, где функция находится в родительском HTML (это проверено в IE/CH/FF), например

<svg xmlns:osb="http://www.openswatchbook.org/uri/2009/osb" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" id="svg3036" version="1.1" inkscape:version="0.48.2 r9819" width="58" height="58">
         <g pointer-events="visible" onclick="parent.testHover()" class="test" fill="none" stroke="black" stroke-width="2">
  <path d="M 8.1 32.8 C 7.1 30.1 0.3 -4.6 11.1 4.9 21.9 14.5 15.9 12.8 29 12.8 42.1 12.9 36.1 14.6 46.9 5.1 57.7 -4.5 50.9 30.3 49.9 32.9 48.9 35.6 37.6 54.8 29 54.7 20.4 54.6 9.1 35.4 8.1 32.8 z" id="path3119" inkscape:connector-curvature="0" sodipodi:nodetypes="zzzzzzz" class="wolf"/>
  <path d="M 31.5 23.3 46.6 21" id="path5212" inkscape:connector-curvature="0" sodipodi:nodetypes="cc" class="eyes"/>
  <path d="M 33 23 C 32.3 33.9 45 22 45.2 21" id="path5260" inkscape:connector-curvature="0" sodipodi:nodetypes="cc" class="eyes"/>
  <path sodipodi:nodetypes="cc" inkscape:connector-curvature="0" id="path5262" d="M 26.5 23.3 11.4 21" class="eyes"/>
  <path sodipodi:nodetypes="cc" inkscape:connector-curvature="0" id="path5264" d="M 25 23 C 25.7 33.9 13 22 12.8 21" class="eyes"/>
  </g>
</svg>

РЕДАКТИРОВАТЬ - Добавлено.

Я протестировал использование вашего svg в качестве источника для <img>, а не <object>, и поместил его в ссылку. Это работает, кликабельно во всех браузерах. Нет необходимости добавлять события указателя или вызов функции. Поэтому вы можете использовать img, а не объект.

person Francis Hemsher    schedule 15.03.2014
comment
Это делает внутреннюю часть кликабельной, но работает ли она для любой области, которую я хотел бы кликнуть? Этого также можно добиться, добавив прозрачную заливку к элементу волка. Мне нужно, чтобы это была ссылка, как это сделать, обернув ее тегом ‹a›, это не работает. - person Sam Sabin; 16.03.2014

Если вы хотите получить действительный HTML-документ в конце. Окружите элемент svg тегом привязки, если вы планируете превратить его в ссылку.

Также не забудьте превратить ссылку в блочный или встроенный блочный элемент. (Это зависит от ваших потребностей)

person Oz Lodriguez    schedule 15.03.2014
comment
Мой SVG уже связан внутри тега объекта. Я не хочу это менять, иначе мне придется использовать встроенный CSS для SVG. Прямо сейчас SVG подключен к CSS через внешнюю таблицу стилей. - person Sam Sabin; 15.03.2014
comment
Хм, тогда я приглашаю вас превратить ваш SVG в шрифт. Это кажется более эффективным по сравнению с тем, что вы хотите сделать. Проверьте fortawesome.github.io/Font-Awesome для справки и проверьте fontastic.me для создания собственного. Создание собственной библиотеки svg и модульный способ многократного использования ее на вашем сайте. - person Oz Lodriguez; 15.03.2014
comment
Это довольно хорошее решение, но я хочу знать, как это сделать независимо. - person Sam Sabin; 16.03.2014

Есть хак, который вы можете сделать, используя фильтр. Эффекты фильтра могут менять заливку на прозрачную, не изменяя ее кликабельность. Ниже вы добавляете полупрозрачную заливку к графике, но затем используете фильтр для ее удаления.

.wolf{
    fill:   blue;
     fill-opacity:  0.09;
    stroke-width:   3.672px;
    stroke-linejoin:    round;
} /*.wolf:hover {
    stroke: #777777;
}*/

.eyes{
    fill:   none;
    fill-opacity: 0;
    stroke-width:   1.26708329px;
}

    <defs>
        <filter id="greenscreen">
        <feComponentTransfer>
            <feFuncA type="table" tableValues="0 0 .2 .3 .4 .5 .6 .7 .8 .9 1"/>
        </feComponentTransfer>
    </filter>
    </defs>
  <g class="test" filter="url(#greenscreen)">

etc.
person Michael Mullany    schedule 16.03.2014
comment
какое это имеет значение, если у вас осталась прозрачная заливка? - person Sam Sabin; 17.03.2014

Изменить: svg:hover .test { stroke: #555555}

Игнорируйте предыдущий ответ (ниже), он касался другой проблемы.

Создайте пустой прозрачный объект, т. е. <rect> такого же размера и формы, как <svg>, и поместите его непосредственно перед </a></svg> (не переносите!).

person Lucian Davidescu    schedule 21.08.2016