我想创建一个动画,其中active
每隔X秒
班级将更改为span
范围内的下一个profession-wrapper
,
developer 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>
答案 0 :(得分:0)
更新版本
为响应以下OP的评论,以下是动画脚本/ css的更新版本,该动画在对.developer
元素进行动画处理时尊重职业的宽度。
工作原理基本相同,但是使用CSS transition
和transform
而不是animation
和left
来移动.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>