前言

本文分享了canvas的文本操作,图片操作,像素操作,对图片实现类似ps功能操作,其它API。

文本操作

探索文本操作,只需简单记住如何操作文本的方法、属性的API。

方法:

方法 说明
fillText() 绘制“填充”文本
strokeText() 绘制“描边”文本
measureText() 用于获取文本的长度

属性:

属性 说明
font 定义文本字体样式
textAlign 定义文本水平对齐方式
textBaseline 定义文本垂直对齐方式
fillStyle 定义画笔“填充”路径的颜色
strokeStyle 定义画笔“描边”路径的颜色

参数示例说明:fillText(text, x, y, maxWidth)、strokeText(text, x, y, maxWidth)

  1. 参数 text 是一个字符串文本;
  2. 参数 x 表示文本的x轴坐标,即文本最左边的坐标;
  3. 参数 y 表示文本的y轴坐标,即文本最下边的坐标;
  4. 参数 maxWidth 可选,表示允许的最大文本的宽度(单位为 px),超出文本将被压缩。

注意:fillText 和 fillStyle 成对使用、strokeText 和 strokeStyle 成对使用。

文本操作示例

var cnv = document.getElementById('canvas');
var ctx = cnv.getContext("2d");var text = "好好学习,天天向上";
ctx.font = "bold 24px 微软雅黑";//获取文字长度必须在定义字体属性后
var length = ctx.measureText(text).width;// 定义画笔“描边”路径的颜色
ctx.strokeStyle = "red";// 绘制“描边”文本 ,文字水平居中
ctx.strokeText(text, (cnv.width - length)/2, 100);// 定义画笔“填充”路径的颜色
ctx.fillStyle="blue";//水平方向的对齐
ctx.textAlign = "center";
ctx.fillText(text, 120, 200);ctx.strokeStyle="green";// 文本垂直方向
ctx.textBaseline = "bottom";// 绘制“描边”文本
ctx.strokeText(text, 200, 350);复制代码

图片操作

绘制源图片

绘制图片时,我们必须保证图片已加载成功到本地。

源图绘制

API: cxt.drawImage(image, dx, dy)

var img = new Image();
img.src="../images/Tulips.jpg";
img1.onload = function() {ctx.drawImage(img, 10,10);
};
复制代码

缩放源图绘制

API: cxt.drawImage(image, dx, dy, dw, dh)

说明: dw、dy分别表示图片的宽度和高度

var img = new Image();
img.src="../images/Hydrangeas.jpg";
img.onload = function() {ctx.restore();ctx.drawImage(img, 133,10, 120, 200);
};
复制代码

截取源图绘制

API: cxt.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)

说明: sx, sy, sw, sh 表示源图像需要截取的范围

var img = new Image();
img.src="../images/Desert.jpg";
img.onload = function() {ctx.drawImage(img, 500, 400, 200, 200, 100, 100, 100, 100);
};
复制代码

平铺图片

在canvas中,当背景图需要显示为重复性的图片时,需调用 createPattern(image, type) 方法。
说明: 参数 image 表示被平铺的图片对象, 参数 type 表示图像平铺的方式。

参数type属性 说明
repeat 默认值,在水平方向和垂直方向同时平铺
repeat-x 只在水平方向平铺
repeat-y 只在垂直方向平铺
no-repeat 不平铺

示例:

//绘制圆,平铺
var bgCanvas = document.createElement('canvas');
bgCanvas.width = 20;
bgCanvas.height = 20;
var bgCtx = bgCanvas.getContext('2d');
bgCtx.beginPath();
bgCtx.arc(10,10, 10, 0, 360*Math.PI/180, false);
bgCtx.closePath();
bgCtx.fillStyle="red";
bgCtx.fill();ctx.restore();
ctx.beginPath();
var pattern = ctx.createPattern(bgCanvas, 'repeat');
ctx.fillStyle = pattern;
ctx.rect(300,300, 200, 200);
ctx.fill();
复制代码

解说:首先绘制一个圆形图案作为背景图片,然后调用 'createPattern'方法,将圆形图平铺方式显示,最后绘制一个矩形,填充属性值为平铺图案。
我们也可以绘制其它图案,甚至文字,填充属性值为平铺图案。

图片填充文字效果

var img = new Image();
img.src="../images/Hydrangeas.jpg";
img.onload = function() {ctx.restore();ctx.drawImage(img, 133,10, 120, 200);//利用图片给文字添加效果ctx.font="bold 50px 微软雅黑";ctx.fillStyle = ctx.createPattern(img, 'repeat');ctx.fillText('好好学习,天天向上', 200, 100);
};
复制代码

