CSS+JS实现粘糊糊的文字变形效果

152 阅读1分钟

我正在参加「码上掘金挑战赛」详情请看:码上掘金挑战赛来了!

前言

CSS + JS实现黏糊糊的文字变形效果,使用码上掘金查看实时效果

逻辑

初始化逻辑

    const elts = {
      text1: document.getElementById("text1"),
      text2: document.getElementById("text2"),
    };

    // The strings to morph between. You can change these to anything you want!
    const texts = ["Why", "is", "this", "so", "satisfying", "to", "watch?"];

    // Controls the speed of morphing.
    const morphTime = 1;
    const cooldownTime = 0.25;

    let textIndex = texts.length - 1;
    let time = new Date();
    let morph = 0;
    let cooldown = cooldownTime;

    elts.text1.textContent = texts[textIndex % texts.length];
    elts.text2.textContent = texts[(textIndex + 1) % texts.length];

脚本初始化用elts保存了text1,text2对应的dom节点,

texts是要展示的文字变形数组,morphTime文件渐变的动画时间,cooldownTime文字动画冷却时间,设置text1显示的内容我WatchM?,text2的内容为Why

time记录初始化的时刻,morph记录渐变动画时间,cooldown保存动画冷却时间

animate

样式部分比较简单,主要讲解animate这个动画函数的效果

// Animation loop, which is called every frame.
function animate() {
	requestAnimationFrame(animate);
	
	let newTime = new Date();
	let shouldIncrementIndex = cooldown > 0;
	let dt = (newTime - time) / 1000;
	time = newTime;
	
	cooldown -= dt;
	
	if (cooldown <= 0) {
		if (shouldIncrementIndex) {
			textIndex++;
		}
		
		doMorph();
	} else {
		doCooldown();
	}
}

这是一个循环的动画,requestAnimationFrame这个api在每一帧渲染前都会执行一次

cooldown记录剩余的动画时间,每次执行animate和上一次的时间相减获得dtcooldown = cooldown - dt,冷却时间小于等于0就执行渐变动画

冷却函数doCooldown,text2透明度100%,text1透明度为0,重置morph,filter为空

    function doCooldown() {
      morph = 0;

      elts.text2.style.filter = "";
      elts.text2.style.opacity = "100%";

      elts.text1.style.filter = "";
      elts.text1.style.opacity = "0%";
    }

doMarph渐变动画前的判断,fraction为动画进行的百分比,当大于1说明渐变动画结束,回到动画冷却状态,fraction设置为1可以让渐变动画停止,我们可以看setMorch是根据fraction来设置filter的样式效果

    function doMorph() {
      morph -= cooldown;
      cooldown = 0;

      let fraction = morph / morphTime;

      if (fraction > 1) {
        cooldown = cooldownTime;
        fraction = 1;
      }

      setMorph(fraction);
    }
    
        // A lot of the magic happens here, this is what applies the blur filter to the text.
    function setMorph(fraction) {
      // fraction = Math.cos(fraction * Math.PI) / -2 + .5;

      elts.text2.style.filter = `blur(${Math.min(8 / fraction - 8, 100)}px)`;
      elts.text2.style.opacity = `${Math.pow(fraction, 0.4) * 100}%`;

      fraction = 1 - fraction;
      elts.text1.style.filter = `blur(${Math.min(8 / fraction - 8, 100)}px)`;
      elts.text1.style.opacity = `${Math.pow(fraction, 0.4) * 100}%`;

      elts.text1.textContent = texts[textIndex % texts.length];
      elts.text2.textContent = texts[(textIndex + 1) % texts.length];
    }

总结

JS的逻辑很简单,主要在于filter和opacity的动画效果的计算方法,这个可以不断调整直到看起来最舒服的动画效果