JS создать мигание с использованием классов и тайм-аутов? - PullRequest
1 голос
/ 31 января 2020

Я пытаюсь добавить и удалить класс из нескольких элементов с некоторыми задержками, чтобы создать «мерцающую / мерцающую анимацию». Но я не могу обернуть голову вокруг хорошего метода для этого, так что как лучше настроить его, как я пытался?

У меня есть два отдельных массива. Значения относятся к атрибутам данных HTML элементов.

Пример массивов:

first = [1, 3, 5, 7];
second = [2, 4, 6, 8];

Пример HTML элемент:

<span class="item" data-item="2">Second Item</span>

Если условие встретился (или, скажем, по событию щелчка) Я хочу запустить следующую последовательность:

  • К каждому элементу массива «первый» следует добавить класс «активный».
  • Через 1 секунду класс «активный» должен быть удален из каждого «первого» элемента массива.
  • При этом к каждому элементу массива «секунда» должен быть добавлен класс «активный».
  • Через 1 секунду (или фактически всего 2 секунды)
    «активный» класс должен быть удален из «вторых» элементов массива,
    и снова добавлен в «первые» элементы массива.
    Затем через 1 секунду каждый отдельный элемент (первого и второго) получит класс «активный». Таким образом, каждый элемент теперь активен.

В данный момент я использую несколько вызовов setTimeout и .each, но я нахожу это грязным.

first = [1, 3, 5, 7];
second = [2, 4, 6, 8];

// directly set array "first" items to active
$.each(first, function(value) {
    $('.items').find('[data-item="' + value + '"]').addClass('active');
});

// after 1 second, remove class from "first" items, add class to "second" items
setTimeout(function() { 
    $.each(first, function(value) {
        $('.items').find('[data-item="' + value + '"]').removeClass('active');
    });
    $.each(second, function(value) {
        $('.items').find('[data-item="' + value + '"]').addClass('active');
    });
}, 1000);

// after 2 seconds, remove class from "second" items, add class to "first" items
setTimeout(function() { 
    $.each(second, function(value) {
        $('.items').find('[data-item="' + value + '"]').removeClass('active');
    });
    $.each(first, function(value) {
        $('.items').find('[data-item="' + value + '"]').addClass('active');
    });
}, 2000);

// after 3 seconds, add class to all items
setTimeout(function() { 
    $('.item').addClass('active');
}, 3000);

Ответы [ 2 ]

2 голосов
/ 31 января 2020

Это работает

ПРИМЕЧАНИЕ. Я использую .index () в первом и элемент данных во втором, чтобы получить четное / нечетное

let on = true;
let tId = setInterval(function() {
  $(".item").each(function() {
    const $this = $(this);
    const even = $(this).index()%2===0;
    $this.toggleClass("active", (!even && on) || (even && !on))
  });
  on=!on
},1000)  

setTimeout(function() { 
  $(".item").addClass("active")
  clearInterval(tId); 
},5000);
.active { color:red}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="item" data-item="1">Item 1</span>
<span class="item" data-item="2">Item 2</span>
<span class="item" data-item="3">Item 3</span>
<span class="item" data-item="4">Item 4</span>
<span class="item" data-item="5">Item 5</span>
<span class="item" data-item="6">Item 6</span>
<span class="item" data-item="7">Item 7</span>
<span class="item" data-item="8">Item 8</span>

Ваниль JS

let on = true;
let tId = setInterval(function() {
  [...document.querySelectorAll(".item")].forEach(item => {
    const even = item.getAttribute("data-item") % 2 === 0;
    item.classList.toggle("active", (!even && on) || (even && !on))
  });
  on = !on
}, 1000)

setTimeout(function() {
  [...document.querySelectorAll(".item")].forEach(item => item.classList.toggle("active", true));
  clearInterval(tId);
}, 5000);
.active {
  color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="item" data-item="1">Item 1</span>
<span class="item" data-item="2">Item 2</span>
<span class="item" data-item="3">Item 3</span>
<span class="item" data-item="4">Item 4</span>
<span class="item" data-item="5">Item 5</span>
<span class="item" data-item="6">Item 6</span>
<span class="item" data-item="7">Item 7</span>
<span class="item" data-item="8">Item 8</span>
1 голос
/ 31 января 2020

Взгляните на (ванильное) решение ниже!

const first = [1, 3, 5, 7];
const second = [2, 4, 6, 8];

//plain vanilla
function blinkAll() {
  //the function takes array as arguments, that need to be formatted like yours above
  Array.from(arguments).forEach((arr, idx) => {
    //use the index as a multiplier, to set the timer of a second from each other
    //check if the argument is actually an array
    if (Array.isArray(arr)) {
      //iterate over the array items
      arr.forEach(element => {
        //select item
        const item = document.querySelector(`span.item[data-item="${element}"`);
        setTimeout(() => blink(item, true, true), 1000 * idx);
      });
    }

  });

}

function blink(item, onoff, first) {
  //use classList and remove or add based upon onoff switch
  item.classList[(onoff ? 'add' : 'remove')]("active");

  //first time executing? Set up the timeouts to get desired result.
  if (first) {
    setTimeout(() => blink(item, false), 1000);
    setTimeout(() => blink(item, true, false), 2000);
  }
}

blinkAll(first, second);
.active {
  color: red;
}
<span class="item" data-item="1">First Item</span>
<span class="item" data-item="2">Second Item</span>
<span class="item" data-item="3">Third Item</span>
<span class="item" data-item="4">Fourth Item</span>
<span class="item" data-item="5">Fifth Item</span>
<span class="item" data-item="6">Sixth Item</span>
<span class="item" data-item="7">Seventh Item</span>
<span class="item" data-item="8">Eight Item</span>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...