切割已绘制的图片

在canvas中,我们可以使用 clip() 方法切割canvas中已绘制的图片。
流程如下:

  1. 绘制基本图形;
  2. 使用 clip() 方法;
  3. 绘制图片;

示例:

//加载图片
var img = new Image();
img.src="../images/Tulips.jpg";
img.onload = function() {//首先绘制一个圆形,定制切割图片ctx.beginPath();ctx.arc(300, 300, 150 ,0, 360*Math.PI/180, false);ctx.closePath();ctx.stroke();//切割ctx.clip();ctx.drawImage(img, 10,10);
};
复制代码

效果:原本是一个矩形的图案,现在被切割显示为一个圆。
当然,除了圆形外,我们还可以切割成各种多边形图案。

像素操作

现在很多美颜神器,比如美图秀秀、手机摄像机美图功能,使用这些软件,可以做出各种效果,比如黑白效果、复古效果等。这一节,我们将探索在canvas上如何操作像素实现这些效果。这一节需要本地启动一个web服务,否则会有跨域限制。

获取图片像素

API: cxt.getImageData(x, y, width, height)
参数说明:x、y表示所选图片区域的坐标,width、height 表示所选图片区域的宽度和高度。

说明:该方法返回的是一个canvasPixelArray 对象,该对象有个data属性,这个属性保存了这张图片像素数据的数组,如[a1,a2,a3,a4,b1,b2,b3,b4,...]。每四个数字存储着一个像素的 rgba 颜色值,对应着这个像素的红(r)、绿(g)、蓝(b)、透明度(a)。该data属性的length值大小表示该图片的像素总量。

获取区域像素

API: cxt.createImageData(sw, sh)
API: cxt.createImageData(imageData)

参数说明: sw、sh 表示要创建区域的宽度和高度; imageData 表示一个像素对象,通过getImageData方法获得,本质其实是获取该像素对象的宽度和高度。

像素数据转化为图片

API: cxt.putImageData(image, x, y)

参数说明:image 表示需绘制的图形像素数据,即 getImageData 方法返回的对象;x、y表示需绘制图形左上角的坐标(x,y)。

以下效果针对整张图片处理。

特效探索

一般我们先用 getImageData() 方法获取像素数据,然后利用一定的算法进行像素操作,最后再使用 putImageData() 方法绘制像素数据。

首先我们在页面中加载一张图片:

let cnv = document.getElementById('canvas');
let ctx = cnv.getContext("2d");let img = new Image();
img.src="../images/Tulips.jpg";
img.onload = function() {ctx.drawImage(img, 0,0);
};
复制代码

颜色反转效果

实现算法:像素的红、绿、蓝通道取各自的相反值,即 255-原值

// 获取指定范围内的图片像素
let imgData = ctx.getImageData(0,0,500,500);
let data = imgData.data;
//遍历每个像素
for(let i=0; i< data.length; i += 4) {data[i+0] = 255 - data[i+0];data[i+1] = 255 - data[i+1];data[i+2] = 255 - data[i+2];
}
// 在指定位置绘制图形
ctx.putImageData(imgData, 0,0);
复制代码

说明:imgData.data,每四个数存储着一个像素的红(r)、绿(g)、蓝(b)、透明度(a)值,故循环需 i+=4,该算法无需处理透明度,也就是说不用处理 data[i+3]。这里我们取了整个图形像素,当然也可以取部分图形像素处理并绘制。

黑白效果
将图片处理成老照片,就可以使用该效果,效果是将彩色图片转换成黑白图片。
实现算法:取红、绿、蓝三个通道的加权平均值方式来实现,比如各自取权为0.3 、0.6、0.1,然后相加。

let imgData = ctx.getImageData(0,0,500,500);
let data = imgData.data;
// 遍历每个像素
for(let i=0; i< data.length; i+=4) {// 灰度值let grayscale = data[i+0] * 0.3 + data[i+1] * 0.6 + data[i+2] * 0.1; data[i+0] = grayscale;data[i+1] = grayscale;data[i+2] = grayscale;
}
ctx.putImageData(imgData, 0,0);
复制代码

说明:若要优化效果,可调整权值,我们还可以建立一个线性回归模型,通过机器学习训练来获取最佳权值。

改变亮度效果

实现算法:像素的红、绿、蓝通道值,分别同时加上一个正值或负值,取正值表示变亮,取负值表示变暗。

