如何使用JavaScript实现div内文本淡入同步执行文本解扰动画效果
调整方案
核心修改点如下:
- 修复
TextScramble构造函数参数拼写错误(原代码参数是elm但赋值时写了el,会直接报错) - 淡入动画触发时机从「解扰完成后」改为「解扰启动瞬间」,保证两者同步执行
- 补全CSS中缺失的淡入关键帧定义
- 修正动画流程逻辑,支持按
phrases中的配置判断是否需要叠加淡入效果
修改后完整代码
JavaScript
// —————————————————————————————————————————————————— // TextScramble // —————————————————————————————————————————————————— class TextScramble { constructor(elm, numWords) { // 修复参数拼写错误 this.el = elm this.numWords = numWords; this.chars = '!<>-_\/[]{}—=+*^?#1234567890________' this.update = this.update.bind(this) } setText(newText, needFade = false) { const oldText = this.el.innerText const length = Math.max(oldText.length, newText.length) const promise = new Promise((resolve) => this.resolve = resolve) this.queue = [] // 计算解扰总时长,用来匹配淡入时长 let maxEndFrame = 0 for (let i = 0; i < length; i++) { const from = oldText[i] || '' const to = newText[i] || '' const start = Math.floor(Math.random() * 40) const end = start + Math.floor(Math.random() * 40) maxEndFrame = Math.max(maxEndFrame, end) this.queue.push({ from, to, start, end }) } cancelAnimationFrame(this.frameRequest) this.frame = 0 // 解扰启动时同步触发淡入 if (needFade) { this.el.animate([ { opacity: '0' }, { opacity: '1' } ], { // 按帧数换算时长,1帧约16.7ms,留少量冗余 duration: maxEndFrame * 17, iterations: 1, fill: 'forwards' }) } else { // 不需要淡入的直接设置不透明度为1 this.el.style.opacity = 1 } this.update() return promise } update() { let output = '' let complete = 0 for (let i = 0, n = this.queue.length; i < n; i++) { let { from, to, start, end, char } = this.queue[i] if (this.frame >= end) { complete++ output += to } else if (this.frame >= start) { if (!char || Math.random() < 0.28) { char = this.randomChar() this.queue[i].char = char } output += `<span class="dud">${char}</span>` } else { output += from } } this.el.innerHTML = output if (complete === this.queue.length) { this.resolve() } else { this.frameRequest = requestAnimationFrame(this.update) this.frame++ } } randomChar() { return this.chars[Math.floor(Math.random() * this.chars.length)] } } // —————————————————————————————————————————————————— // Example // —————————————————————————————————————————————————— const phrases = { 'Coding' : 'none', 'With' : 'none', 'Muhammad': 'none', 'Coding With Muhammad' : 'fade' } let phraseValues = Object.keys(phrases); const el = document.querySelector('.text') const fx = new TextScramble(el, phraseValues.length) let counter = 0 const next = () => { const currentPhrase = phraseValues[counter] const needFade = phrases[currentPhrase] === 'fade' fx.setText(currentPhrase, needFade).then(() => { counter = (counter + 1) % phraseValues.length setTimeout(next, 800) }) } next()
CSS
html, body { font-family: 'Roboto Mono', monospace; background: #212121; height: 100%; margin: 0; } .container { height: 100%; width: 100%; justify-content: center; align-items: center; display: flex; } .text { font-weight: 100; font-size: 28px; color: #FAFAFA; /* 初始不透明度设为0,避免首次加载闪一下 */ opacity: 0; } .dud { color: #757575; } /* 补全淡入关键帧,备用 */ @keyframes fade { from { opacity: 0; } to { opacity: 1; } } .fadeIn { animation: fade 10s forwards; }
HTML
<div class="container"> <div class="text"></div> </div>
如果需要所有文本切换都叠加淡入效果,直接把phrases里所有值都改成fade即可,淡入时长会自动和当前文本的解扰时长匹配,也可以手动修改duration的数值自定义速度。
内容的提问来源于stack exchange,提问作者Vahe
相关产品推荐
相关产品推荐

