You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现类似Bornfight Studio的网页涂鸦自动擦除效果?

实现涂鸦自动擦除效果

要实现类似的涂鸦绘制后自动消失的效果,核心思路是记录每一笔绘制的图形数据,通过动画循环逐步淡化并移除旧的绘制内容。下面是基于你提供的代码修改后的完整实现:

修改后的完整代码

HTML

<canvas id="canvas"></canvas>

CSS(可选,优化canvas显示)

#canvas {
  background: #000;
  display: block;
  margin: 0 auto;
  cursor: crosshair;
}

JavaScript

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    painting = false,
    lastX = 0,
    lastY = 0,
    lineThickness = 1;

// 存储所有绘制的图形数据
const draws = [];
// 线条最大存活时间(毫秒,可调整)
const MAX_LIFETIME = 2000;

canvas.width = canvas.height = 600;
// 初始化画布背景
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, 600, 600);

canvas.onmousedown = function(e) {
    painting = true;
    lastX = e.pageX - this.offsetLeft;
    lastY = e.pageY - this.offsetTop;
};

canvas.onmouseup = function(e){
    painting = false;
}

canvas.onmousemove = function(e) {
    if (painting) {
        const mouseX = e.pageX - this.offsetLeft;
        const mouseY = e.pageY - this.offsetTop;

        // 保留原有的线条插值逻辑,确保绘制连贯
        var x1 = mouseX,
            x2 = lastX,
            y1 = mouseY,
            y2 = lastY;

        var steep = (Math.abs(y2 - y1) > Math.abs(x2 - x1));
        if (steep){
            var x = x1;
            x1 = y1;
            y1 = x;

            var y = y2;
            y2 = x2;
            x2 = y;
        }
        if (x1 > x2) {
            var x = x1;
            x1 = x2;
            x2 = x;

            var y = y1;
            y1 = y2;
            y2 = y;
        }

        var dx = x2 - x1,
            dy = Math.abs(y2 - y1),
            error = 0,
            de = dy / dx,
            yStep = -1,
            y = y1;
        
        if (y1 < y2) {
            yStep = 1;
        }
       
        lineThickness = 5 - Math.sqrt((x2 - x1) *(x2-x1) + (y2 - y1) * (y2-y1))/10;
        if(lineThickness < 1){
            lineThickness = 1;   
        }

        // 不再直接绘制,而是将图形数据存入数组
        for (var x = x1; x < x2; x++) {
            const drawX = steep ? y : x;
            const drawY = steep ? x : y;
            draws.push({
                x: drawX,
                y: drawY,
                size: lineThickness,
                timestamp: Date.now()
            });
            
            error += de;
            if (error >= 0.5) {
                y += yStep;
                error -= 1.0;
            }
        }

        lastX = mouseX;
        lastY = mouseY;
    }
}

// 动画循环,负责绘制和清理旧线条
function animate() {
    // 清除画布(重新绘制黑色背景)
    ctx.fillStyle = "#000";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    const now = Date.now();
    // 过滤存活线条并绘制,实现渐变消失
    draws.forEach(draw => {
        const age = now - draw.timestamp;
        if (age > MAX_LIFETIME) return;

        // 根据存活时间计算透明度,越旧越淡
        const alpha = 1 - (age / MAX_LIFETIME);
        ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`;
        ctx.fillRect(draw.x, draw.y, draw.size, draw.size);
    });

    // 清理已过期的线条数据,避免内存占用过高
    while (draws.length > 0 && (Date.now() - draws[0].timestamp) > MAX_LIFETIME) {
        draws.shift();
    }

    requestAnimationFrame(animate);
}

// 启动动画循环
animate();

关键改动说明

  1. 绘制数据存储:新增draws数组,记录每一个绘制矩形的位置、大小和时间戳,不再直接将图形画到画布上。
  2. 动画循环控制:通过requestAnimationFrame实现持续渲染,每次循环先清空画布,再根据时间戳筛选存活线条。
  3. 渐变消失效果:根据线条存活时间计算透明度,旧线条会逐渐变淡直至消失,调整MAX_LIFETIME数值可控制线条保留时长(数值越大,保留时间越长)。
  4. 内存优化:定期移除数组中已过期的线条数据,避免数组无限增长导致内存占用过高。

内容的提问来源于stack exchange,提问作者Neko Nin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:12:18