Использование JS и SVG

198
16 июня 2018, 07:50

Вопрос касается JS + SVG. Долго думал сюда написать, но уже несколько дней не могу найти решение, прошу помочь разобраться.

Примерный код я напишу внизу, но суть следующая: есть обёртка, в которой находятся 2 элемента, картинка и иконка из SVG. Иконка спозицирнирована абсолютно (в примерном коде будет иначе) поверх картинки. При наведении на картинку иконка меняется посредством замены пути в USE. При клике на обёртку должно рпоисходить некое действие.

На практике же у меня получается либо изменить иконку, либо выполнить действие при клике. Конечно, можно заменить SVG и картинку единой картинкой, которая меняется при наведении курсора посредством CSS, но я бы предпочёл всё же SVG. Ради интереса пробовал на цветных квадратах всё делать и заметил, что если менять цвет квадрата через свойства CSS (..style.backgroundColor и даже картинки можно), то клик работает. Также пробовал использовать setTimeout, но использование под вопросом, т.к. задержка при наведении срабатывает, да и клик не всегда пройдёт, прям русская рулетка. А чтобы боле менее проходила, нужна и задержка нормальная.

В общем, идеи иссякли, если знаете что нужно дописать, подскажите.

var wrapper = document.querySelector(".wrapper"); 
var image = document.querySelector(".image"); 
var icon_svg = document.querySelector(".icon-svg"); 
 
image.addEventListener('mouseover', function() { 
  if (!icon_svg.firstElementChild.classList.contains('#play_icon_active')) { 
     icon_svg.firstElementChild.setAttribute('xlink:href', 'svg_sprite.svg#play_icon_active'); 
  } 
}); 
 
image.addEventListener('mouseout', function() { 
  icon_svg.firstElementChild.setAttribute('xlink:href', 'svg_sprite.svg#play_icon'); 
}); 
 
wrapper.addEventListener('click', function() { 
  alert("OK"); 
});
.wrapper { 
  width: 50vw; 
  height: 30vh; 
  background-color: green; 
} 
 
.image { 
  width: 50%; 
  height: 100%; 
  margin: 0 auto; 
  background-color: blue; 
} 
 
.icon-svg { 
  width: 50%; 
  height: 50%; 
}
<object type="image/svg+xml" data="svg_sprite.svg"> 
</object> 
<div class="wrapper"> 
  <div class="image"> 
    <svg class="icon-svg"> 
               <use xlink:href="svg_sprite.svg#play_icon"> 
               </use> 
            </svg> 
  </div> 
</div>

Answer 1

Разметка не совсем такая, как у вас, но проблема понятна.

Дело в том, что у вас не верно условие if (!icon_svg.firstElementChild.classList.contains('#play_icon_active')). Из-за этого постоянно срабатывает событие mouseover и меняет атрибут, как следствие клик просто не происходит.

Решение:

  • Написать правильное условие.
  • На всякий случай использовать для .icon-svg стиль pointer-events: none; что бы событие клика не обращало внимание на svg.

Пример.

var wrapper = document.querySelector(".wrapper"); 
var image = document.querySelector(".image"); 
var icon_svg = document.querySelector(".icon-svg") 
 
image.addEventListener('mouseover', function() { 
  if (icon_svg.firstElementChild.getAttribute('href') !== '#play_icon_active') { 
    icon_svg.firstElementChild.setAttribute('href', '#play_icon_active'); 
  } 
}); 
 
image.addEventListener('mouseout', function() { 
  icon_svg.firstElementChild.setAttribute('href', '#play_icon'); 
}); 
 
wrapper.addEventListener('click', function() { 
  console.log("OK"); 
});
.wrapper { 
  width: 50vw; 
  height: 30vh; 
  background-color: green; 
} 
 
.image { 
  width: 50%; 
  height: 100%; 
  margin: 0 auto; 
  background-color: blue; 
} 
 
.icon-svg { 
  width: 50%; 
  height: 50%; 
  pointer-events: none; 
  /* Делаем "прозрачным" для событий*/ 
}
<svg xmlns="w3.org/2000/svg" style="display:none;"> 
  <symbol id="play_icon" viewBox="0 0 171 170"><circle fill="none" stroke="#FFF" stroke-width="14" stroke-miterlimit="10" cx="86" cy="85" r="77.5"/><circle opacity=".35" fill="#138ACE" cx="85.5" cy="84.5" r="75.5"/><path fill="#FFF" d="M58.5 121.9L128 85.6 58.6 48.9z"/> 
  </symbol> 
  <symbol id="play_icon_active" viewBox="0 0 169.8 170"><circle fill="none" stroke="#2b93d4" stroke-width="14" stroke-miterlimit="10" cx="84.8" cy="85" r="77.5"/><circle opacity=".4" fill="#fff" cx="84.3" cy="84.5" r="75.5"/> 
  <path fill="#2b93d4" d="M57.3 121.9l69.5-36.3-69.4-36.7z"/> 
  </symbol> 
</svg> 
 
<div class="wrapper"> 
  <div class="image"> 
    <svg class="icon-svg"> 
       <use href="#play_icon" /> 
    </svg> 
  </div> 
</div>

READ ALSO
Есть ли обработчик события Click у элемента?

Есть ли обработчик события Click у элемента?

Подвесил на кнопку Next слайдера Slick свой обработчик события ClickОн срабатывает один раз, а потом перестает

174
socket io как реализовать валидность данных [закрыт]

socket io как реализовать валидность данных [закрыт]

Создаю игру на node jsВ качестве соединения использую socket io

135
Переменная как название массива

Переменная как название массива

Можно ли как-нибудь задать название массива значением переменной?

191
background url не работает правильно

background url не работает правильно

image_url получаю из json но при загрузке к данному пути в начале прибавляется путь самого html файла

156