如何在悬停和点击时切换元素样式?

时间:2019-04-15 20:27:13

标签: 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>

非常感谢。

2 个答案:

答案 0 :(得分:2)

您的代码正在清除所有圈子中类的使用,然后在被单击的圈子中切换该类,但这将始终导致被单击的圈子变为活动状态(因为您刚刚清除了所有类)。 您需要检查被点击的圈子是否已经处于活动状态并以此为依据。

通过使用事件委托,您可以使代码更简单。您不必在每个圈子上都设置事件处理程序,并且可以轻松地检查不在圈子上的点击。这称为event delegation

此外,由于您是将圈子转换为数组,因此请使用Array.forEach()方法进行循环,这比管理循环索引要简单得多。

查看内联评论:

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>

答案 1 :(得分:1)

这将按照您的预期执行:

let circles = Array.from(document.querySelectorAll('.svgcircle'));

circles.forEach(circle => {
  circle.addEventListener("click", ({target}) => {
    circles.forEach(c => target !== c && 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') 
  && 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>

希望这会有所帮助,