[前端] canvas进阶之常用滤镜

2024-05-05 09:48

本文主要是介绍[前端] canvas进阶之常用滤镜,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在操作之前先上一张初始预览图,页面的布局结果就是这样,然后就是对各种滤镜效果的转换

 

主要的实现原理是改变像素 rgb的值

 

接下来进入正题,进入代码操作

HTML布局:

 

<div style="overflow: hidden;"><canvas id="canvasa" width="455" height="248" style="display:block;float:left;border:1px solid #aaa;"></canvas><canvas id="canvasb" width="455" height="248" style="display:block;float:left;border:1px solid #aaa;"></canvas>
</div><div style=" margin-top:20px;font-size:20px;"><a href = "javascript:greyEffect()" >灰度</a><a href = "javascript:blackEffect()" >黑白</a><a href = "javascript:reverseEffect()" >反色</a><a href = "javascript:blurEffect()" >模糊</a><a href = "javascript:mosaicEffect()" >像素化</a>
</div>

 

 

 

JS脚本:

a、初始化

 

var canvasa = document.getElementById("canvasa");
var contexta = canvasa.getContext("2d");var canvasb = document.getElementById("canvasb");
var contextb = canvasb.getContext("2d");var image = new Image();window.onload = function(){image.src = "lol.jpg";image.onload = function(){contexta.drawImage( image , 0 , 0 , canvasa.width , canvasa.height );}
}

 

 

 

b、各种滤镜效果函数

1、灰度滤镜

 

function greyEffect(){var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );var pixelData = imageData.data;for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){var r = pixelData[i*4+0];var g = pixelData[i*4+1];var b = pixelData[i*4+2];var grey = r*0.3+g*0.59+b*0.11;pixelData[i*4+0] = grey;pixelData[i*4+1] = grey;pixelData[i*4+2] = grey;}contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height );
}

 

 

 

效果:

 

2、黑白滤镜

 

function blackEffect(){var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );var pixelData = imageData.data;for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){var r = pixelData[i*4+0];var g = pixelData[i*4+1];var b = pixelData[i*4+2];var grey = r*0.3+g*0.59+b*0.11;if(grey > 125){pv = 255;}else{pv = 0;}pixelData[i*4+0] = pv;pixelData[i*4+1] = pv;pixelData[i*4+2] = pv;}contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasa.width , canvasa.height );
}

 

 

 

效果:

 

3、反色滤镜

 

function reverseEffect(){var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );var pixelData = imageData.data;for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){var r = pixelData[i*4+0];var g = pixelData[i*4+1];var b = pixelData[i*4+2];pixelData[i*4+0] = 255 - r;pixelData[i*4+1] = 255 - g;pixelData[i*4+2] = 255 - b;}contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height );
}

 

 

 

效果:

 

4、模糊滤镜

 

function blurEffect(){var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );var tmpPixelData = tmpImageData.data;var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );var pixelData = imageData.data;var blurR = 3;var totalnum = (2*blurR + 1)*(2*blurR + 1);for( var i = blurR ; i < canvasb.height - blurR ; i ++ )for( var j = blurR ; j < canvasb.width - blurR ; j ++ ){var totalr = 0 , totalg = 0 , totalb = 0;for( var dx = -blurR ; dx <= blurR ; dx ++ )for( var dy = -blurR ; dy <= blurR ; dy ++ ){var x = i + dx;var y = j + dy;var p = x*canvasb.width + y;totalr += tmpPixelData[p*4+0];totalg += tmpPixelData[p*4+1];totalb += tmpPixelData[p*4+2];}var p = i*canvasb.width + j;pixelData[p*4+0] = totalr / totalnum;pixelData[p*4+1] = totalg / totalnum;pixelData[p*4+2] = totalb / totalnum;}contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height );
}

 

 

 

效果:

 

5、像素化滤镜

 

function mosaicEffect(){var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );var tmpPixelData = tmpImageData.data;var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height );var pixelData = imageData.data;var size = 16;var totalnum = size*size;for( var i = 0 ; i < canvasb.height ; i += size )for( var j = 0 ; j < canvasb.width ; j += size ){var totalr = 0 , totalg = 0 , totalb = 0;for( var dx = 0 ; dx < size ; dx ++ )for( var dy = 0 ; dy < size ; dy ++ ){var x = i + dx;var y = j + dy;var p = x*canvasb.width + y;totalr += tmpPixelData[p*4+0];totalg += tmpPixelData[p*4+1];totalb += tmpPixelData[p*4+2];}var p = i*canvasb.width+j;var resr = totalr / totalnum;var resg = totalg / totalnum;var resb = totalb / totalnum;for( var dx = 0 ; dx < size ; dx ++ )for( var dy = 0 ; dy < size ; dy ++ ){var x = i + dx;var y = j + dy;var p = x*canvasb.width + y;pixelData[p*4+0] = resr;pixelData[p*4+1] = resg;pixelData[p*4+2] = resb;}}contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width, canvasb.height );}

 

 

 

