我如何才能使过渡平稳而不是跳跃

时间:2018-11-14 21:05:08

标签: javascript css animation css-animations

我试图在不使用库的情况下在我的应用程序中实现通知系统。这是问题的图像:https://imgur.com/oRc11dM

这是gif的jsfiddle:https://jsfiddle.net/w9yk7n54/

当您单击“新通知”按钮时,已经显示的通知会跳起来,为新通知和新通知幻灯片的放置留出空间。我想知道如何做到这一点,以便它们都可以顺利地向上组合。

通知的尺寸不会完全相同,因此我无法为height / 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 :(得分:1)

您的notif容器中有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>

答案 1 :(得分:0)

一个想法是插入一个新的高度等于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>