#javascript #css
#javascript #css
Вопрос:
У меня есть 4 круга SVG, и я хочу переключать их стиль при наведении и при нажатии. Я хочу, чтобы при щелчке по одному кругу одновременно отображался стиль, т.Е. Стиль удаляется из одного круга при щелчке по другому. Наведение работает с использованием CSS, но мой JavaScript не совсем корректен.
Он удаляет стиль из одного круга при нажатии на другой, но не позволяет переключать класс стиля из активного целевого круга. Также как я могу удалить стиль из круга, если щелкнуто что-либо за пределами кругов SVG?
var circles = document.querySelectorAll('.svgcircle')
circles = Array.prototype.slice.call(circles);
for (i = 0; i < circles.length; i ) {
(function(index) {
circles[index].addEventListener("click", function() {
var targetcircle = event.target;
for (var j = 0; j < circles.length; j ) {
circles[j].classList.remove("circleTarget");
}
targetcircle.classList.toggle("circleTarget");
})
})(i);
}
html,
body {
height: 100%;
width: 100%;
overflow: hidden;
}
svg {
position: absolute;
top: 35%;
left: 50%;
margin-left: -200px;
padding: 10px;
}
svg circle {
fill: #B5EF8A;
cursor: pointer;
stroke: #56CBF9;
stroke-width: 2px;
}
svg circle:hover {
fill: #fff;
stroke: #56CBF9;
}
.circleTarget {
fill: #fff;
stroke: #56CBF9;
}
<svg height="100" width="400" id="svg">
<circle class="svgcircle" cx="50" cy="50" r="40" />
<circle class="svgcircle" cx="150" cy="50" r="40" />
<circle class="svgcircle" cx="250" cy="50" r="40" />
<circle class="svgcircle" cx="350" cy="50" r="40" />
</svg>
Большое спасибо.
Ответ №1:
Ваш код очищает использование классов во всех ваших кругах, а затем переключает класс на тот, на который был нажат, но это всегда приведет к тому, что выбранный круг станет активным (потому что вы только что очистили все классы). Вам нужно будет проверить, был ли уже активен круг, на который нажимается, и действовать на основе этого.
Используя делегирование событий, вы можете сделать код намного проще.Вам не нужно будет настраивать обработчики событий для каждого круга, и вы можете легко проверить наличие кликов, которые не были в кругах. Это называется делегированием событий.
Кроме того, поскольку вы преобразуете свои круги в массив, используйте Array.forEach()
метод to loop , который намного проще, чем управление индексами цикла.
Смотрите Комментарии встроенные:
var circles = Array.prototype.slice.call(document.querySelectorAll('.svgcircle'));
// Setting the event listener on the document, kills two birds
// with one stone. It removes the need to set click event handlers
// on each circle and it allows for easy checking to see if you
// clicked on anything other than a circle.
document.addEventListener("click", function(evt){
// Check to see if the clicked element was one of the circles:
if(evt.target.classList.contains("svgcircle")){
// It was, so capture whether the clicked circle is active already
let active = evt.target.classList.contains("circleTarget");
removeClass(); // Reset the class usage on all the circles
// If the clicked circle was active, deactivate it.
// Otherwise, activate it:
if(active){
evt.target.classList.remove("circleTarget");
} else {
evt.target.classList.add("circleTarget");
}
} else {
// It wasn't, so clear all the styling from all the circles
removeClass();
}
});
function removeClass(){
// Loop over all the circles and remove the target class
circles.forEach(function(cir){
cir.classList.remove("circleTarget");
});
}
html,
body {
height: 100%;
width: 100%;
overflow: hidden;
}
svg {
position: absolute;
top: 35%;
left: 50%;
margin-left: -200px;
padding: 10px;
}
svg circle {
fill: #B5EF8A;
cursor: pointer;
stroke: #56CBF9;
stroke-width: 2px;
}
svg circle:hover {
fill: #fff;
stroke: #56CBF9;
}
.circleTarget {
fill: #fff;
stroke: #56CBF9;
}
<svg height="100" width="400" id="svg">
<circle class="svgcircle" cx="50" cy="50" r="40" />
<circle class="svgcircle" cx="150" cy="50" r="40" />
<circle class="svgcircle" cx="250" cy="50" r="40" />
<circle class="svgcircle" cx="350" cy="50" r="40" />
</svg>
Ответ №2:
Это будет работать так, как вы ожидаете:
let circles = Array.from(document.querySelectorAll('.svgcircle'));
circles.forEach(circle => {
circle.addEventListener("click", ({target}) => {
circles.forEach(c => target !== c amp;amp; c.classList.remove("circleTarget"));
target.classList.toggle("circleTarget");
})
});
// Remove class if anything else is clicked
document.body.addEventListener('click', ({target}) =>
!Array.from(target.classList).includes('svgcircle')
amp;amp; circles.forEach(c => c.classList.remove("circleTarget")));
html,
body {
height: 100%;
width: 100%;
overflow: hidden;
}
svg {
position: absolute;
top: 35%;
left: 50%;
margin-left: -200px;
padding: 10px;
}
svg circle {
fill: #B5EF8A;
cursor: pointer;
stroke: #56CBF9;
stroke-width: 2px;
}
svg circle:hover {
fill: #fff;
stroke: #56CBF9;
}
.circleTarget {
fill: #fff;
stroke: #56CBF9;
}
<svg height="100" width="400" id="svg">
<circle class="svgcircle" cx="50" cy="50" r="40" />
<circle class="svgcircle" cx="150" cy="50" r="40" />
<circle class="svgcircle" cx="250" cy="50" r="40" />
<circle class="svgcircle" cx="350" cy="50" r="40" />
</svg>
Надеюсь, это поможет,
Комментарии:
1. Это справедливый момент, я обновил свой ответ.
.forEach()
это было мое намерение, просто, должно быть, вылетело из головы в то время