Как я могу упростить этот код? JavaScript + css3

Я новичок в программировании и до сих пор разбираюсь в логике программирования. Я потратил несколько часов, пытаясь упростить этот код, но без сигары. Учитывая тот факт, что в основе программирования лежит упрощение задач, как мне сделать следующий код короче?

var card1 = document.getElementById('card1');
var card2 = document.getElementById('card2');
var card3 = document.getElementById('card3');
var card4 = document.getElementById('card4');

// card 1
card1.addEventListener('mouseenter', function(){
    card2.classList.add('blur');
    card3.classList.add('blur');
    card4.classList.add('blur');
})

card1.addEventListener('mouseleave', function(){
    card2.classList.remove('blur');
    card3.classList.remove('blur');
    card4.classList.remove('blur');
})

// card 2
card2.addEventListener('mouseenter', function(){
    card1.classList.add('blur');
    card3.classList.add('blur');
    card4.classList.add('blur');
})

card2.addEventListener('mouseleave', function(){
    card1.classList.remove('blur');
    card3.classList.remove('blur');
    card4.classList.remove('blur');
})

// card 3
card3.addEventListener('mouseenter', function(){
    card1.classList.add('blur');
    card2.classList.add('blur');
    card4.classList.add('blur');
})

card3.addEventListener('mouseleave', function(){
    card1.classList.remove('blur');
    card2.classList.remove('blur');
    card4.classList.remove('blur');
})

// card 4
card4.addEventListener('mouseenter', function(){
    card1.classList.add('blur');
    card2.classList.add('blur');
    card3.classList.add('blur');
})

card4.addEventListener('mouseleave', function(){
    card1.classList.remove('blur');
    card2.classList.remove('blur');
    card3.classList.remove('blur');
})

Заранее спасибо, Тиаго

РЕДАКТИРОВАТЬ: в конце концов я смог придумать что-то на основе ответа @CertainPerformance, которое соответствовало моим потребностям:

const cards = document.querySelectorAll('.modalidade__card');
const cardsArray = Array.apply(null, cards);
for (let i = 0; i < cardsArray.length; i++) {
    cardsArray[i].addEventListener('mouseenter', (e) => {
        for (let c = 0; c < cardsArray.length; c++) {
            cardsArray[c].classList.add('blur');
        };
        e.target.classList.remove('blur');
    });
    cardsArray[i].addEventListener('mouseleave', (e) => {
        for (let c = 0; c < cardsArray.length; c++) {
            if (cardsArray[c].classList.contains('blur')) {
                cardsArray[c].classList.remove('blur');
            };
        };
    });
};


person thiagopg84    schedule 10.04.2020    source источник
comment
первое улучшение, вы можете добавить свои объекты в коллекцию, а затем вы можете использовать лямбы для работы, например, var cards = [card1,card2,card3,card4]; , затем в своих функциях вы можете использовать cards.filter(currentCard => currentCard != card1 ).forEach(filteredCard => { filteredCard.classList.add('blur') } );   -  person Leo    schedule 10.04.2020


Ответы (4)


Вы можете использовать классы вместо идентификаторов, чтобы получить коллекцию всех карточек. Затем вы можете использовать делегирование событий для контейнера всех карточек. Когда одна из карт введена, переберите коллекцию и размойте остальные. Когда одна из карточек останется, переберите коллекцию и удалите размытие:

const cards = document.querySelectorAll('.card');
container.addEventListener('mouseover', (e) => {
  if (e.target.matches('.card')) {
    for (const card of cards) {
      card.classList.add('blur');
    }
    e.target.classList.remove('blur');
  }
});
container.addEventListener('mouseout', (e) => {
  if (e.target.matches('.card')) {
    for (const card of cards) {
      card.classList.remove('blur');
    }
  }
});

Обратите внимание, что для того, чтобы делегирование событий работало, вы должны использовать событие, которое всплывает — mouseover и mouseout всплывают, а mouseenter и mouseleave — нет. (Или вы можете перебрать каждую карту и добавить слушателя к каждой с помощью mouseenter и mouseleave)

