跳转到内容

滤镜

刀刀
0字
0分钟
2026/8/16

Canvas 滤镜前置知识

Canvas getImageData

getImageDataCanvasRenderingContext2D 对象上的一个方法,用于获取指定矩形区域的像素数据。该方法返回一个 ImageData 对象,其中包含了矩形区域内每个像素的 RGBA 值。

以下是 getImageData 方法的基本语法:

js
const imageData = context.getImageData(x, y, width, height)

参数解释:

参数含义
x矩形区域的起始点 x 坐标。
y矩形区域的起始点 y 坐标。
width矩形区域的宽度。
height矩形区域的高度。

以下为示例:

js
const canvas = document.getElementById('myCanvas')
const ctx = canvas.getContext('2d')

// 获取画布上 (0, 0) 到 (100, 100) 的矩形区域的像素数据
const imageData = ctx.getImageData(0, 0, 100, 100)

// 访问像素数据
for (let i = 0; i < imageData.data.length; i += 4) {
  const red = imageData.data[i]
  const green = imageData.data[i + 1]
  const blue = imageData.data[i + 2]
  const alpha = imageData.data[i + 3]

  // 对获取的像素数据进行处理(例如修改颜色值)
  // ...
}

示例中,先获取 <canvas> 元素的上下文对象 ctx。然后,使用 getImageData 方法获取画布上指定区域的像素数据,并将结果保存到 imageData 对象中。通过访问 imageData.data,可以逐个像素地访问像素数组中的 RGBA 值。

注意

  1. getImageData 方法返回的 ImageData 对象是一个包含了具体像素数据的跨域对象。为了避免遇到跨域问题,画布和图像必须来自同一个域或通过 CORS(Cross-Origin Resource Sharing,跨域资源共享)进行设置。
  2. 由于 getImageData 返回的像素数据相当庞大,大量使用该方法可能会对性能产生影响。因此,在使用 getImageData 时,最好尽可能限制使用范围和像素数量,以免影响性能。

Canvas clearRect

clearRect 是一个用于在 HTML5<canvas> 元素上清除矩形区域的方法。它可以用来擦除画布上的内容,以便进行新的绘制。

clearRect 方法接受四个参数:xywidthheight。这些参数定义了要清除的矩形区域的位置和尺寸。其中,(x, y) 是矩形区域左上角的坐标,width 是矩形的宽度,height 是矩形的高度。

示例:清除矩形区域

js
const canvas = document.getElementById('myCanvas')
const ctx = canvas.getContext('2d')

// 绘制一个蓝色的矩形
ctx.fillStyle = 'blue'
ctx.fillRect(0, 0, 200, 200)

// 清除矩形的一部分
ctx.clearRect(50, 50, 100, 100)

该示例中,先通过 fillRect 方法绘制一个蓝色的矩形,然后使用 clearRect 方法清除了矩形区域的中间部分,留下四个蓝色的角落。

注意

clearRect 方法只适用于 <canvas> 元素,如果尝试在其他类型的元素上调用该方法,将会产生错误。

Canvas putImageData

putImageDataHTML5 <canvas> 元素的一个方法,用于将像素数据放回画布中。

该方法接受两个参数:imageDataxy。其中,imageData 是一个 ImageData 对象,它包含了要在画布上绘制的像素数据;xy 是绘制的起始位置。

示例:

js
const canvas = document.getElementById('myCanvas')
const ctx = canvas.getContext('2d')

// 创建一个 ImageData 对象
const imageData = ctx.createImageData(200, 200)

// 填充 imageData 对象的像素数据
const data = imageData.data
for (let i = 0; i < data.length; i += 4) {
  // 设置像素的红、绿、蓝、透明度通道的值
  data[i] = 255 // 红色通道
  data[i + 1] = 0 // 绿色通道
  data[i + 2] = 0 // 蓝色通道
  data[i + 3] = 255 // 不透明度通道
}

// 在指定位置绘制像素数据
ctx.putImageData(imageData, 50, 50)

上例中,先通过 ctx.createImageData() 创建了一个指定宽度和高度的 ImageData 对象。然后,通过访问 imageData.data 数组来设置每个像素的值。该示例将每个像素设置为纯红色。

最后,使用 putImageData 方法将像素数据绘制到画布上的指定位置。该示例将像素数据放置在画布上的位置 (50, 50) 处。

注意

像素数据必须与画布的大小相匹配,否则绘制将会产生不可预测的结果。

Canvas 获取图片

先获取用户选择上传的图片:

vue
<script setup>
import { ref } from 'vue'

const imgUrl = ref('')
const imgRef = ref(null)
const onChangeFn = (e) => {
  // 获取用户上传的文件
  const file = e.target.files[0]

  // 预览文件
  let fr = new FileReader()
  fr.readAsDataURL(file)

  // 获取图片读完的图片结果(非同步,需要在onload获取)
  fr.onload = () => {
    imgUrl.value = fr.result
  }
}

const addFn = () => {}
</script>

<template>
  <div ref="filterRef">
    <input type="file" @change="onChangeFn" />
    <img :src="imgUrl" ref="imgRef" />
    <button @click="addFn">点我添加滤镜</button>
  </div>
</template>

Canvas 滤镜实现

实现滤镜效果本质上是通过 getImageData() 方法获取到图片每一个像素点的 RGBA 值,通过修改其像素值实现滤镜。具体步骤如下:

  1. 将图片绘制到 Canvas
  2. 通过 getImageData() 方法获取到图片的像素数据,在其 data 属性是一个数组,能获取到该图片的像素值
  3. 通过循环遍历的方法,修改指定索引的像素值
  4. 通过 clearRect() 方法把画布图片清空
  5. 通过 putImageData() 方法把修改了像素点的图片添加进去
js
// ....
const filterRef = ref(null)
const addFn = () => {
  const filterCanvas = document.createElement('canvas')
  filterCanvas.height = imgRef.value.height
  filterCanvas.width = imgRef.value.width

  let ctx = filterCanvas.getContext('2d')
  filterRef.value.appendChild(filterCanvas)
  ctx.drawImage(imgRef.value, 0, 0, imgRef.value.width, imgRef.value.height)

  // 获取像素值
  let imageData = ctx.getImageData(
    0,
    0,
    imgRef.value.width,
    imgRef.value.height,
  )
  let _len = imageData.data.length
  for (let i = 0; i < _len; i++) {
    // 滤镜算法:将所有像素点的红色通道值设为0,其他通道值保持不变
    if (i % 4 === 0) {
      imageData.data[i] = 0
    }
  }

  // 清空 canvas
  ctx.clearRect(0, 0, imgRef.value.width, imgRef.value.height)

  // 重新绘制像素
  ctx.putImageData(imageData, 0, 0)
}

Canvas 总体效果

跳转预览:点击跳转

贡献者

The avatar of contributor named as v_duyilin v_duyilin
The avatar of contributor named as duyidao duyidao
The avatar of contributor named as 刀刀 刀刀

页面历史

刀刀博客累计访客 人;文档累计访问量共