湛江市救护车出租网

如何利用JavaScript实现一个文字擦除效果

2026-03-25 13:58:04 浏览次数:0
详细信息

方法一:使用CSS遮罩渐变(推荐)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <style>
        .erase-container {
            position: relative;
            display: inline-block;
            font-size: 48px;
            font-weight: bold;
        }

        .erase-text {
            background: linear-gradient(to right, 
                #000 0%, 
                #000 50%, 
                transparent 50%, 
                transparent 100%);
            background-size: 200% 100%;
            background-position: 100% 0;
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
            transition: background-position 2s ease-in-out;
        }

        .erase-text.active {
            background-position: 0 0;
        }

        button {
            margin-top: 20px;
            padding: 10px 20px;
            font-size: 16px;
        }
    </style>
</head>
<body>
    <div class="erase-container">
        <div class="erase-text" id="eraseText">Hello World!</div>
    </div>
    <br>
    <button onclick="startErase()">开始擦除</button>
    <button onclick="resetErase()">重置</button>

    <script>
        function startErase() {
            const text = document.getElementById('eraseText');
            text.classList.add('active');
        }

        function resetErase() {
            const text = document.getElementById('eraseText');
            text.classList.remove('active');
        }

        // 自动开始
        setTimeout(startErase, 500);
    </script>
</body>
</html>

方法二:Canvas实现(更灵活)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <style>
        canvas {
            border: 1px solid #ddd;
        }

        .controls {
            margin-top: 20px;
        }

        button {
            padding: 10px 20px;
            font-size: 16px;
            margin-right: 10px;
        }

        input[type="range"] {
            width: 300px;
        }
    </style>
</head>
<body>
    <canvas id="eraseCanvas" width="600" height="150"></canvas>
    <div class="controls">
        <button onclick="startAnimation()">开始动画</button>
        <button onclick="resetCanvas()">重置</button>
        <button onclick="eraseRandom()">随机擦除</button>
        <br><br>
        <label>擦除进度: <span id="progress">0%</span></label>
        <input type="range" id="eraseSlider" min="0" max="100" value="0" oninput="manualErase(this.value)">
    </div>

    <script>
        const canvas = document.getElementById('eraseCanvas');
        const ctx = canvas.getContext('2d');
        const text = "Canvas文字擦除效果";
        let isAnimating = false;
        let animationId = null;

        // 初始化绘制文字
        function drawText() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.font = "bold 60px Arial";
            ctx.textAlign = "center";
            ctx.textBaseline = "middle";
            ctx.fillStyle = "#333";
            ctx.fillText(text, canvas.width / 2, canvas.height / 2);
        }

        // 擦除指定百分比
        function erase(percentage) {
            drawText();

            // 创建擦除区域
            const eraseWidth = (canvas.width * percentage) / 100;

            // 使用合成模式擦除
            ctx.globalCompositeOperation = 'destination-out';

            // 绘制擦除矩形(从左到右)
            ctx.fillRect(
                canvas.width / 2 - ctx.measureText(text).width / 2,
                canvas.height / 2 - 30,
                eraseWidth,
                60
            );

            // 恢复合成模式
            ctx.globalCompositeOperation = 'source-over';

            // 更新进度显示
            document.getElementById('progress').textContent = percentage + '%';
        }

        // 开始动画擦除
        function startAnimation() {
            if (isAnimating) return;

            isAnimating = true;
            let progress = 0;

            function animate() {
                if (progress >= 100) {
                    isAnimating = false;
                    cancelAnimationFrame(animationId);
                    return;
                }

                progress += 0.5;
                erase(progress);
                document.getElementById('eraseSlider').value = progress;
                animationId = requestAnimationFrame(animate);
            }

            animate();
        }

        // 手动控制擦除
        function manualErase(value) {
            if (isAnimating) {
                cancelAnimationFrame(animationId);
                isAnimating = false;
            }
            erase(value);
        }

        // 随机擦除效果
        function eraseRandom() {
            drawText();

            // 创建多个随机位置的擦除圆圈
            ctx.globalCompositeOperation = 'destination-out';

            for (let i = 0; i < 50; i++) {
                const x = Math.random() * canvas.width;
                const y = Math.random() * canvas.height;
                const radius = Math.random() * 20 + 5;

                ctx.beginPath();
                ctx.arc(x, y, radius, 0, Math.PI * 2);
                ctx.fill();
            }

            ctx.globalCompositeOperation = 'source-over';
        }

        // 重置画布
        function resetCanvas() {
            if (isAnimating) {
                cancelAnimationFrame(animationId);
                isAnimating = false;
            }
            document.getElementById('eraseSlider').value = 0;
            drawText();
            document.getElementById('progress').textContent = '0%';
        }

        // 初始化
        drawText();
    </script>
