最近学习了 HTML5 中的重头戏--canvas。利用 canvas,前端人员可以很轻松地、进行图像处理。其 API 繁多,这次主要学习常用的 API,并且完成以下两个代码:

  1. 实现去色滤镜
  2. 实现负色(反色)滤镜

欢迎入群:857989948 。IT 技术深度交流和分享,涉及方面包括但不限于:网站制作、运营、UI 设计、算法分析、大数据、人工智能等。本群主打有深度、有态度的技术交流,欢迎热衷记录知识的您的加入。

1 了解 canvas?

1.1 什么是 canvas?

这个 HTML 元素是为了客户端矢量图形而设计的。它自己没有行为,但却把一个绘图 API 展现给客户端 JavaScript 以使脚本能够把想绘制的东西都绘制到一块画布上。

1.2 canvas 和 svg、vml 的区别?

<canvas> 标记和 SVG 以及 VML 之间的一个重要的不同是,<canvas> 有一个基于 JavaScript 的绘图 API,而 SVG 和 VML 使用一个 XML 文档来描述绘图。

2 canvas 绘图学习

大多数 Canvas 绘图 API 都没有定义在 <canvas> 元素本身上,而是定义在通过画布的getContext()方法获得的一个“绘图环境”对象上。而<canvas>元素本身默认的宽高分别是 300px、150px。

2.1 canvas 绘制矩形

// 处理canvas元素
var c = document.querySelector("#my-canvas");
c.width = 150;
c.height = 70; // 获取 指定canvas标签 上的context对象
var ctx = c.getContext("2d");
ctx.fillStyle = "#FF0000"; // 颜色
ctx.fillRect(0, 0, 150, 75); // 形状

2.2 canvas 绘制路径

var c = document.querySelector("#my-canvas");
var ctx = c.getContext("2d");
ctx.moveTo(0, 0); // 开始坐标
ctx.lineTo(200, 100); // 结束坐标
ctx.stroke(); // 立即绘制

2.3 canvas 绘制圆形

对于ctx.arc()这个接口,5 个参数是:(x,y,r,start,stop)。其中,x 和 y 是圆心坐标,r 是半径。

startstop的单位是弧度制。不是长度,也不是 °。