person CertainPerformance    schedule 10.04.2020
comment
Спасибо за ответ! Вроде сработало. Если я наведу курсор на середину карты, это не сработает. Однако, если я наведу его рядом с его границами, он сработает. Карта имеет внутреннюю обивку. И область карты, которая запускает функцию, находится именно там, где находится отступ. Итак, я предполагаю, что e.target заменяется каким-то другим элементом в моем html-коде, когда я наводил курсор на среднюю область. Я мог бы добавить прозрачный элемент поверх карточек, чтобы он служил целью. Но ваше решение прекрасно. Меня больше интересовали пути решения этой проблемы. Спасибо за ваше понимание! - person thiagopg84; 10.04.2020
comment
Слушатель должен срабатывать, как только мышь входит в одну из карт — после того, как мышь прошла границу, не должно быть никаких изменений, пока мышь снова не выйдет за границу. - person CertainPerformance; 10.04.2020
comment
Да, я не знаю, почему это происходит. Я все еще пытаюсь понять это :( Еще раз спасибо! - person thiagopg84; 10.04.2020
comment
Я понял, что не так. Я добавил console.log(e.target) внутри функции, чтобы посмотреть, что к чему. Цель заменяется другими элементами внутри карточек, после чего срабатывает функция mouseout. Любые идеи? - person thiagopg84; 10.04.2020
comment
@ thiagopg84 thiagopg84 Если цель заменяется динамически, похоже, что в вопросе отсутствует какой-то код, который необходимо увидеть, чтобы причину можно было обнаружить. - person CertainPerformance; 10.04.2020

Вместо этого вы можете использовать псевдо-селектор css :hover. javascript.

.cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 0;
  pointer-events: none;
}

li {
    pointer-events: auto;
}
.cards:hover > * {
  filter: blur(5px);
  transition: filter .1s;
}

.cards > * {
  padding: 2rem;
  margin: 8px;
  background: bisque;
}

.cards > *:hover {
  filter: none;
}
<ul class="cards">
  <li>Card 1</li>
  <li>Card 2</li>
  <li>Card 3</li>
  <li>Card 4</li>  
</ul>

person ray hatfield    schedule 10.04.2020
comment
OP хочет что-то сделать с элементами, которые не зависают, в то время как один из других наводится, поэтому я не думаю, что :hover сработает - person CertainPerformance; 10.04.2020
comment
Ах. Верно. Я неправильно понял намерение. Но вы все равно можете сделать это с помощью :hover и родительского или родственного селектора. - person ray hatfield; 10.04.2020
comment
Однако вы не можете вернуться назад с помощью CSS. Например, хотя вы можете выполнить .card:hover ~ .card (применив правило к тем, кто следует за наведенной карточкой), вы не можете сделать .card ~ .card:hover и применить правило к тем, кто находится за наведенной карточкой. - person CertainPerformance; 10.04.2020
comment
Но у вас может быть контейнер, который применяет эффект ко всему, и более конкретный селектор для зависшего элемента. Я собираюсь переключиться на компьютер и привести пример. Я почти уверен, что это можно сделать чисто через css. - person ray hatfield; 10.04.2020
comment
@rayhatfield CertainPerformance прав, это невозможно сделать только с помощью CSS. Должен быть какой-то JavaScript, чтобы разрешить требуемые состояния, необходимые для логики. - person Patrick Roberts; 10.04.2020
comment
@rayhatfield хорошо... .cards:hover > * не совсем то же самое, что и при наведении курсора на одну из карточек. Вам не нужно наводить курсор на какую-либо из карточек, чтобы этот селектор активировался. - person Patrick Roberts; 10.04.2020
comment
@rayhatfield, вы можете довольно легко навести курсор на родителя на поле между каждой из карточек, не наводя курсор ни на одну из них. Это милый лайфхак, но, в конечном счете, полностью правильное решение ограничивает возможные макеты ваших карточек, в отличие от решения, использующего JavaScript. - person Patrick Roberts; 10.04.2020
comment
@PatrickRoberts Достаточно честно. В сообщении ОП недостаточно информации, чтобы определить, необходим ли javascript для решения его проблемы, и до тех пор, пока в этом нет особой необходимости, я бы склонен использовать чистый css. Если ОП хочет уточнить, я могу обновить или удалить свой ответ (что, вероятно, не понадобится, потому что ответ CertainPerformance является довольно надежное решение js). - person ray hatfield; 10.04.2020
comment
Извините, я не мог не отредактировать ваш фрагмент. Я добавил события указателя, чтобы решить проблему, указанную Париком Робертсом. Хороший ответ, ИМХО. - person vals; 10.04.2020
comment
Спасибо, @vals. Это пришло мне в голову, но было уже поздно, и я не хотел гнаться за этим дальше. - person ray hatfield; 10.04.2020