let imgData = ctx.getImageData(0,0,500,500);
let data = imgData.data;
// 亮度随机值
let a = [Math.floor(Math.random()*30), -Math.floor(Math.random()*30)][Math.floor(Math.random()*2)];
// 遍历每个像素
for(let i=0; i< data.length; i+=4) {data[i+0] += a;data[i+1] += a;data[i+2] += a;
}
ctx.putImageData(imgData, 0,0);
复制代码

复古效果
将图片变的古旧,可使用该效果。
实现算法: 分别取像素的红、绿、蓝通道值的指定加权平均值。

let imgData = ctx.getImageData(0,0,500,500);
let data = imgData.data;
for(let i=0; i< data.length; i+=4) {let r = data[i+0];let g = data[i+1];let b = data[i+2];data[i+0] = r* 0.39 +g* 0.76 + b*0.18;data[i+1] = r*0.35 +g* 0.68 + b*0.16;data[i+2] = r*0.27+g* 0.53 + b*0.13;
}
ctx.putImageData(imgData, 0,0);
复制代码

说明:为了达到最优效果,我们可以调整这些权值,我们也可以建模通过机器学习训练获取最优解。

透明效果

很明显,我们只要改变像素的透明度值,即可达到该效果。

let imgData = ctx.getImageData(0,0,500,500);
let data = imgData.data;
for(let i=0; i< data.length; i++) {data[i+3] *= 0.5;
}
ctx.putImageData(imgData, 0,0);
复制代码

阴影

canvas中,阴影分为图形阴影和文字阴影。

属性 说明
shadowOffsetX 阴影与图形的水平距离,默认0。大于0向右偏移,小于0时向左偏移。
shadowOffsetY 阴影与图形的垂直距离,默认0。大于0向下偏移,小于0时向上偏移。
shadowColor 阴影的颜色,默认黑色
shadowBlur 阴影的模糊值,默认0

文字阴影

ctx.beginPath();
// 阴影效果
ctx.font="bold 50px 微软雅黑";
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 5;
ctx.shadowColor = "LightSkyBlue";
ctx.shadowBlur = 10;
ctx.fillStyle = "HotPink";
ctx.fillText("好好学习,天天向上", 50,450);
ctx.restore();
复制代码

图片阴影

let img = new Image();
img.src="../images/Tulips.jpg";
img.onload = function() {ctx.shadowOffsetX = 5;ctx.shadowOffsetY = 5;ctx.shadowColor = "LightSkyBlue";ctx.shadowBlur = 10;ctx.fillRect(10,10, 100,100);ctx.drawImage(image, 10, 10);
};
复制代码

说明: 这里图片宽高和矩形宽高一致,矩形坐标和图形坐标保持一致,这是为了保证绘制出来的阴影大小跟图片大小一致。

其它canvas属性

透明度属性

ctx.globalAppha, 默认值为1.0(完全不透明),取值范围(0.0~1.0),必须在绘制图形前定义才有效,而且对整个画布都有起作用。

toDataURl()

获取canvas对象位图的字符串,通过这个方法,我们可以导出canvas图形到本地,参数为图片类型。

<canvas id="canvas" width=500 height=500 style="border: 1px dashed gray;"></canvas>
<a download="canvas" id="img" href="" ><button id="down">下载图片</button></a>
<script>let cnv = document.getElementById('canvas');document.getElementById('img').setAttribute('href',cnv.toDataURL('image/png'));
</script>
复制代码

globalCompositeOperation属性

正常情况下,canvas会按照图形绘制的顺序来依次显示每个图形,后面覆盖前面的。若要改变这个显示方式,我们可以设置globalCompositeOperation属性值来改变。

结束

本篇我们探索了文本操作、图片绘制、图形像素操作、阴影效果、以及canvas的其它属性,至此canvas API探索篇到此已全部结束。有兴趣的朋友可以尝试文中像素操作提到的利用机器学习获取最优权值。

@作者:白云飘飘(534591395@qq.com)

@github: github.com/534591395 欢迎关注我的微信公众号:

或者微信公众号搜索 新梦想兔,关注我哦。

转载于:https://juejin.im/post/5d5caf255188257573635d0a