var c = document.querySelector("#my-canvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(95, 50, 40, 0, 2 * Math.PI);
ctx.stroke();

2.4 canvas 绘制文字

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.font = "30px Arial";
ctx.fillText("Hello World", 10, 50);

3 canvas 图像处理学习

3.1 常用 API 接口

关于图像处理的 API,主要有 4 个:

  • 绘制图像: drawImage(img,x,y,width,height)drawImage(img,sx,sy,swidth,sheight,x,y,width,height)
  • 获取图像数据: getImageData(x,y,width,height)
  • 重写图像数据: putImageData(imgData,x,y[,dirtyX,dirtyY,dirtyWidth,dirtyHeight])
  • 导出图像: toDataURL([type, encoderOptions])

更详细的 API 和参数说明请看:canvas 图像处理 API 参数讲解

3.2 绘制图像

在此些 API 的基础上,我们就可以在canvas元素中绘制我们的图片。假设我们图片是./img/photo.jpg

<script>
window.onload = function () {
var img = new Image() // 声明新的Image对象
img.src = "./img/photo.jpg"
// 图片加载后
img.onload = function () {
var canvas = document.querySelector("#my-canvas");
var ctx = canvas.getContext("2d"); // 根据image大小,指定canvas大小
canvas.width = img.width
canvas.height = img.height // 绘制图像
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
}
}
</script>

如下图所示,图片被画入了 canvas:

4 实现滤镜

这里我们主要借用getImageData函数,他返回每个像素的 RGBA 值。借助图像处理公式,操作像素进行相应的、数学运算即可。

什么是 RGBA?

更多滤镜实现

4.1 去色效果

去色效果相当于就是老旧相机拍出来的黑白照片。人们根据人眼的敏感程度,给出了如下公式:

gray = red * 0.3 + green * 0.59 + blue * 0.11

代码如下:

<script>
window.onload = function () {
var img = new Image()
img.src = "./img/photo.jpg"
img.onload = function () {
var canvas = document.querySelector("#my-canvas");
var ctx = canvas.getContext("2d");
canvas.width = img.width
canvas.height = img.height
ctx.drawImage(img, 0, 0, canvas.width, canvas.height) // 开始滤镜处理
var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
for (var i = 0; i < imgData.data.length / 4; ++i) {
var red = imgData.data[i * 4],
green = imgData.data[i * 4 + 1],
blue = imgData.data[i * 4 + 2];
var gray = 0.3 * red + 0.59 * green + 0.11 * blue; // 计算gray
// 刷新RGB,注意:
// imgData.data[i * 4 + 3]存放的是alpha,不需要改动
imgData.data[i * 4] = gray;
imgData.data[i * 4 + 1] = gray;
imgData.data[i * 4 + 2] = gray;
}
ctx.putImageData(imgData, 0, 0); // 重写图像数据
}
}
</script>

效果如下图所示:

4.2 负色效果

负色效果就是用最大值减去当前值。而 getImageData 获得的 RGB 中的数值理论最大值是:255。所以,公式如下:

new_val = 255 - val

代码如下:

<script>
window.onload = function () {
var img = new Image()
img.src = "./img/photo.jpg"
img.onload = function () {
var canvas = document.querySelector("#my-canvas");
var ctx = canvas.getContext("2d");
canvas.width = img.width
canvas.height = img.height
ctx.drawImage(img, 0, 0, canvas.width, canvas.height) // 开始滤镜处理
var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
for (var i = 0; i < imgData.data.length / 4; ++i) {
var red = imgData.data[i * 4],
green = imgData.data[i * 4 + 1],
blue = imgData.data[i * 4 + 2];
// 刷新RGB,注意:
// imgData.data[i * 4 + 3]存放的是alpha,不需要改动
imgData.data[i * 4] = 255 - imgData.data[i * 4];
imgData.data[i * 4 + 1] = 255 - imgData.data[i * 4 + 1];
imgData.data[i * 4 + 2] = 255 - imgData.data[i * 4 + 2];
}
ctx.putImageData(imgData, 0, 0); // 重写图像数据
}
}
</script>

效果图如下:

本篇文章来自董沅鑫的个人网站,引用、转载请指明出处

查看更多知识,或者技术交流:请访问godbmw.com

canvas学习和滤镜实现的更多相关文章

  1. canvas学习之API整理笔记(二)

    前面我整理过一篇文章canvas学习之API整理笔记(一),从这篇文章我们已经可以基本了解到常用绘图的API.简单的变换和动画.而本篇文章的主要内容包括高级动画.像素操作.性能优化等知识点,讲解每个知 ...

  2. canvas学习(一)

    Canvas 学习之路 (一) canvas 是H5 里面神一样的东西,使得只是通过html和js就能做出非常棒的游戏和画面. 因为对前端无限的爱好,更加对canvas充满好奇,将我学习canvas的 ...

  3. canvas学习和面向对象(二)

    Canvas 学习(二) 上一篇Canvas 学习(一)中我是用canvas绘制了一些基本和组合的图形. 现在开始绘制图片和动画帧,以及面向对象的升级版本. 还是一样,看代码,所有的代码都托管在git ...

  4. 纯JavaScript实现HTML5 Canvas六种特效滤镜

    纯JavaScript实现HTML5 Canvas六种特效滤镜  小试牛刀,实现了六款简单常见HTML5 Canvas特效滤镜,并且封装成一个纯 JavaScript可调用的API文件gloomyfi ...

  5. canvas学习总结六:绘制矩形

    在第三章中(canvas学习总结三:绘制路径-线段)我们提高Canvas绘图环境中有些属于立即绘制图形方法,有些绘图方法是基于路径的. 立即绘制图形方法仅有两个strokeRect(),fillRec ...

  6. canvas学习笔记、小函数整理

    http://bbs.csdn.net/topics/391493648 canvas实例分享 2016-3-16 http://bbs.csdn.net/topics/390582151 html5 ...

  7. canvas学习(三):文字渲染

    一.绘制基本的文字: var canvas = document.getElementById("myCanvas") var ctx = canvas.getContext('2 ...

  8. canvas学习(二):渐变与曲线的绘制

    canvas学习(二):渐变与曲线的绘制 一:createLinearGradient()线性渐变: 二:createLinearGradient() 放射状/圆形渐变: 三:createPatter ...

  9. canvas学习(一):线条,图像变换和状态保存

    canvas学习(一):线条,图像变换和状态保存 一:绘制一条线段: var canvas = document.getElementById('canvas') var ctx = canvas.g ...

随机推荐

  1. css3的动画效果

    全新的css3加入的动画效果: [ animation-name ]:检索或设置对象所应用的动画名称 [ animation-duration ]: 检索或设置对象动画的持续时间 [ animatio ...

  2. Rabbit RPC 代码阅读(一)

    前言 因为想对RPC内部的机制作一个了解,特作以下阅读代码日志,以备忘. RPC介绍 Rabbit RPC 原理可以用3点概括: 1.服务端启动并且向注册中心发送服务信息,注册中心收到后会定时监控服务 ...

  3. [UWP]不那么好用的ContentDialog

    ContentDialog是UWP开发中最常用的组件之一,一个体验良好的UWP应用很难避免不去使用它.博客园里也有许多的文章介绍如何来利用ContentDialog实现各种自定义样式的弹窗界面.不过实 ...

  4. 背水一战 Windows 10 (82) - 用户和账号: 获取用户的信息, 获取用户的同意

    [源码下载] 背水一战 Windows 10 (82) - 用户和账号: 获取用户的信息, 获取用户的同意 作者:webabcd 介绍背水一战 Windows 10 之 用户和账号 获取用户的信息 获 ...

  5. JVM活学活用——调优工具

    概述 工具做为图形化界面来展示更能直观的发现问题,另一方面一些耗费性能的分析(dump文件分析)一般也不会在生产直接分析,往往dump下来的文件达1G左右,人工分析效率较低,因此利用工具来分析jvm相 ...

  6. Codeforces gym102152 K.Subarrays OR

    传送:http://codeforces.com/gym/102152/problem/K 题意:给定$n(n\le10^5)$个数$a_i(a_i\le10^9)$,对于任一个子数组中的数进行或操作 ...

  7. Android 监听耳机的插拔事件

    一般采用的是动态监听的方式来实现的: package com.renhui.ej; import android.content.BroadcastReceiver; import android.c ...

  8. 前端自动化部署方案-实践(配合shell)

    以下实例项目为vue项目,其他项目当然也雷同咯 在项目中建一个这个么脚本文件 不说了,上代码 #!/bin/sh handle=$1; env=$2; # 远程部署机 webhook # 如果用远程机 ...

  9. [CocoaPods]客户端加载第三方库

    请先阅读另一篇博文铺垫知识基础:[CocoaPods]终端方式集成第三方库 客户端的Github地址:CocoaPods-app 点击下载客户端: [CocoaPods客户端] 安装下载的文件.软件界 ...

  10. 人生苦短之---认识Python

    认识 Python 人生苦短,我用 Python —— Life is short, you need Python 目标 Python 的起源 为什么要用 Python? Python 的特点 Py ...