</body>
</html>

方法三:SVG实现(矢量,不失真)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <style>
        .svg-container {
            width: 600px;
            height: 150px;
            border: 1px solid #ddd;
        }

        .erase-btn {
            padding: 10px 20px;
            font-size: 16px;
            margin-top: 20px;
        }
    </style>
</head>
<body>
    <svg class="svg-container" id="eraseSvg">
        <defs>
            <!-- 创建遮罩 -->
            <mask id="textMask">
                <!-- 白色区域显示文字 -->
                <rect id="maskRect" x="0" y="0" width="100%" height="100%" fill="white"/>
                <!-- 黑色矩形用于擦除 -->
                <rect id="eraseRect" x="0" y="0" width="0" height="100%" fill="black">
                    <animate 
                        id="eraseAnim"
                        attributeName="width"
                        from="0%"
                        to="100%"
                        dur="2s"
                        fill="freeze"
                        begin="indefinite"
                    />
                </rect>
            </mask>
        </defs>

        <!-- 应用遮罩的文字 -->
        <text x="50%" y="50%" 
              text-anchor="middle" 
              dominant-baseline="middle"
              font-size="60"
              font-weight="bold"
              mask="url(#textMask)">
            SVG擦除效果
        </text>
    </svg>

    <br>
    <button class="erase-btn" onclick="startSVGErase()">开始擦除</button>
    <button class="erase-btn" onclick="reverseSVGErase()">反向擦除</button>
    <button class="erase-btn" onclick="resetSVGErase()">重置</button>

    <script>
        const eraseAnim = document.getElementById('eraseAnim');
        const eraseRect = document.getElementById('eraseRect');
        const maskRect = document.getElementById('maskRect');

        function startSVGErase() {
            // 设置从0%到100%的动画
            eraseAnim.setAttribute('from', '0%');
            eraseAnim.setAttribute('to', '100%');
            eraseAnim.beginElement();
        }

        function reverseSVGErase() {
            // 设置从100%到0%的动画(恢复)
            eraseAnim.setAttribute('from', '100%');
            eraseAnim.setAttribute('to', '0%');
            eraseAnim.beginElement();
        }

        function resetSVGErase() {
            // 立即重置到初始状态
            eraseRect.setAttribute('width', '0');
        }
    </script>
</body>
</html>

方法四:粒子效果擦除(最炫酷)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <style>
        .particle-container {
            position: relative;
            width: 600px;
            height: 150px;
            overflow: hidden;
        }

        .text {
            position: absolute;
            font-size: 60px;
            font-weight: bold;
            color: #333;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            z-index: 1;
        }

        .particles {
            position: absolute;
            width: 100%;
            height: 100%;
            z-index: 2;
        }

        .particle {
            position: absolute;
            background: white;
            border-radius: 50%;
            pointer-events: none;
        }

        button {
            padding: 10px 20px;
            font-size: 16px;
            margin-top: 20px;
        }
    </style>
