分享一个有意思的文字飞入动画(模仿水滴融合)

先上效果图:
在这里插入图片描述
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        :root {
            --text-color: #f6f1e6;
            --drops-color: #231d1c;
        }

        body {
            background: var(--text-color);
            font-family: Georgia, serif;
        }

        .canvas {
            position: relative;
            height: 100vh;
            overflow: hidden;
        }
        .canvas--animated .puddle__letter {
            -webkit-animation-play-state: running;
            animation-play-state: running;
        }

        .puddle {
            position: absolute;
            display: flex;
            transform: rotate(var(--r, 0deg)) translate(calc(-50% - var(--x, 0)), calc(-50% - var(--y, 0)));
            top: 50%;
            left: 50%;
            color: var(--text-color);
            font-size: 6vmin;
            white-space: pre;
        }
        .puddle__letter {
            transform: translateY(800px);
            padding: 0.1em 0.2em;
            margin: -0.1em -0.2em;
            will-change: transform;
            -webkit-animation: drop 800ms var(--delay) ease-out forwards paused;
            animation: drop 800ms var(--delay) ease-out forwards paused;
        }

        .combined-puddles {
            position: relative;
            height: 100%;
            z-index: -1;
            filter: url(#drops-filter);
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
        }
        .combined-puddles .puddle__letter {
            border-radius: 50%;
            color: var(--drops-color);
            background-color: currentColor;
        }
        .combined-puddles .puddle__letter--t-1 {
            box-shadow: 0.0259077911em 0.0158195613em 0 0.156531918em currentColor;
        }
        .combined-puddles .puddle__letter--t-2 {
            box-shadow: 0.0027610231em 0.0292517118em 0 0.0017377822em currentColor;
        }
        .combined-puddles .puddle__letter--t-3 {
            box-shadow: 0.0014897121em 0.0208965418em 0 0.2029532073em currentColor;
        }
        .combined-puddles .puddle__letter--t-4 {
            box-shadow: 0.0181212165em 0.0001267036em 0 0.2696130855em currentColor;
        }
        .combined-puddles .puddle__letter--t-5 {
            box-shadow: 0.0299544544em 0.0155872295em 0 0.3927980665em currentColor;
        }
        .combined-puddles .puddle__letter--t-6 {
            box-shadow: 0.0223628085em 0.013623193em 0 0.3951977831em currentColor;
        }
        .combined-puddles .puddle__letter--t-7 {
            box-shadow: 0.017073126em 0.0166402911em 0 0.1251815461em currentColor;
        }
        .combined-puddles .puddle__letter--t-8 {
            box-shadow: 0.0160218528em 0.0103797109em 0 0.2355980051em currentColor;
        }
        .combined-puddles .puddle__letter--t-9 {
            box-shadow: 0.0061457537em 0.0272304962em 0 0.0502537243em currentColor;
        }
        .combined-puddles .puddle__letter--t-10 {
            box-shadow: 0.0010890892em 0.0108737853em 0 0.2990892848em currentColor;
        }

        @-webkit-keyframes drop {
            0% {
                transform: translate(0, 100vh);
            }
            80% {
                transform: translate(0, -5px);
            }
            100% {
                transform: translate(0, 0);
            }
        }

        @keyframes drop {
            0% {
                transform: translate(0, 100vh);
            }
            80% {
                transform: translate(0, -5px);
            }
            100% {
                transform: translate(0, 0);
            }
        }
    </style>
</head>
<body>
<div class="canvas">
    <div class="puddle" style="--x: 1.55em; --y: 3.73em">Roses are red</div>
    <div class="puddle" style="--x: 1.5em; --y: 1.8em">Violets are blue</div>
    <div class="puddle" style="--x: -1.5em; --y: -1.8em">Unexpected ";"</div>
    <div class="puddle" style="--x: -1.3em; --y: -3.7em">On line 32</div>
</div>
</body>
<script>
    class Droppy {
        DEFAULT_OPTIONS = {
            canvasSelector: ".canvas",
            textSelector: ".puddle",
            letterClassName: "puddle__letter",
            dropsClassName: "combined-puddles",
            delayBetweenDrops: 95,
            dropTypes: 10,
            wordAngleRange: [-3, 3]
        };

        constructor(opts) {
            this.opts = { ...this.DEFAULT_OPTIONS, ...opts };
            this.$textSelector = document.querySelectorAll(this.opts.textSelector);
            this.$canvas = document.querySelector(this.opts.canvasSelector);
            this.init();
        }

        init() {
            this.injectSVGFilter();
            this.wrapLetters();
            this.addDelayToEachLetter();
            this.createDrops();
            this.startAnimation();
        }

        getRandomInt = (min, max) => {
            return Math.floor(Math.random() * (max - min + 1)) + min;
        };

        startAnimation() {
            this.$canvas.classList.add("canvas--animated");
        }

        wrapLetters() {
            this.$textSelector.forEach(($word) => {
                const letters = Array.from($word.innerText).map((letter) => {
                    const dropType = this.getRandomInt(1, this.opts.dropTypes);
                    const className = `${this.opts.letterClassName} ${this.opts.letterClassName}--t-${dropType}`;
                    return `<div class="${className}">${letter}</div>`;
                });
                const angle = this.getRandomInt(
                    this.opts.wordAngleRange[0],
                    this.opts.wordAngleRange[1]
                );
                $word.style.cssText += `--r:${angle}deg`;
                $word.innerHTML = letters.join("");
            });
        }
        addDelayToEachLetter() {
            const letters = document.querySelectorAll(`.${this.opts.letterClassName}`);
            Array.from(letters, ($letter, index) => {
                const delay = index * this.opts.delayBetweenDrops;
                $letter.style.cssText += `--delay:${delay}ms`;
            });
        }

        createDrops() {
            const $drops = document.createElement("div");
            $drops.className = this.opts.dropsClassName;
            Array.from(this.$textSelector, ($word) =>
                $drops.appendChild($word.cloneNode(true))
            );
            this.$canvas.appendChild($drops);
        }

        injectSVGFilter() {
            const filter =
                '<svg style="display:none;"><filter id="drops-filter" x="-50%" width="200%" y="-50%" height="200%" color-interpolation-filters="sRGB"><feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" /><feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 21 -7" result="cm" /></filter></svg>';
            this.$canvas.insertAdjacentHTML("beforeend", filter);
        }
    }
    new Droppy();

</script>
</html>
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timi先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值