效果:

 

 

知识点:

1、putImageData(imgData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight) 方法参数详解

 

参数描述
imgData规定要放回画布的 ImageData 对象。
xImageData 对象左上角的 x 坐标,以像素计。
yImageData 对象左上角的 y 坐标,以像素计。
dirtyX可选。水平值(x),以像素计,在画布上放置图像的位置。
dirtyY可选。水平值(y),以像素计,在画布上放置图像的位置。
dirtyWidth可选。在画布上绘制图像所使用的宽度。
dirtyHeight可选。在画布上绘制图像所使用的高度。

 

图解:

 

 

2、与之对应的是getImageData(x, y, width, height)

 

参数描述
x开始复制的左上角位置的 x 坐标。
y开始复制的左上角位置的 y 坐标。
width将要复制的矩形区域的宽度。
height将要复制的矩形区域的高度。

 

改变色相(代码不全):

 

 

var rgb = $(this).css('background-color');  // 获取背景rgb颜色
var rgbArr = rgb.match(/\d+/g); // 转换成数组

 

 

 

 

/* 渲染表带颜色 @param rgbArr array (rgb颜色值)*/
this.renderColor = function(rgbArr) {var canvas = document.getElementById('watchBandCanvas');var ctx = canvas.getContext('2d');var img = new Image();img.src = $('.img-watch-band').attr('src');img.onload = function() {var width = img.width;var height = img.height;canvas.width = width;canvas.height = height;ctx.drawImage(img, 0, 0);var imgData = ctx.getImageData(0, 0, width, height);for( var i=0; i<imgData.data.length; i+=4){imgData.data[i+0] = rgbArr[0] - imgData.data[i+0];imgData.data[i+1] = rgbArr[1] - imgData.data[i+1];imgData.data[i+2] = rgbArr[2] - imgData.data[i+2];}ctx.putImageData(imgData, 0, 0, 0, 0, width, height);}
}

 

欢迎关注技术开发分享录:http://fenxianglu.cn/

 

这篇关于[前端] canvas进阶之常用滤镜的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/961409

相关文章

RedHat运维-Linux文本操作基础-AWK进阶

你不用整理,跟着敲一遍,有个印象,然后把它保存到本地,以后要用再去看,如果有了新东西,你自个再添加。这是我参考牛客上的shell编程专项题,只不过换成了问答的方式而已。不用背,就算是我自己亲自敲,我现在好多也记不住。 1. 输出nowcoder.txt文件第5行的内容 2. 输出nowcoder.txt文件第6行的内容 3. 输出nowcoder.txt文件第7行的内容 4. 输出nowcode

【Linux进阶】UNIX体系结构分解——操作系统,内核,shell

1.什么是操作系统? 从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境。我们通常将这种软件称为内核(kerel),因为它相对较小,而且位于环境的核心。  从广义上说,操作系统包括了内核和一些其他软件,这些软件使得计算机能够发挥作用,并使计算机具有自己的特生。这里所说的其他软件包括系统实用程序(system utility)、应用程序、shell以及公用函数库等

vue, 左右布局宽,可拖动改变

1:建立一个draggableMixin.js  混入的方式使用 2:代码如下draggableMixin.js  export default {data() {return {leftWidth: 330,isDragging: false,startX: 0,startWidth: 0,};},methods: {startDragging(e) {this.isDragging = tr

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录 前言Dropdown组件1. 功能分析2. 代码+详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲全局Dropdown组件封装,可根据UI设计师要求自定义修改。 Dropdown组件 1. 功能分析 (1)通过position属性,可以控制下拉选项的位置 (2)通过传入width属性, 可以自定义下拉选项的宽度 (3)通过传入classN

js+css二级导航

效果 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Con

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

vue+el国际化-东抄西鉴组合拳

vue-i18n 国际化参考 https://blog.csdn.net/zuorishu/article/details/81708585 说得比较详细。 另外做点补充,比如这里cn下的可以以项目模块加公共模块来细分。 import zhLocale from 'element-ui/lib/locale/lang/zh-CN' //引入element语言包const cn = {mess

以canvas方式绘制粒子背景效果,感觉还可以

这个是看到项目中别人写好的,感觉这种写法效果还可以,就存留记录下 就是这种的背景效果。如果想改背景颜色可以通过canvas.js文件中的fillStyle值改。 附上demo下载地址。 https://download.csdn.net/download/u012138137/11249872

vue同页面多路由懒加载-及可能存在问题的解决方式

先上图,再解释 图一是多路由页面,图二是路由文件。从图一可以看出每个router-view对应的name都不一样。从图二可以看出层路由对应的组件加载方式要跟图一中的name相对应,并且图二的路由层在跟图一对应的页面中要加上components层,多一个s结尾,里面的的方法名就是图一路由的name值,里面还可以照样用懒加载的方式。 页面上其他的路由在路由文件中也跟图二是一样的写法。 附送可能存在