</head>
<body>
    <div class="particle-container">
        <div class="text" id="particleText">粒子擦除效果</div>
        <div class="particles" id="particles"></div>
    </div>

    <br>
    <button onclick="startParticleErase()">开始粒子擦除</button>
    <button onclick="resetParticles()">重置</button>

    <script>
        const textElement = document.getElementById('particleText');
        const particlesContainer = document.getElementById('particles');
        let particles = [];

        function createParticles() {
            // 清除现有粒子
            resetParticles();

            const textRect = textElement.getBoundingClientRect();
            const containerRect = particlesContainer.getBoundingClientRect();

            // 创建网格粒子
            const particleSize = 6;
            const spacing = 4;

            for (let x = 0; x < textRect.width; x += spacing) {
                for (let y = 0; y < textRect.height; y += spacing) {
                    // 检查点是否在文字区域内
                    const canvas = document.createElement('canvas');
                    const ctx = canvas.getContext('2d');
                    canvas.width = 1;
                    canvas.height = 1;

                    // 临时绘制文字
                    ctx.font = getComputedStyle(textElement).font;
                    ctx.fillStyle = 'black';
                    ctx.textAlign = 'left';
                    ctx.textBaseline = 'top';
                    ctx.fillText(textElement.textContent, -x, -y);

                    // 检查像素是否不透明
                    const pixel = ctx.getImageData(0, 0, 1, 1).data;
                    if (pixel[3] > 128) { // 如果像素不透明
                        createParticle(
                            textRect.left - containerRect.left + x,
                            textRect.top - containerRect.top + y,
                            particleSize
                        );
                    }
                }
            }
        }

        function createParticle(x, y, size) {
            const particle = document.createElement('div');
            particle.className = 'particle';
            particle.style.width = size + 'px';
            particle.style.height = size + 'px';
            particle.style.left = x + 'px';
            particle.style.top = y + 'px';
            particle.style.opacity = '1';
            particle.style.boxShadow = '0 0 2px rgba(0,0,0,0.3)';

            particlesContainer.appendChild(particle);
            particles.push(particle);

            return particle;
        }

        function startParticleErase() {
            // 先创建粒子
            createParticles();

            // 为每个粒子添加动画
            particles.forEach((particle, index) => {
                // 随机延迟
                const delay = Math.random() * 1000;

                setTimeout(() => {
                    // 随机方向和距离
                    const angle = Math.random() * Math.PI * 2;
                    const distance = 50 + Math.random() * 100;
                    const duration = 1000 + Math.random() * 1000;

                    // 飞走动画
                    particle.style.transition = `all ${duration}ms ease-out`;
                    particle.style.transform = `translate(
                        ${Math.cos(angle) * distance}px,
                        ${Math.sin(angle) * distance}px
                    )`;
                    particle.style.opacity = '0';

                    // 动画结束后移除
                    setTimeout(() => {
                        if (particle.parentNode) {
                            particle.parentNode.removeChild(particle);
                        }
                    }, duration);
                }, delay);
            });

            // 文字淡出
            textElement.style.transition = 'opacity 1.5s ease-out';
            textElement.style.opacity = '0';
        }

        function resetParticles() {
            // 移除所有粒子
            particles.forEach(particle => {
                if (particle.parentNode) {
                    particle.parentNode.removeChild(particle);
                }
            });
            particles = [];

            // 重置文字
            textElement.style.opacity = '1';
            textElement.style.transition = 'none';
        }
    </script>
</body>
</html>

总结对比

方法 优点 缺点 适用场景
CSS渐变 简单、性能好、代码少 效果较简单 基础擦除效果
Canvas 灵活、可定制性强 代码较复杂 需要精确控制或特效
SVG 矢量不失真、动画流畅 兼容性稍差 需要高质量显示
粒子 视觉效果炫酷 性能开销大 特殊展示效果

建议:

可以根据具体需求选择合适的方法!

相关推荐