1

I have these bubbles which are linked to the background behind them. Each bubble is associated with a different background and for example, if the first bubble is the active bubble then the background is red, if the second bubble is active the background turns blue and so on. To make a bubble active you simply have to hover over it. Another way to change which bubble is active is by not doing anything and every 5 seconds the next bubble is going to become active.

Everything works well and as expected but there is a tiny bug.

If you hover over a bubble this is going to make the bubble active but if you keep the mouse there eventually (after 5 seconds) the active bubble is going to become the next bubble despite the mouse being over the original bubble. The question is - is there a way to pause the setInterval function while the user has the mouse over any of the circles and once the mouse isn't on any of the bubbles setInterval to resume?

jQuery($ => {
  let $rect = $('.rect')
  let $circles = $('.circle').on('mouseover', setActiveCircle)
  $circles.first().trigger('mouseover')

  function setActiveCircle() {
    $circles.removeClass('active-circle')
    $(this).addClass('active-circle')
    $rect.removeClass('rect-1 rect-2 rect-3 rect-4').addClass($(this).data('rect'))
  }

  setInterval(function() {
    let $activeCircle = $circles.filter('.active-circle')
    let $targetCircle = $activeCircle.next()
    if ($targetCircle.length === 0)
      $targetCircle = $circles.first()

    setActiveCircle.call($targetCircle)
  }, 5000)
})
.rect {
  display: flex;
  justify-content: center;
  background: #fbc1d7;
  padding: 50px;
  background-size: cover;
  background-position: center;
}

.rect-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: 1100px;
}

.rect-1 {
  background: red;
}

.rect-2 {
  background: blue;
}

.rect-3 {
  background: yellow;
}

.rect-4 {
  background: green;
}

.grid-2-small {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.circle {
  height: 200px;
  width: 200px;
  border-radius: 50%;
  background-color: #910700;
  opacity: .4;
  transition: ease .5s;
  cursor: pointer;
}

.circle:hover {
  opacity: .7;
  transform: scale(1.05);
  text-decoration: none;
}

.active-circle {
  opacity: .9;
  transform: scale(1.25);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="rect">
  <div class="rect-container">
    <div></div>
    <div>
      <div class="grid-2-small">
        <a class="circle" data-rect="rect-1"></a>
        <a class="circle" data-rect="rect-2"></a>
        <a class="circle" data-rect="rect-3"></a>
        <a class="circle" data-rect="rect-4"></a>
      </div>
    </div>
  </div>
</div>
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • There's no native way to pause and resume an interval. You can emulate the behavior by clearing an interval, and then recreate it when needed. [Some examples at SO](https://stackoverflow.com/questions/24724852/pause-and-resume-setinterval). – Teemu Jun 26 '20 at 11:27
  • https://stackoverflow.com/questions/21277900/how-can-i-pause-setinterval-functions – Teemu Jun 26 '20 at 11:32

2 Answers2

1

You could check in the interval handler if one of the circles is currently active. It's relatively easy by using the .circle:hover selector:

  ...

  setInterval(function() {
    // check if one of the circle is currently active (mouse over)
    const hoverCircle = document.querySelector('.circle:hover');
    if (hoverCircle) {
        return; // do not change the background
    }
    let $activeCircle = $circles.filter('.active-circle')
    let $targetCircle = $activeCircle.next()
    if ($targetCircle.length === 0)
      $targetCircle = $circles.first()

    setActiveCircle.call($targetCircle)
  }, 5000)
})
...
vstm
  • 12,407
  • 1
  • 51
  • 47
0

You can use clearInterval here is a working example jsfiddle

jQuery($ => {
  let $rect = $('.rect')
  let $circles = $('.circle').on('mouseover', setActiveCircle)
  $circles.first().trigger('mouseover')

  function setActiveCircle() {
    $circles.removeClass('active-circle')
    $(this).addClass('active-circle')
    $rect.removeClass('rect-1 rect-2 rect-3 rect-4').addClass($(this).data('rect'))
  }
  function circletimer(){
    let $activeCircle = $circles.filter('.active-circle')
    let $targetCircle = $activeCircle.next()
    if ($targetCircle.length === 0)
      $targetCircle = $circles.first()

    setActiveCircle.call($targetCircle)
  }

 var stopinter=setInterval(circletimer(), 5000)
  
  if(  $circles.first().trigger('mouseover'))  clearInterval(stopinter)


})
.rect {
  display: flex;
  justify-content: center;
  background: #fbc1d7;
  padding: 50px;
  background-size: cover;
  background-position: center;
}

.rect-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: 1100px;
}

.rect-1 {
  background: red;
}

.rect-2 {
  background: blue;
}

.rect-3 {
  background: yellow;
}

.rect-4 {
  background: green;
}

.grid-2-small {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.circle {
  height: 200px;
  width: 200px;
  border-radius: 50%;
  background-color: #910700;
  opacity: .4;
  transition: ease .5s;
  cursor: pointer;
}

.circle:hover {
  opacity: .7;
  transform: scale(1.05);
  text-decoration: none;
}

.active-circle {
  opacity: .9;
  transform: scale(1.25);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="rect">
  <div class="rect-container">
    <div></div>
    <div>
      <div class="grid-2-small">
        <a class="circle" data-rect="rect-1"></a>
        <a class="circle" data-rect="rect-2"></a>
        <a class="circle" data-rect="rect-3"></a>
        <a class="circle" data-rect="rect-4"></a>
      </div>
    </div>
  </div>
</div>
Sven.hig
  • 4,449
  • 2
  • 8
  • 18