Например, мы можем

var card1 = document.getElementById('card1');
var card2 = document.getElementById('card2');
var card3 = document.getElementById('card3');
var card4 = document.getElementById('card4');

var mouseenter = function(){
    if(this != card1) card1.classList.add('blur');
    if(this != card2) card2.classList.add('blur');
    if(this != card3) card3.classList.add('blur');
    if(this != card4) card4.classList.add('blur');
};
var mouseleave = function(){
    if(this != card1) card1.classList.remove('blur');
    if(this != card2) card2.classList.remove('blur');
    if(this != card3) card3.classList.remove('blur');
    if(this != card4) card4.classList.remove('blur');
};

card1.addEventListener('mouseenter', mouseenter);
card1.addEventListener('mouseleave', mouseleave);
card2.addEventListener('mouseenter', mouseenter);
card2.addEventListener('mouseleave', mouseleave);
card3.addEventListener('mouseenter', mouseenter);
card3.addEventListener('mouseleave', mouseleave);
card4.addEventListener('mouseenter', mouseenter);
card4.addEventListener('mouseleave', mouseleave);
person Derek Lam    schedule 10.04.2020
comment
Конечно, это упрощает существующий код, но не устраняет ненужные повторения. Идеальное решение не должно было бы повторять одни и те же строки кода для каждой из четырех карт. - person Patrick Roberts; 10.04.2020
comment
Спасибо, Дерек! Это очень хорошее решение, и оно работает как шарм. - person thiagopg84; 10.04.2020

Попробуйте следующим образом

const card1 = document.getElementById("card1"),
  card2 = document.getElementById("card2"),
  card3 = document.getElementById("card3"),
  card4 = document.getElementById("card4");

// onMouse Effect
const onMouse = (ele, type = "enter") => {
  ele.forEach((item) =>
    type === "enter"
      ? item.classList.add("blur")
      : item.classList.remove("blur")
  );
};
// Card 1
card1.addEventListener("mouseenter", () => onMouse([card2, card3, card4]));
card1.addEventListener("mouseleave", () =>
  onMouse([card2, card3, card4], "leave")
);
// Card 2
card2.addEventListener("mouseenter", () => onMouse([card1, card3, card4]));
card2.addEventListener("mouseleave", () =>
  onMouse([card1, card3, card4], "leave")
);
// Card 3
card3.addEventListener("mouseenter", () => onMouse([card2, card1, card4]));
card3.addEventListener("mouseleave", () =>
  onMouse([card2, card1, card4], "leave")
);
// Card 4
card4.addEventListener("mouseenter", () => onMouse([card2, card3, card1]));
card4.addEventListener("mouseleave", () =>
  onMouse([card2, card3, card1], "leave")
);
.cursor-pointer {
  cursor: pointer;
}
h1 {
  font-size: 2em;
}
.blur h1 {
  font-size: 1em;
  text-align: center;
  color: transparent;
  text-shadow: #111 0 0 15px;
  transition: 0.4s;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
      integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
      crossorigin="anonymous"
    />
  </head>
  <body>
    <section class="container">
      <div class="p-5 m-5 text-center bg-primary cursor-pointer" id="card1">
        <h1>Card 1</h1>
      </div>
      <div class="p-5 m-5 text-center bg-primary cursor-pointer" id="card2">
        <h1>Card 2</h1>
      </div>
      <div class="p-5 m-5 text-center bg-primary cursor-pointer" id="card3">
        <h1>Card 3</h1>
      </div>
      <div class="p-5 m-5 text-center bg-primary cursor-pointer" id="card4">
        <h1>Card 4</h1>
      </div>
    </section>
  </body>
</html>

person MAHENDRA. A.R    schedule 10.04.2020