纯JavaScript实现HTML5 Canvas六种特效滤镜示例


Posted in Javascript onJune 28, 2013

小试牛刀,实现了六款简单常见HTML5 Canvas特效滤镜,并且封装成一个纯JavaScript可调用的API文件gloomyfishfilter.js。支持的特效滤镜分别为:
1.反色
2.灰色调
3.模糊
4.浮雕
5.雕刻
6.镜像

滤镜原理解释:
1.反色:获取一个像素点RGB值r, g, b则新的RGB值为(255-r, 255-g, 255-b)
2.灰色调:获取一个像素点RGB值r, g, b则新的RGB值为

newr = (r * 0.272) + (g * 0.534) + (b * 0.131); 
newg = (r * 0.349) + (g * 0.686) + (b * 0.168); 
newb = (r * 0.393) + (g * 0.769) + (b * 0.189);

3.模糊:基于一个5*5的卷积核
4.浮雕与雕刻:
基于当前像素的前一个像素RGB值与它的后一个像素的RGB值之差再加上128
5.镜像:模拟了物体在镜子中与之对应的效果。
杂项准备
1.如何获取Canvas 2d context对象
var canvas = document.getElementById("target"); 
canvas.width = source.clientWidth; 
canvas.height = source.clientHeight; 
if(!canvas.getContext) { 
console.log("Canvas not supported. Please install a HTML5compatible browser."); 
return; 
} 
// get 2D context of canvas and draw image 
tempContext = canvas.getContext("2d");

2.如何绘制一个DOM img对象到Canvas对象中
var source = document.getElementById("source"); 
tempContext.drawImage(source, 0, 0, canvas.width,canvas.height);

3.如何从Canvas对象中获取像素数据
var canvas = document.getElementById("target"); 
varlen = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
var binaryData = canvasData.data;

4.如何对DOM对象实现鼠标Click事件绑定
function bindButtonEvent(element, type, handler) 
{ 
if(element.addEventListener){ 
element.addEventListener(type, handler,false); 
}else { 
element.attachEvent('on'+type, handler);// for IE6,7,8 
} 
}

5.如何调用实现的gfilter API完成滤镜功能
<scriptsrc="gloomyfishfilter.js"></script> //导入API文件 
gfilter.colorInvertProcess(binaryData, len); //调用 API

6.浏览器支持:IE, FF, Chrome上测试通过,其中IE上支持通过以下标签实现:
<meta http-equiv="X-UA-Compatible"content="chrome=IE8">

效果演示:
纯JavaScript实现HTML5 Canvas六种特效滤镜示例 
应用程序源代码:
CSS部分:
#svgContainer { 
width:800px; 
height:600px; 
background-color:#EEEEEE; 
} 
#sourceDiv { float: left; border: 2px solid blue} 
#targetDiv { float: right;border: 2px solid red}

filter1.html中HTML源代码:
<!DOCTYPE html> 
<html> 
<head> 
<meta http-equiv="X-UA-Compatible" content="chrome=IE8"> 
<meta http-equiv="Content-type" content="text/html;charset=UTF-8"> 
<title>Canvas Filter Demo</title> 
<link href="default.css" rel="stylesheet" /> 
<script src="gloomyfishfilter.js"></scrip> 
</head> 
<body> 
<h1>HTML Canvas Image Process - By Gloomy Fish</h1> 
<div id="svgContainer"> 
<div id="sourceDiv"> 
<img id="source" src="../test.png" /> 
</div> 
<div id="targetDiv"> 
<canvas id="target"></canvas> 
</div> 
</div> 
<div id="btn-group"> 
<button type="button" id="invert-button">反色</button> 
<button type="button" id="adjust-button">灰色调</button> 
<button type="button" id="blur-button">模糊</button> 
<button type="button" id="relief-button">浮雕</button> 
<button type="button" id="diaoke-button">雕刻</button> 
<button type="button" id="mirror-button">镜像</button> 
</div> 
</body> 
</html>

