Как я могу сделать этот переход плавным, а не подпрыгивать - PullRequest
0 голосов
/ 15 ноября 2018

Я пытаюсь внедрить систему уведомлений в моем приложении без использования библиотеки.Вот gif проблемы: https://imgur.com/oRc11dM

А вот jsfiddle of gif: https://jsfiddle.net/w9yk7n54/

Когда вы нажимаете на кнопку нового уведомления, уже отображаемые уведомления поднимаются вверх, чтобы сделатьместо для нового уведомления и новых уведомлений. Мне было интересно, как сделать так, чтобы все они плавно шли вверх.

Все уведомления не будут иметь одинаковые размеры, поэтому я не могу установить статические значения для высоты./etc.

Спасибо!

let btn = document.querySelector('button')
let container = document.querySelector('.notifications-container')

let notif_contents = [
  "<p>1</p><p>1</p><p>1</p><p>1</p>",
  "<p>test</p>",
  "<div><h1>testtesttest</h1><p>yoloalsdfasdf</p></div>"
]
let current = 0

btn.onclick = () => {

  let notif = document.createElement('div')
  notif.classList.add('notif')
  notif.innerHTML = notif_contents[current]
  notif.addEventListener('animationend', () => {
    notif.parentElement.removeChild(notif)
  })
  current++

  container.append(notif)
}
* {
  box-sizing: border-box;
}

.container {
  height: 300px;
  width: 400px;
  border: 1px solid black;
  position: absolute;
}

.notifications-container {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 200px;
  background: rgba( 0, 0, 0, 0.2);
  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-end;
  overflow: hidden;
}

.notif {
  position: relative;
  width: 100%;
  padding: 10px;
  border: 1px solid black;
  animation: notifAnim 5s forwards;
  transition: all .2s;
  background: white;
}

button {
  z-index: 100;
  background: lightcoral;
  color: white;
  border: none;
  padding: 10px;
  font-size: 20px;
  margin: 5px;
}

@keyframes notifAnim {
  0% {
    transform: translateY( 100%)
  }
  20% {
    transform: translateY( 0)
  }
  80% {
    transform: translateY( 0)
  }
  100% {
    transform: translateY( 100%)
  }
}
<div class="container">
  <button>New Notification</button>
  <div class="notifications-container"></div>
</div>

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Ваш контейнер уведомлений имеет justify-content: flex-end.Это означает, что всякий раз, когда вы добавляете новый, предыдущие будут увеличиваться с высотой нового.

"Исправить" - присвоить каждому элементу отрицательный margin-top, равный его высоте, и интегрировать в ваш текущий переход, получив margin-top обратно к 0.

Пример:

let btn = document.querySelector('button'),
  container = document.querySelector('.notifications-container'),
  notif_contents = [
  "<p>1</p><p>1</p><p>1</p><p>1</p>",
  "<p>test</p>",
  "<div><h1>testtesttest</h1><p>yoloalsdfasdf</p></div>",
  "<code>another.test()</code>",
  "<strong>another</strong> <i>test</i>"
]

btn.onclick = () => {
  let notif = document.createElement('div'),
    index = Math.floor(Math.random() * notif_contents.length)
  notif.classList.add('notif')
  notif.innerHTML = notif_contents[index]
  notif.addEventListener('animationend', () => {
    notif.parentElement.removeChild(notif)
  })

  container.append(notif)
  notif.style.marginTop = '-' + notif.offsetHeight + 'px'
}
* {
  box-sizing: border-box;
}

.container {
  height: 300px;
  width: 400px;
  border: 1px solid #888;
  position: absolute;
}

.notifications-container {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 200px;
  background: rgba( 0, 0, 0, 0.2);
  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-end;
  overflow: hidden;
}

.notif {
  position: relative;
  width: 100%;
  padding: 10px;
  border: 1px solid #ddd;
  border-bottom: none;
  animation: notifAnim 5s forwards;
  background: white;
}

button {
  z-index: 100;
  background: lightcoral;
  color: white;
  border: none;
  padding: 10px;
  font-size: 20px;
  margin: 5px;
}

@keyframes notifAnim {
  0%,
  100% {
    transform: translateY( 100%)
  }
  20%,
  80% {
    transform: translateY( 0);
    margin-top: 0
  }
}
<div class="container">
  <button>New Notification</button>
  <div class="notifications-container"></div>
</div>
0 голосов
/ 15 ноября 2018

Идея состоит в том, чтобы вставить новый элемент с высотой, равной 0, и вы анимируете высоту в дополнение к переводу.Конечно, вы должны использовать max-height, поскольку высота неизвестна, и мы не можем анимировать авто:

let btn = document.querySelector('button')
let container = document.querySelector('.notifications-container')

let notif_contents = [
  "<p>1</p><p>1</p><p>1</p><p>1</p>",
  "<p>test</p>",
  "<div><h1>testtesttest</h1><p>yoloalsdfasdf</p></div>"
]
let current = 0

btn.onclick = () => {

  let notif = document.createElement('div')
  notif.classList.add('notif')
  notif.innerHTML = notif_contents[current]
  notif.addEventListener('animationend', () => {
    notif.parentElement.removeChild(notif)
  })
  current++

  container.append(notif)
}
* {
  box-sizing: border-box;
}

.container {
  height: 300px;
  width: 400px;
  border: 1px solid black;
  position: absolute;
}

.notifications-container {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 200px;
  background: rgba( 0, 0, 0, 0.2);
  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-end;
  overflow: hidden;
}

.notif {
  position: relative;
  width: 100%;
  padding:0 10px;
  max-height:0px;
  border: 1px solid black;
  animation: notifAnim 5s forwards;
  transition: all .2s;
  background: white;
}

button {
  z-index: 100;
  background: lightcoral;
  color: white;
  border: none;
  padding: 10px;
  font-size: 20px;
  margin: 5px;
}

@keyframes notifAnim {
  0% {
    transform: translateY( 100%);
    max-height:0;
    padding:0 10px;
  }
  30% {
    transform: translateY( 0);
    max-height:300px;
    padding:10px;
  }
  80% {
    transform: translateY( 0);
    max-height:300px;
    padding:10px;
  }
  100% {
    transform: translateY( 100%);
    max-height:300px;
    padding:10px;
  }
}
<div class="container">
  <button>New Notification</button>
  <div class="notifications-container"></div>
</div>
...