VueJS -подобные переходы, без Vue? - PullRequest
0 голосов
/ 09 апреля 2020

Как вы получаете VueJS -подобный контроль над переходами с использованием ванили JavaScript?

Цель состоит в том, чтобы элемент имел display: none;, когда он скрыт, но при этом сохранял способность затемнять его. /out.

Мне удалось заставить его исчезнуть, применив класс с непрозрачностью 0, а затем прослушивая событие transitionend, чтобы поменять класс с классом hide, который устанавливает display: none;. Эта часть на самом деле, кажется, работает хорошо ...

Однако, при попытке сделать обратное, она, похоже, не работает. Вместо того, чтобы переходить в; он полностью игнорирует переход и просто появляется с полной непрозрачностью и никогда не запускает событие transitionend.

const btnShow = document.querySelector('#btnShow');
const btnHide = document.querySelector('#btnHide');
const div = document.querySelector('div');

btnShow.addEventListener('click', () => {
  console.log('btnShow clicked');
  
  div.classList.remove('hide');
  div.classList.add('div-enter');
  div.classList.replace('div-enter', 'div-enter-to');

  div.addEventListener('transitionend', function() {
    console.log('show transition ended');
    div.classList.remove('div-enter-to');
  }, { once: true });
});

btnHide.addEventListener('click', () => {
  console.log('btnHide clicked');
  
  div.classList.add('div-leave');
  div.classList.replace('div-leave', 'div-leave-to');

  div.addEventListener('transitionend', () => {
    console.log('hide transition ended');
    div.classList.replace('div-leave-to', 'hide');
  }, { once: true });
});
.hide {
  display: none;
  opacity: 0;
}

.div-enter {
  opacity: 0;
}

.div-enter-to {
  opacity: 1;
}

.div-leave {
  opacity: 1;
}

.div-leave-to {
  opacity: 0;
}

/* Irrelevant styles */
html, body {
  height: 100vh;
  width: 100vw;
  margin: 0;
  padding: 1em 1.5em;
  font-size: 100%;
}

div {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  margin: 1em 0;
  padding: 3rem 0;
  width: 50%;
  background: #4bfa;
  border-radius: 5px;
  transition: all 1s linear;
}

button {
  border: none;
  border-radius: 2px;
}

button:hover {
  cursor: pointer;
}
<button id="btnShow">show</button>
<button id="btnHide">hide</button>

<div>
  fade out, then set display: none<br />
  then do the reverse...
</div>

Ответы [ 3 ]

0 голосов
/ 09 апреля 2020

Используйте анимацию вместо переходов, рабочий пример измененного кода приведен ниже.

const btnShow = document.querySelector('#btnShow');
const btnHide = document.querySelector('#btnHide');
const div = document.querySelector('div');

btnShow.addEventListener('click', () => {
  div.classList.remove('hide');
  div.classList.add('fade-in');

  div.addEventListener('animationend', function() {
    div.classList.remove('fade-in');
  }, { once: true });
});

btnHide.addEventListener('click', () => {
  console.log('btnHide clicked');
  
  div.classList.add('fade-out');

  div.addEventListener('animationend', () => {
    div.classList.replace('fade-out', 'hide');
  }, { once: true });
});
@keyframes fade-out {
   0% {opacity: 1;}
   100% {opacity: 0;} 
} 

@keyframes fade-in {
   100% {opacity: 1;}
   0% {opacity: 0;} 
}

.hide { display: none; }
.fade-out {animation-name: fade-out; animation-duration: 1s; }
.fade-in {animation-name: fade-in; animation-duration: 1s; }

/* Irrelevant styles */
html, body {
  height: 100vh;
  width: 100vw;
  margin: 0;
  padding: 1em 1.5em;
  font-size: 100%;
}

div {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  margin: 1em 0;
  padding: 3rem 0;
  width: 50%;
  background: #4bfa;
  border-radius: 5px;
  transition: all 1s linear;
}

button {
  border: none;
  border-radius: 2px;
}

button:hover {
  cursor: pointer;
}
<button id="btnShow">show</button>
<button id="btnHide">hide</button>

<div>
  fade out, then set display: none<br />
  then do the reverse...
</div>
0 голосов
/ 09 апреля 2020

Мне удалось заставить его работать, обернув анимацию ввода в setTimeout(() => {}, 0);

Я не до конца понимаю, почему это работает, поэтому я буду благодарен за комментарии, объясняющие это. Я пытался поместить их в requestAnimationFrame(), но это, похоже, не дало того же эффекта.

Если кто-нибудь знает лучший или более чистый способ достижения этого, я бы хотел увидеть его .

const btnShow = document.querySelector('#btnShow');
const btnHide = document.querySelector('#btnHide');
const div = document.querySelector('div');

btnShow.addEventListener('click', () => {
  console.log('btnShow clicked');
  
  div.classList.replace('hide', 'div-enter');

  setTimeout(() => {
    div.classList.replace('div-enter', 'div-enter-to');
    
    div.addEventListener('transitionend', function() {
      console.log('show transition ended');
      div.classList.remove('div-enter-to');
    }, { once: true });
  }, 0);
});

btnHide.addEventListener('click', () => {
  console.log('btnHide clicked');
  
  div.classList.add('div-leave');
  div.classList.replace('div-leave', 'div-leave-to');

  div.addEventListener('transitionend', () => {
    console.log('hide transition ended');
    div.classList.replace('div-leave-to', 'hide');
  }, { once: true });
});
.hide {
  display: none;
  opacity: 0;
}

.div-enter {
  opacity: 0;
}

.div-enter-to {
  opacity: 1;
}

.div-leave {
  opacity: 1;
}

.div-leave-to {
  opacity: 0;
}

/* Irrelevant styles */
html, body {
  height: 100vh;
  width: 100vw;
  margin: 0;
  padding: .5em 1em;
  font-size: 100%;
}

div {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  margin: 1em 0;
  padding: 2rem 0;
  width: 50%;
  background: #4bfa;
  border-radius: 5px;
  transition: all 1s linear;
}

button {
  border: none;
  border-radius: 2px;
}

button:hover {
  cursor: pointer;
}
<div>
  fade out, then set display: none<br />
  then do the reverse...
</div>

<button id="btnShow">show</button>
<button id="btnHide">hide</button>
0 голосов
/ 09 апреля 2020

Класс hide должен быть записан следующим образом:

.hide {
  visibility: hidden;
  opacity: 0;
}

CSS Переходы и анимации позволяют анимировать определенный c набор CSS свойств. Вы не можете анимировать свойство display.

Источник: https://www.w3.org/TR/css-transitions-1/#animatable -properties

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...