幻灯片隐藏和显示文字

时间:2020-09-11 14:57:15

标签: javascript html css

我想创建一个动画,其中active每隔X秒 班级将更改为span范围内的下一个profession-wrapperdeveloper span会以某种方式在active span顶部滑动 将显示新active span的字母,在隐藏每个字母的同时在其上方滑动 并且当它覆盖整个单词时,active类将进入下一个跨度。

我让developer span滑动了,active class得以按需工作, 但是developer span并不涵盖其滑动的active span, 并且由于每个跨度的文本长度都不同,所以滑动不会在单词的末尾结束,而是在固定的位置上完成,在|active span之间留出了很多空白

我如何获得一张幻灯片以覆盖幻灯片上的文字,并确保幻灯片在新的active单词的结尾处完成?

const firstProfession = document.querySelector('.profession-wrapper').firstElementChild;
let professionActive = document.querySelector('.active');

setInterval(() => {
  professionActive.classList.remove('active');
  professionActive.classList.add('inactive');
  if (professionActive.nextElementSibling) {
    professionActive = professionActive.nextElementSibling;
  } else {
    professionActive = firstProfession;
  }
  
  professionActive.classList.remove('inactive');
  professionActive.classList.add('active');
}, 6000);
.profession-header {
  display: flex;
  width: 100%;
  position: relative;
}

.profession-wrapper {
  position: relative;
  display: flex;
  padding-right: 7px;
}

.inactive {
  opacity: 0;
  position: absolute;
  overflow: hidden;
  display: inline-block;
}

.active {
  opacity: 1;
  display: inline-block;
  position: relative;
  overflow: hidden;
  width: max-content;
  padding-right: 5px;
}

.developer::before {
  content: '';
  border-left: 2px solid white;
  display: block;
  margin-right: 5px;
  height: 1.5rem;
  position: absolute;
  left: -7px;
}

.developer {
  position: absolute;
  animation: slide-text-in-out 6s ease-in-out infinite;
}

@keyframes slide-text-in-out {
  0% {
    left: 8px;
  }

  45%, 55% {
    left: 50%;
  }

  100% {
    left: 8px;
  }
}
<h5 class="profession-header">
  <span class="profession-wrapper">
    <span class="profession active">Web</span>
    <span class="profession inactive">Full Stack</span>
    <span class="profession inactive">Front End</span>
    <span class="profession inactive">Back End</span>
  </span>
  <span class="developer">Developer</span>
</h5>

1 个答案:

答案 0 :(得分:0)

更新版本

为响应以下OP的评论,以下是动画脚本/ css的更新版本,该动画在对.developer元素进行动画处理时尊重职业的宽度。

工作原理基本相同,但是使用CSS transitiontransform而不是animationleft来移动.developer div。

setupProfessionAnim(document.querySelector('.profession-header'));

function setupProfessionAnim(containerEl) {
  let professions = Array.from(containerEl.querySelectorAll('.profession')),
      sliding = containerEl.querySelector('.developer'),
      covered = true; // <-- state tracking variable

  sliding.addEventListener('transitionend', runNextAnimation); // <-- changed event
  runNextAnimation(); // <-- starts the first transition

  function runNextAnimation() {
    let active, next;
    
    covered = !covered; // <-- inverse the state
    if (covered) { // <-- are we in covering mode?
      sliding.style.transform = 'translateX(0)'; // <-- then cover
      return; // <-- and stop further processing
    }
    
    // otherwise

    active = getWithClass(professions, 'active');
    next = active.nextElementSibling ? active.nextElementSibling : professions[0];

    next.classList.add('active'); // <-- switch the .active class
    active.classList.remove('active'); // <-- here, too
    
    sliding.style.transform = 'translateX(' + getWidth(next) + 'px)'; // <-- and let the .developer div uncover
  }
}

function getWithClass(elList, className) {
  return elList.find
    ? elList.find(el => el.classList.contains(className))
    : elList.filter(el => el.classList.contains(className))[0];
}