canvas初探实践-第二篇相关推荐

  1. matlab实现鬼波信号压制算法  代码实践--第二篇 频率-波数域鬼波压制

    第二篇  matlab实现频率-波数域鬼波压制方法 本篇用来介绍频率-波数域鬼波压制的实现思路和压制效果 算法实现思路见2.3节,除了文中代码外,需配置鬼波压制算法工具包(https://downlo ...

  2. 有赞搜索引擎实践(算法篇)

    有赞搜索引擎实践(算法篇) 18 April 2016 1. 搜索算法总体架构 在上篇文章(工程篇)中, 我们介绍了有赞搜索引擎的基本框架. 搜索引擎主要3个部件构成. 第一, hadoop集群, 用 ...

  3. 第二篇|腾讯开源项目盘点:ncnn、xLua、libco等

    开源展示了人类共同协作,成果分享的魅力,每一次技术发展都是站在巨人的肩膀上,技术诸多创新和发展往往就是基于开源发展起来的,没有任何一家网络公司可以不使用开源技术,仅靠自身技术而发展起来. 腾讯开源了个 ...

  4. 【.NET Core 跨平台 GUI 开发】第二篇:Gtk# 布局入门,初识HBox 和 VBox

    这是 Gtk# 系列博文的第二篇.在上一篇博文<编写你的第一个 Gtk# 应用>中,我们提到"一个 Gtk.Window 只能直接包含一个部件".这意味着,在不做其他额 ...

  5. 中小型研发团队架构落地实践18篇,含案例、代码

    1 写在前面 中小型研发团队很多,而社区在中小型研发团队架构实践方面的探讨却很少.中小型研发团队特别是 50 至 200 人的研发团队,在早期的业务探索阶段,更多关注业务逻辑,快速迭代以验证商业模式, ...

  6. Python 打字小游戏开发,来体验不一样的打字游戏乐趣(第二篇)

    Python 打字小游戏开发,来体验不一样的打字游戏乐趣(第二篇) 代码实现 窗口类 小车类 玩家类 电脑类 赛道类 小树类 打字类 Python 打字小游戏开发,来体验不一样的打字游戏乐趣(第一篇) ...

  7. Python:Excel自动化实践入门篇 甲【留言点赞领图书门票】

    *以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s?__biz=MzUxMTgxMzExNQ==&mid=22 ...

  8. 第二篇:到底什么才是数据资产

    前言 "数据治理"简简单单四个字却涉及组织.制度.机制.技术.标准等非常多的内容,是一门复杂综合性学科,而且是很多数据类项目的基础性.前置性工作,很多项目或多或少都会涉及到数据治理 ...

  9. U3D_Shader编程(第二篇:基础夯实篇)

    <U3D_Shader编程> ##<U3D_Shader编程>发布说明: ++++Shader一个高大上的领域,不管怎么样,我来了. ++++立钻哥哥从2018年开始正式对Sh ...

最新文章

  1. SUSE10中Oracle10g存储中文数据
  2. [CERC2017]Buffalo Barricades
  3. 机器学习算法之决策树
  4. JavaSE--类加载器
  5. memcached client for java api,Memcached Client Forjava API
  6. 学python看书还是视频效率高_学习是看书还是看教学视频更有效率?
  7. 基于Kinect 2.0深度摄像头的三维重建 and Kinect Fusion
  8. 根据ReentrantLock -- 解析AQS原理
  9. 中国计算机学会(CCF)推荐国际学术会议和期刊目录(2019年版,官网转载)
  10. 问题求解RK3288调ALC5640芯片遇到的问题,前部分硬件问题,后部分如见驱动问题。
  11. brctl 设置ip_brctl命令
  12. GAN网络笔记 MATLAB实现
  13. python爬取网页数据总结_pycharm爬取网页数据
  14. 直播评论可以用html,网页制作HTML5实现直播间评论滚动效果的代码
  15. mtk6737t摄像头配置文件的编译
  16. 核心乐理---音程名称
  17. es 集群 number_of_shards、number_of_replicas
  18. MySQL详细安装步骤
  19. 小程序点击删除后刷新当前页面
  20. kubernetes v1.20项目之部署二进制安装_系统环境配置

热门文章

  1. shell运行java去哪加载jar包_shell脚本启动jar包-jar文件怎么打开
  2. 3489万!浪潮中标福州市行政(市民)服务中心综合信息化提升项目
  3. 寻找神秘4位数:在0-9十个数字中任意选择4个数字,如选2,9,8,4这四个数字,组成最大的数是9842,最小的数是2489,然后相减,再把得到的4位数组成的最大与最小值相减
  4. java 获取秒数_Java获取精确到秒的时间戳(转)
  5. “货运版滴滴”货拉拉又获巨额融资,同城货运市场生变?
  6. html5苹果怎么设置,苹果iphone5虚拟快捷键如何设置 iphone5“小太阳”设置方法图解...
  7. 金融学 经济学字母和基本公式
  8. php金字塔代码掏空中间,php练习——打印半金字塔、金字塔、空心金字塔、菱形、空心菱形...
  9. 1024祝青春少年!!!
  10. Photoshop2023常用快捷键和使用技巧(作为备忘)