ZetCode

JavaScript Canvas putImageData 教程

最后修改于 2025 年 4 月 3 日

在本文中,我们将探讨 JavaScript 中的 Canvas putImageData 方法。此方法对于 HTML canvas 上的直接像素操作至关重要。掌握 putImageData 对于图像处理和特效至关重要。

基本定义

putImageData 是一个 Canvas API 方法,用于将像素数据写入 canvas。它与包含像素颜色值的 ImageData 对象一起工作。这允许对 canvas 像素进行直接的底层操作。

该方法接受一个 ImageData 对象,并将其绘制到指定的坐标。它还可以选择性地接受一个脏矩形来仅复制部分图像数据。这对于性能优化非常强大。

putImageData 的基本用法

此示例演示了如何创建和绘制简单的 ImageData 对象。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Basic putImageData</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // Create blank ImageData
    const imageData = ctx.createImageData(100, 100);
    const data = imageData.data;
    
    // Fill with red pixels
    for (let i = 0; i < data.length; i += 4) {
        data[i] = 255;     // R
        data[i + 1] = 0;   // G
        data[i + 2] = 0;    // B
        data[i + 3] = 255;  // A
    }
    
    ctx.putImageData(imageData, 50, 50);
</script>

</body>
</html>

在这个基本示例中,我们创建了一个 100x100 像素的 ImageData 对象。然后,我们通过在 data 数组中设置 RGBA 值将其填充为纯红色像素。

putImageData 方法将此像素数据绘制在位置 (50,50)。这演示了在 canvas 上创建和绘制像素数据的最简单方法。

复制 Canvas 数据

此示例展示了如何复制 canvas 的一部分并对其进行操作。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Copy Canvas Data</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // Draw original content
    ctx.fillStyle = 'blue';
    ctx.fillRect(50, 50, 100, 100);
    
    // Get image data
    const imageData = ctx.getImageData(50, 50, 100, 100);
    const data = imageData.data;
    
    // Invert colors
    for (let i = 0; i < data.length; i += 4) {
        data[i] = 255 - data[i];     // R
        data[i + 1] = 255 - data[i + 1]; // G
        data[i + 2] = 255 - data[i + 2]; // B
    }
    
    // Draw modified data
    ctx.putImageData(imageData, 150, 50);
</script>

</body>
</html>

这里我们首先绘制一个蓝色矩形。然后我们使用 getImageData 复制其像素数据。我们通过反转颜色来修改数据。

修改后的数据使用 putImageData 绘制回 canvas 的新位置。这展示了如何处理现有的 canvas 内容。

部分图像更新

此示例演示了仅使用 putImageData 更新 canvas 的一部分。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Partial Update</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // Create full canvas image data
    const imageData = ctx.createImageData(canvas.width, canvas.height);
    const data = imageData.data;
    
    // Fill with gradient
    for (let y = 0; y < canvas.height; y++) {
        for (let x = 0; x < canvas.width; x++) {
            const i = (y * canvas.width + x) * 4;
            data[i] = x % 255;     // R
            data[i + 1] = y % 255;  // G
            data[i + 2] = 128;      // B
            data[i + 3] = 255;      // A
        }
    }
    
    // Draw only a portion (dirty rectangle)
    ctx.putImageData(imageData, 0, 0, 50, 50, 100, 100);
</script>

</body>
</html>

此示例创建了一个全 canvas 渐变,但仅绘制了 100x100 的部分。最后四个参数定义了脏矩形(源 x、y、宽度、高度)。

当您只需要更新 canvas 的一部分时,此技术对于性能很有用。绘制过程中会忽略其余像素数据。

图像处理滤镜

此示例展示了如何使用 putImageData 创建简单的灰度滤镜。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Grayscale Filter</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>
<img id="source" src="image.jpg" style="display:none">

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    const img = document.getElementById('source');
    
    img.onload = function() {
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const data = imageData.data;
        
        // Convert to grayscale
        for (let i = 0; i < data.length; i += 4) {
            const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
            data[i] = avg;     // R
            data[i + 1] = avg; // G
            data[i + 2] = avg; // B
        }
        
        ctx.putImageData(imageData, 0, 0);
    };
</script>

</body>
</html>

此示例加载图像,将其绘制到 canvas,然后将其转换为灰度。灰度转换会平均每个像素的 RGB 值。

处理后,我们使用 putImageData 将修改后的像素绘制回 canvas。这演示了 putImageData 的实际图像处理。

像素动画效果

此示例使用 putImageData 创建了像素动画效果。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Pixel Animation</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // Initial drawing
    ctx.fillStyle = 'blue';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    
    let offset = 0;
    
    function animate() {
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const data = imageData.data;
        
        // Shift pixels horizontally
        for (let y = 0; y < canvas.height; y++) {
            for (let x = 0; x < canvas.width; x++) {
                const i = (y * canvas.width + x) * 4;
                const ni = (y * canvas.width + ((x + offset) % canvas.width)) * 4;
                data[i] = imageData.data[ni];     // R
                data[i + 1] = imageData.data[ni + 1]; // G
                data[i + 2] = imageData.data[ni + 2]; // B
            }
        }
        
        ctx.putImageData(imageData, 0, 0);
        offset++;
        requestAnimationFrame(animate);
    }
    
    animate();
</script>

</body>
</html>

此示例创建了一个水平像素移动动画。每一帧,像素会向右移动一个位置,从而产生滚动效果。

动画循环使用 getImageDataputImageData 来不断更新 canvas。这表明 putImageData 可用于实时效果。

来源

MDN putImageData 文档

在本文中,我们探索了使用 putImageData 操作 canvas 像素的各种技术。掌握此方法对于 Web 应用程序中的高级图形和图像处理至关重要。

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直撰写编程文章。到目前为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出 所有 JS Canvas 教程