function getWidth(el) {
  return el.getBoundingClientRect().width;
}
.profession-header {
  display: flex;
  width: 100%;
  position: relative;
}

.profession-wrapper {
  position: relative;
  display: flex;
  padding-right: 7px;
}

.profession {
  display: none;
  width: max-content;
  padding-right: 1ex;
}
.profession.active {
  display: block;
}

.developer {
  position: absolute;
  width: 160px; /* adjust if necessary */
  background-color: #fff; /* remove if you like, just for demonstation purposes */
  transform: translateX(0);
  transition: transform 2s ease-in-out 0s;
}
<h5 class="profession-header">
  <span class="profession-wrapper">
    <span class="profession active">Web</span>
    <span class="profession inactive">Full Stack</span>
    <span class="profession inactive">Front End</span>
    <span class="profession inactive">Back End</span>
  </span>
  <span class="developer">Developer</span>
</h5>

上一个版本

您应该避免在setInterval和CSS动画时间之间有一个隐含的要求。相反,请使用CSS动画触发的事件来切换类。这样可以确保动画的“时间轴”不会不同步(另一种查看方式是,它确保只有一个单个时间轴,而不是多个)。

下面是一个解决您的问题的有效示例。请注意我留下的评论!

setupProfessionAnim(document.querySelector('.profession-header'));

function setupProfessionAnim(containerEl) {
  let professions = Array.from(containerEl.querySelectorAll('.profession')), // get an array of all professions
      sliding = containerEl.querySelector('.developer'); // get the 'developer' element
  
  sliding.addEventListener('animationiteration', runNextAnimation); // re-execute runNextAnimation whenever an animation iteration finishes
  
  function runNextAnimation() {
    // this actually switches the classes from 'active' to 'inactive' and vice-versa
    let active = getWithClass(professions, 'active'), // get the current 'active' profession
      next = active.nextElementSibling ? active.nextElementSibling : professions[0]; // find next profession
      
    active.classList.replace('active', 'inactive'); // switch!
    next.classList.replace('inactive', 'active');   // here, too!
  }
}

function getWithClass(elList, className) {
  // convenience helper, uses Array.prototype.find if available and falls back to Array.prototype.filter
  return elList.find
    ? elList.find(el => el.classList.contains(className))
    : elList.filter(el => el.classList.contains(className))[0];
}
.profession-header {
  display: flex;
  width: 100%;
  position: relative;
}

.profession-wrapper {
  position: relative;
  display: flex;
  padding-right: 7px;
}

.inactive {
  opacity: 0;
  position: absolute;
  overflow: hidden;
  display: inline-block;
  animation: slide-text-out 2s ease-in-out;
}

.active {
  opacity: 1;
  display: inline-block;
  position: relative;
  overflow: hidden;
  width: max-content;
  padding-right: 5px;
  animation: slide-text-in 2s ease-in-out;
}

/* --- removed ---
.developer::before {
  content: '';
  border-left: 2px solid white;
  display: block;
  margin-right: 5px;
  height: 1.5rem;
  position: absolute;
  left: -7px;
}
--- removed --- */

.developer {
  position: absolute;
  /* --- new additions --- */
  width: 160px; /* adjust if necessary */
  border-left: 2px solid white;
  padding-left: 5px;
  background-color: #fff; /* remove if you like, just for demonstation purposes */
  /* --- end new additions --- */
  animation: slide-text-in-out 6s ease-in-out infinite;
}

@keyframes slide-text-in-out {
  0% {
    left: 0;
  }

  45%, 55% {
    left: 50%;
  }

  100% {
    left: 0;
  }
}
<h5 class="profession-header">
  <span class="profession-wrapper">
    <span class="profession active">Web</span>
    <span class="profession inactive">Full Stack</span>
    <span class="profession inactive">Front End</span>
    <span class="profession inactive">Back End</span>
  </span>
  <span class="developer">Developer</span>
</h5>