網站搜尋

javascript - 在階段中更改單詞,CSS 垂直動畫循環


我猜沒有比這個更好的解釋了:

我幾乎用純 CSS 完成了我想要的,但……

  • 我必須手動設定每個單詞的「位置」
  • 如果再加上一個詞,我就必須重新計算所有東西
  • 我無法設定每個單字的 1 秒時間,只能設定整個動畫的總時間
  • 有反應嗎?只有我重新計算所有東西時才會有

程式碼是一個具有 overflow: hidden 的 div,以及一個子元素具有 negative margin-top(以及動畫)。

現場示範:

body {
  font-size: 2em;
  font-family: sans-serif;
 }
 
 .animation {
    vertical-align: sub;
    height: 1em;
    overflow: hidden;
    display: inline-block;
    line-height: 2em;
 }
 
ul {
  animation: animation 10s infinite;
  padding: 0;
  margin-top: -0.55em;
  list-style: none;
}

@keyframes animation {
    0%        { margin-top: -0.55em }
    12.5%     { margin-top: -2.54em }
    25%       { margin-top: -4.55em }
    37.5%     { margin-top: -6.55em }
    50%       { margin-top: -8.5em }
    62.5%     { margin-top: -6.55em }
    75%       { margin-top: -4.55em }
    87.5%     { margin-top: -2.54em }
    100%      { margin-top: -0.55em }
}
 Lorem ipsum dolor sit
 
    <div class="animation">
      <ul>
        <li>golfish</li>
        <li>dog</li>
        <li>cat</li>
        <li>hamster</li>
        <li>fox</li>
      </ul>
    </div>
    
, consectetur adipiscing elit. 

所以...

我覺得我無法解決我的問題,因為它們是 CSS 的限制,所以……有可能用 jQuery 來達成嗎?

答案#1

這裡嘗試了一個 CSS 解決方案。不完全確定參考圖片的哪些部分是重要的,所以我盡量匹配它。然而,我確實需要在標記中複製列表,以便在滾動通過視窗時顏色能從 lightgray 變為 black。

另請注意,動畫幀和時機與列表中的項目數量緊密相關。如果預期項目數量會動態變化,可能需要一些 JavaScript 介入。

body {
  font-size: 2em;
  font-family: sans-serif;
  line-height: 1.2
}

.animation {
  display: inline-block;
  vertical-align: top;
  text-align: center;
  border: 1px solid;
  overflow: visible;
  white-space: nowrap;
  color: lightgray;
  position: relative;
}

.animation ul {
  list-style: none;
  padding: 0 .5ex;
  margin: 0;
  height: 1.2em;
}

.animation li {
  position: relative;
  animation: cycle-5-items 5s ease-in-out alternate infinite;
}

.animation ul.mask {
  color: black;
  overflow: hidden;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
}

@keyframes cycle-5-items {
  0%, 10% {
    transform: translateY(0%);
  }
  
  15%, 35% {
    transform: translateY(-100%);
  }
  
  40%, 60% {
    transform: translateY(-200%);
  }
  
  65%, 85% {
    transform: translateY(-300%);
  }
  
  90%, 100% {
    transform: translateY(-400%);
  }
}
Lorem ipsum dolor sit
 
    <div class="animation">
      <ul class="mask">
        <li>golfish</li>
        <li>dog</li>
        <li>cat</li>
        <li>hamster</li>
        <li>fox</li>
      </ul>
      <ul>
        <li>golfish</li>
        <li>dog</li>
        <li>cat</li>
        <li>hamster</li>
        <li>fox</li>
      </ul>
    </div>
    
, consectetur adipiscing elit.

答案#2

你不需要 jQuery。這裡有一個使用 CSS 過渡效果的簡單純 JavaScript 解決方案。

function createWordListAnimation(animNode, delay){
  // Fetch the DOM elements.
  var animWindow = animNode.querySelector(".animation-window");
  var ul = animWindow.querySelector("ul");
  var lis = ul.querySelectorAll("li");

  // Copy the animation's window to create the gray list.
  var grayList = animWindow.cloneNode(true);
  var grayUl = grayList.querySelector("ul");
  grayList.classList.remove("animation-window");
  grayList.classList.add("animation-gray-list");
  animNode.insertBefore(grayList, animWindow);

  // This function shows the li number `liNum`.                     
  function goTo(liNum){
    var li = lis[liNum];
    var liTop = li.getBoundingClientRect().top;
    var ulTop = ul.getBoundingClientRect().top;
    var liOffset = liTop - ulTop;
    ul.style.top = -liOffset + "px";
    grayUl.style.top = -liOffset + "px";
  }

  // Set up an interval that changes the current li every `delay` ms.
  var current = 0;
  // We need a boolean to know if the animation is going up or down.
  var ascending = true;
  // Create the interval.
  return setInterval(function(){
    ascending = ascending && current + 1 < lis.length || current === 0;
    current = ascending ? current + 1: current - 1;
    goTo(current);
  }, delay);
}

createWordListAnimation(document.querySelector(".animation"), 1000 /* (ms) */);
body {
  font-size: 2em;
  font-family: sans-serif;
}

.animation {
  vertical-align: sub;
  display: inline-block;
  margin-top: -.1em;
  margin-bottom: -.1em;
  border-style: solid;
  border-color: lightgray;
  border-width: 1px;
  height: 1.2em;
}

.animation-window {
  position: relative;
  height: 100%;
  overflow: hidden;
  background-color: white;
}

.animation-gray-list {
  position: absolute;
  color: lightgray;
}

.animation ul {
  position: relative;
  list-style: none;
  top: 0;
  padding: 0;
  margin: 0;
  transition: top 300ms;
}

.animation li {
  margin: 0 .2em;
  text-align: center;
}
Lorem ipsum dolor sit
 
    <div class="animation">
      <div class="animation-window">
        <ul>
          <li>golfish</li>
          <li>dog</li>
          <li>cat</li>
          <li>hamster</li>
          <li>fox</li>
        </ul>
      </div>
    </div>,

consectetur adipiscing elit.

這個解決方案的缺點是窗口不能是透明的(它必須隱藏灰色列表)。仍然可以使它透明,但你將不得不創建兩個灰色列表——一個在上方,一個在下方——這開始變得有點複雜。