filter1.html中JavaScript源代码:
var tempContext = null; // global variable 2d context 
window.onload = function() { 
var source = document.getElementById("source"); 
var canvas = document.getElementById("target"); 
canvas.width = source.clientWidth; 
canvas.height = source.clientHeight; if (!canvas.getContext) { 
console.log("Canvas not supported. Please install a HTML5 compatible browser."); 
return; 
} 
// get 2D context of canvas and draw image 
tempContext = canvas.getContext("2d"); 
tempContext.drawImage(source, 0, 0, canvas.width, canvas.height); 
// initialization actions 
var inButton = document.getElementById("invert-button"); 
var adButton = document.getElementById("adjust-button"); 
var blurButton = document.getElementById("blur-button"); 
var reButton = document.getElementById("relief-button"); 
var dkButton = document.getElementById("diaoke-button"); 
var mirrorButton = document.getElementById("mirror-button"); 
// bind mouse click event 
bindButtonEvent(inButton, "click", invertColor); 
bindButtonEvent(adButton, "click", adjustColor); 
bindButtonEvent(blurButton, "click", blurImage); 
bindButtonEvent(reButton, "click", fudiaoImage); 
bindButtonEvent(dkButton, "click", kediaoImage); 
bindButtonEvent(mirrorButton, "click", mirrorImage); 
} 
function bindButtonEvent(element, type, handler) 
{ 
if(element.addEventListener) { 
element.addEventListener(type, handler, false); 
} else { 
element.attachEvent('on'+type, handler); // for IE6,7,8 
} 
} 
function invertColor() { 
var canvas = document.getElementById("target"); 
var len = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
var binaryData = canvasData.data; 
// Processing all the pixels 
gfilter.colorInvertProcess(binaryData, len); 
// Copying back canvas data to canvas 
tempContext.putImageData(canvasData, 0, 0); 
} 
function adjustColor() { 
var canvas = document.getElementById("target"); 
var len = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
var binaryData = canvasData.data; 
// Processing all the pixels 
gfilter.colorAdjustProcess(binaryData, len); 
// Copying back canvas data to canvas 
tempContext.putImageData(canvasData, 0, 0); 
} 
function blurImage() 
{ 
var canvas = document.getElementById("target"); 
var len = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
// Processing all the pixels 
gfilter.blurProcess(tempContext, canvasData); 
// Copying back canvas data to canvas 
tempContext.putImageData(canvasData, 0, 0); 
} 
function fudiaoImage() 
{ 
var canvas = document.getElementById("target"); 
var len = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
// Processing all the pixels 
gfilter.reliefProcess(tempContext, canvasData); 
// Copying back canvas data to canvas 
tempContext.putImageData(canvasData, 0, 0); 
} 
function kediaoImage() 
{ 
var canvas = document.getElementById("target"); 
var len = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
// Processing all the pixels 
gfilter.diaokeProcess(tempContext, canvasData); 
// Copying back canvas data to canvas 
tempContext.putImageData(canvasData, 0, 0); 
} 
function mirrorImage() 
{ 
var canvas = document.getElementById("target"); 
var len = canvas.width * canvas.height * 4; 
var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height); 
// Processing all the pixels 
gfilter.mirrorProcess(tempContext, canvasData); 
// Copying back canvas data to canvas 
tempContext.putImageData(canvasData, 0, 0); 
}

