Как отловить события щелчка SVG, которые попадают в окно просмотра, а не на элементы в нем? - PullRequest
3 голосов
/ 23 мая 2019

У меня есть файл SVG с различными путями, он встроен в HTML-страницу с помощью тега object.Javascript используется для обеспечения некоторой интерактивности для каждого пути - при щелчке по нему отображается всплывающая подсказка rect.Вот как это выглядит:

Paths in an SVG file

Я хочу, чтобы подсказка исчезла, когда кто-то щелкает за пределами пути, с которым связана подсказка, это реализованодобавив такой обработчик событий к каждому пути:

path.addEventListener("click", function(event){
    if (!isTipShown()){
        createTooltip()
    }
    else{
        hideTooltip()
    }
})

isTipShown, createTooltip и hideTooltip - это функции, которые проверяют SVG DOM и соответственно изменяют его.

Это работает, но он завершается неудачно, если щелчок переходит в пустое пространство между самими путями - потому что нет объекта, который может его перехватить.

Какой подход может быть выбран для реализации такой функциональности?

Мои текущие мысли:

  • Создайте прозрачный прямоугольник, который покрывает весь видовой экран, и используйте его в качестве цели щелчка.Как можно убедиться, что прямоугольник идет ко всему?
  • Обработчик кликов для всего HTML-документа делает свое дело, но только если пользователи щелкают за пределами самого окна просмотра.

Ответы [ 2 ]

1 голос
/ 23 мая 2019

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

SVG не имеет понятия слоев , но этого можно добиться, убедившись, что rect равен до всех элементов в DOM SVG и всех последующих элементы будут размещены поверх него, визуально:

<rect x="0" y="0" width="30" height="30" fill="purple"/>
<rect x="20" y="5" width="30" height="30" fill="blue"/>
<rect x="40" y="10" width="30" height="30" fill="green"/>
<rect x="60" y="15" width="30" height="30" fill="yellow"/>
<rect x="80" y="20" width="30" height="30" fill="red"/>

Layered squares

Вот как это было сделано на практике (переменная svgDoc является корневым элементом SVG):

    function createBackgroundRectangle(svgDoc){
        var rect = svgDoc.createElementNS("http://www.w3.org/2000/svg", 'rect')
        rect.setAttributeNS(null, 'height', 500)
        rect.setAttributeNS(null, 'width', 900)
        rect.setAttributeNS(null, 'id', 'pseudo-background')
        rect.setAttributeNS(null, 'x', 0)
        rect.setAttributeNS(null, 'y', 0)
        // the opacity is set to 0, so it doesn't get in the way visually. For debugging
        // purposes, you can change it to another value and see the actual rectangle
        rect.setAttributeNS(null, 'style', 'opacity:0;fill:#ffd42a;fill-opacity:1;')
        svgDoc.rootElement.insertBefore(rect, svgDoc.rootElement.children[0])
    }

svgDoc.rootElement.insertBefore(rect, svgDoc.rootElement.children[0]) делает его первым, поскольку он вставляется перед текущим дочерним элементом с индексом 0.

0 голосов
/ 23 мая 2019

Подсказка по фигурам не моя SVG!

Как лучше всего удалить всплывающую подсказку при нажатии svg?
Они решили, что это так:

  1. ID во всплывающей подсказке.
  2. Изменить существующую подсказку с идентификатором.
  3. Удалить подсказку с идентификатором при нажатии в другом месте

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

Вот пример:

document.addEventListener("DOMContentLoaded", function() {
  var pathRed = document.getElementById("red");
  var pathOrange = document.getElementById("orange");
  var pathBlue = document.getElementById("blue");
  var paths = [pathRed, pathOrange, pathBlue];

  var toolTip = document.createElement("div");
  toolTip.id = "toolTip";
  var svg = document.getElementById("box");
  var shown = false;

  paths.forEach(function(element) {
    element.addEventListener("click", function(event) {
      if (shown == false) {
        toolTip.innerText = element.id;
        toolTip.style.top = (event.pageY) + "px";
        toolTip.style.left = (event.pageX) + "px";
        document.body.appendChild(toolTip);
        shown = true;
        //Only click the path
        event.stopPropagation();
      } else {
        removeToolTip();
      }
    });
  });

  svg.addEventListener("click", function(event) {
    removeToolTip();
    event.preventDefault();
  });

  function removeToolTip() {
    shown = false;
    if (document.body.contains(toolTip)) {
      document.body.removeChild(toolTip);
    }
  }

});
#toolTip {
  position: absolute;
  background-color: #00000099;
  padding: 2px;
  border-radius: 2px;
  color: white;
  font-size: 20px;
}
<h1>Click the boxes!</h1>
<svg id="box" viewBox="0 0 15 15" width="250px">
  <path id="red" fill="red" d="m0,0 5,0 0,5 -5,0Z"/>
  <path id="orange" fill="orange" d="m5,5 5,0 0,5 -5,0Z"/>
  <path id="blue" fill="blue" d="m10,10 5,0 0,5 -5,0Z"/>
</svg>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...