滤镜源代码(gloomyfishfilter.js):
var gfilter = { 
type: "canvas", 
name: "filters", 
author: "zhigang", 
getInfo: function () { 
return this.author + ' ' + this.type + ' ' + this.name; 
}, 
/** 
* invert color value of pixel, new pixel = RGB(255-r, 255-g, 255 - b) 
* 
* @param binaryData - canvas's imagedata.data 
* @param l - length of data (width * height of image data) 
*/ 
colorInvertProcess: function(binaryData, l) { 
for (var i = 0; i < l; i += 4) { 
var r = binaryData[i]; 
var g = binaryData[i + 1]; 
var b = binaryData[i + 2]; binaryData[i] = 255-r; 
binaryData[i + 1] = 255-g; 
binaryData[i + 2] = 255-b; 
} 
}, 
/** 
* adjust color values and make it more darker and gray... 
* 
* @param binaryData 
* @param l 
*/ 
colorAdjustProcess: function(binaryData, l) { 
for (var i = 0; i < l; i += 4) { 
var r = binaryData[i]; 
var g = binaryData[i + 1]; 
var b = binaryData[i + 2]; 
binaryData[i] = (r * 0.272) + (g * 0.534) + (b * 0.131); 
binaryData[i + 1] = (r * 0.349) + (g * 0.686) + (b * 0.168); 
binaryData[i + 2] = (r * 0.393) + (g * 0.769) + (b * 0.189); 
} 
}, 
/** 
* deep clone image data of canvas 
* 
* @param context 
* @param src 
* @returns 
*/ 
copyImageData: function(context, src) 
{ 
var dst = context.createImageData(src.width, src.height); 
dst.data.set(src.data); 
return dst; 
}, 
/** 
* convolution - keneral size 5*5 - blur effect filter(模糊效果) 
* 
* @param context 
* @param canvasData 
*/ 
blurProcess: function(context, canvasData) { 
console.log("Canvas Filter - blur process"); 
var tempCanvasData = this.copyImageData(context, canvasData); 
var sumred = 0.0, sumgreen = 0.0, sumblue = 0.0; 
for ( var x = 0; x < tempCanvasData.width; x++) { 
for ( var y = 0; y < tempCanvasData.height; y++) { 
// Index of the pixel in the array 
var idx = (x + y * tempCanvasData.width) * 4; 
for(var subCol=-2; subCol<=2; subCol++) { 
var colOff = subCol + x; 
if(colOff <0 || colOff >= tempCanvasData.width) { 
colOff = 0; 
} 
for(var subRow=-2; subRow<=2; subRow++) { 
var rowOff = subRow + y; 
if(rowOff < 0 || rowOff >= tempCanvasData.height) { 
rowOff = 0; 
} 
var idx2 = (colOff + rowOff * tempCanvasData.width) * 4; 
var r = tempCanvasData.data[idx2 + 0]; 
var g = tempCanvasData.data[idx2 + 1]; 
var b = tempCanvasData.data[idx2 + 2]; 
sumred += r; 
sumgreen += g; 
sumblue += b; 
} 
} 
// calculate new RGB value 
var nr = (sumred / 25.0); 
var ng = (sumgreen / 25.0); 
var nb = (sumblue / 25.0); 
// clear previous for next pixel point 
sumred = 0.0; 
sumgreen = 0.0; 
sumblue = 0.0; 
// assign new pixel value 
canvasData.data[idx + 0] = nr; // Red channel 
canvasData.data[idx + 1] = ng; // Green channel 
canvasData.data[idx + 2] = nb; // Blue channel 
canvasData.data[idx + 3] = 255; // Alpha channel 
} 
} 
}, 
/** 
* after pixel value - before pixel value + 128 
* 浮雕效果 
*/ 
reliefProcess: function(context, canvasData) { 
console.log("Canvas Filter - relief process"); 
var tempCanvasData = this.copyImageData(context, canvasData); 
for ( var x = 1; x < tempCanvasData.width-1; x++) 
{ 
for ( var y = 1; y < tempCanvasData.height-1; y++) 
{ 
// Index of the pixel in the array 
var idx = (x + y * tempCanvasData.width) * 4; 
var bidx = ((x-1) + y * tempCanvasData.width) * 4; 
var aidx = ((x+1) + y * tempCanvasData.width) * 4; 
// calculate new RGB value 
var nr = tempCanvasData.data[aidx + 0] - tempCanvasData.data[bidx + 0] + 128; 
var ng = tempCanvasData.data[aidx + 1] - tempCanvasData.data[bidx + 1] + 128; 
var nb = tempCanvasData.data[aidx + 2] - tempCanvasData.data[bidx + 2] + 128; 
nr = (nr < 0) ? 0 : ((nr >255) ? 255 : nr); 
ng = (ng < 0) ? 0 : ((ng >255) ? 255 : ng); 
nb = (nb < 0) ? 0 : ((nb >255) ? 255 : nb); 
// assign new pixel value 
canvasData.data[idx + 0] = nr; // Red channel 
canvasData.data[idx + 1] = ng; // Green channel 
canvasData.data[idx + 2] = nb; // Blue channel 
canvasData.data[idx + 3] = 255; // Alpha channel 
} 
} 
}, 
/** 
* before pixel value - after pixel value + 128 
* 雕刻效果 
* 
* @param canvasData 
*/ 
diaokeProcess: function(context, canvasData) { 
console.log("Canvas Filter - process"); 
var tempCanvasData = this.copyImageData(context, canvasData); 
for ( var x = 1; x < tempCanvasData.width-1; x++) 
{ 
for ( var y = 1; y < tempCanvasData.height-1; y++) 
{ 
// Index of the pixel in the array 
var idx = (x + y * tempCanvasData.width) * 4; 
var bidx = ((x-1) + y * tempCanvasData.width) * 4; 
var aidx = ((x+1) + y * tempCanvasData.width) * 4; 
// calculate new RGB value 
var nr = tempCanvasData.data[bidx + 0] - tempCanvasData.data[aidx + 0] + 128; 
var ng = tempCanvasData.data[bidx + 1] - tempCanvasData.data[aidx + 1] + 128; 
var nb = tempCanvasData.data[bidx + 2] - tempCanvasData.data[aidx + 2] + 128; 
nr = (nr < 0) ? 0 : ((nr >255) ? 255 : nr); 
ng = (ng < 0) ? 0 : ((ng >255) ? 255 : ng); 
nb = (nb < 0) ? 0 : ((nb >255) ? 255 : nb); 
// assign new pixel value 
canvasData.data[idx + 0] = nr; // Red channel 
canvasData.data[idx + 1] = ng; // Green channel 
canvasData.data[idx + 2] = nb; // Blue channel 
canvasData.data[idx + 3] = 255; // Alpha channel 
} 
} 
}, 
/** 
* mirror reflect 
* 
* @param context 
* @param canvasData 
*/ 
mirrorProcess : function(context, canvasData) { 
console.log("Canvas Filter - process"); 
var tempCanvasData = this.copyImageData(context, canvasData); 
for ( var x = 0; x < tempCanvasData.width; x++) // column 
{ 
for ( var y = 0; y < tempCanvasData.height; y++) // row 
{ 
// Index of the pixel in the array 
var idx = (x + y * tempCanvasData.width) * 4; 
var midx = (((tempCanvasData.width -1) - x) + y * tempCanvasData.width) * 4; 
// assign new pixel value 
canvasData.data[midx + 0] = tempCanvasData.data[idx + 0]; // Red channel 
canvasData.data[midx + 1] = tempCanvasData.data[idx + 1]; ; // Green channel 
canvasData.data[midx + 2] = tempCanvasData.data[idx + 2]; ; // Blue channel 
canvasData.data[midx + 3] = 255; // Alpha channel 
} 
} 
}, 
};
Javascript 相关文章推荐
jsp js鼠标移动到指定区域显示选项卡离开时隐藏示例
Jun 14 Javascript
深入理解JavaScript系列(27):设计模式之建造者模式详解
Mar 03 Javascript
jQuery插件实现控制网页元素动态居中显示
Mar 24 Javascript
jquery代码实现简单的随机图片瀑布流效果
Apr 20 Javascript
实例讲解jquery中mouseleave和mouseout的区别
Feb 17 Javascript
js Canvas绘制圆形时钟教程
Feb 06 Javascript
简单谈谈js的数据类型
Sep 25 Javascript
vue项目中api接口管理总结
Apr 20 Javascript
Vuejs监听vuex中值的变化的方法示例
Dec 02 Javascript
详解如何在vue项目中使用layui框架及采坑
May 05 Javascript
微信小程序官方动态自定义底部tabBar的例子
Sep 04 Javascript
JS数组进阶示例【数组的几种函数用法】
Jan 16 Javascript
jquery中通过父级查找进行定位示例
Jun 28 #Javascript
javascript实现文字图片上下滚动的具体实例
Jun 28 #Javascript
JavaScript操纵窗口的方法小结
Jun 28 #Javascript
网站如何做到完全不需要jQuery也可以满足简单需求
Jun 27 #Javascript
js获取当前日期代码适用于网页头部
Jun 27 #Javascript
jquery仿QQ商城带左右按钮控制焦点图片切换滚动效果
Jun 27 #Javascript
JQUERY实现左侧TIPS滑进滑出效果示例
Jun 27 #Javascript
You might like
PHP 长文章分页函数 带使用方法,不会分割段落,翻页在底部
2009/10/22 PHP
php获取从html表单传递数组的方法
2015/03/20 PHP
php实现36进制与10进制转换功能示例
2017/01/10 PHP
基于laravel Request的所有方法详解
2019/09/29 PHP
JQuery从头学起第二讲
2010/07/04 Javascript
jQuery表格行换色的三种实现方法
2011/06/27 Javascript
关于图片的预加载过程中隐藏未知的
2012/12/19 Javascript
Javascript基础教程之定义和调用函数
2015/01/18 Javascript
Javascript中的高阶函数介绍
2015/03/15 Javascript
javascript入门教程基础篇
2015/11/16 Javascript
jquery网页日历显示控件calendar3.1使用详解
2016/11/24 Javascript
微信小程序侧边栏滑动特效(左右滑动)
2017/01/23 Javascript
react-router实现跳转传值的方法示例
2017/05/27 Javascript
Vue Spa切换页面时更改标题的实例代码
2017/07/15 Javascript
vue axios用法教程详解
2017/07/23 Javascript
深入理解Vue nextTick 机制
2018/04/28 Javascript
微信小程序swiper禁止用户手动滑动代码实例
2019/08/23 Javascript
Python语言编写电脑时间自动同步小工具
2013/03/08 Python
python 列表删除所有指定元素的方法
2018/04/19 Python
简单了解Django ContentType内置组件
2019/07/23 Python
在django-xadmin中APScheduler的启动初始化实例
2019/11/15 Python
python使用SQLAlchemy操作MySQL
2020/01/02 Python
Python3基本输入与输出操作实例分析
2020/02/14 Python
python报错: 'list' object has no attribute 'shape'的解决
2020/07/15 Python
HUGO BOSS美国官方网上商店:世界知名奢侈品牌
2017/08/04 全球购物
法国最大电子商务平台:Cdiscount
2018/03/13 全球购物
Coggles美国/加拿大:高级国际时装零售商
2018/10/23 全球购物
临床医学专业学生的自我评价分享
2013/11/21 职场文书
全国文明单位申报材料
2014/05/31 职场文书
幼儿发展评估方案
2014/06/11 职场文书
视光学专业自荐信
2014/06/24 职场文书
公司会议开幕词
2015/01/29 职场文书
教师辞职书范文
2015/02/26 职场文书
SQLServer2008提示评估期已过解决方案
2021/04/12 SQL Server
python 提取html文本的方法
2021/05/20 Python
vue中data里面的数据相互使用方式
2022/06/05 Vue.js