博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
清除canvas画布内容--点擦除+线擦除
阅读量:7144 次
发布时间:2019-06-29

本文共 6454 字,大约阅读时间需要 21 分钟。

清空canvas画布内容

1、重置宽或高

由于canvas每当高度或宽度被重设时,画布内容就会被清空,因此可以用以下方法清空:(此方法仅限需要清除全部内容的情况)

var c=document.getElementById("myCanvas");  c.width=c.width;

 

2、clearRect

1 var c=document.getElementById("myCanvas");2 var ctx=c.getContext("2d");3 ctx.fillStyle="red";4 ctx.fillRect(0,0,300,150);5 ctx.clearRect(20,20,100,50);

3、globalCompositeOperation

引用globalCompositeOperation()函数,这个函数是用来在画布上组合颜色,我们可以利用这个原理,叠加(数学上的"或"原理)来制作橡皮。

首先看看 globalCompositeOperation属性可以设置的值有哪些,分别是什么效果:

描述
source-over 默认。在目标图像上显示源图像。
source-atop 在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
source-in 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
source-out 在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
destination-over 在源图像上方显示目标图像。
destination-atop 在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。
destination-in 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
destination-out 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
lighter 显示源图像 + 目标图像。
copy 显示源图像。忽略目标图像。
xor 使用异或操作对源图像与目标图像进行组合。
1  2  3  4 12 13 14 15 48 49 50 

可以看出如果设置成destination-out,就可以清除canvas现有的像素点的图像。


 

清除绘制到画布上的线条(点擦除,线擦除)

  在我最近实现的项目中有画笔功能, 同时画笔画出的线条可以被橡皮擦擦除,有点擦除和线擦除两种方式。

  使用以上两种方法也可以,但是如果这些线条不止绘制一次的话呢,中间有其他操作(例如绘制的内容变换一次后)那上面的方法就不容易做到了,因为要反复绘制存储每次擦除后的数据,简单的为了能达到该目的,可以将整个canvas画布转化成base64编码的image,后面再次绘制的时候把这个image数据再绘制到canvas上,可以继续在这个canvas上进行绘制和擦除内容。但是怎么样也不好做到线擦除的功能了!

  下面介绍另外一种存储绘制路径点坐标的方法去实现绘制线条后的点擦除和线擦除的功能。

  首先介绍下存储线条的数据结构,之前写的一篇《》大家可以先大致看看hash结构的实现,但是key和value快速查找的优势需要清楚。另外在canvas画的各种形状和线条,我们是如何知道点击到哪个元素哪条线?《》这篇博客里有说明实现原理。

1. 线条存储及绘制

项目中我存储的线条hash结构的对象如下:

展开第一个线条key值为“#8c471a”的具体信息如下,value值其中有colorKey,lineColor,lineWidth,以及最重要的List结构的points对象,是一个存储了该线条所有点坐标集合的List对象。

下面的一段代码,实现了绘制该线条到画布。使用二次贝塞尔函数使得绘制出来的线条流畅平滑没有折痕,当只有一个点时可绘制出一个圆点。

1                 var count = this.points.length(); 2                 var p: Core.Point = this.points.get(0); 3                 if (isDrawHit) { 4                     ctx.strokeStyle = this.colorKey; 5                 } 6                 else { 7                     ctx.strokeStyle = this.lineColor; 8                 } 9                 ctx.lineCap = "round";10                 ctx.lineJoin = 'round';//转折的时候不出现尖角11                 if (ctx.canvas.id == "hitCanvas")12                     ctx.lineWidth = this.lineWidth + eraserRadius;//扩大hit上线条的范围,橡皮半径13                 else14                     ctx.lineWidth = this.lineWidth;15                 ctx.beginPath();16                 if (count >= 2) {17                     ctx.moveTo(p.x, p.y);18                     for (var i = 1; i < count - 2; i++) {19                         // p = this.points.get(i);20                         // ctx.lineTo(p.x, p.y);21                         if (this.points.get(i).x == this.points.get(i + 1).x && this.points.get(i).y == this.points.get(i + 1).y)22                             continue;23                         var c = (this.points.get(i).x + this.points.get(i + 1).x) / 2;24                         var d = (this.points.get(i).y + this.points.get(i + 1).y) / 2;25                         ctx.quadraticCurveTo(this.points.get(i).x, this.points.get(i).y, c, d); //二次贝塞曲线函数   26                     }27                     // For the last 2 points28                     if (count >= 3) {29                         ctx.quadraticCurveTo(30                             this.points.get(i).x,31                             this.points.get(i).y,32                             this.points.get(i + 1).x,33                             this.points.get(i + 1).y34                         );35                     } else if (count >= 2) {36                         ctx.lineTo(this.points.get(1).x, this.points.get(1).y);37                     }38                     ctx.stroke();39                 } else {40                     if (isDrawHit) {41                         ctx.fillStyle = this.colorKey;42                     }43                     else {44                         ctx.fillStyle = this.lineColor;45                     }46                     if (ctx.canvas.id == "hitCanvas")47                         var radius = this.lineWidth + eraserRadius;//扩大hit上线条的范围,橡皮半径48                     else49                         var radius = this.lineWidth;50                     ctx.arc(this.points.get(0).x, this.points.get(0).y, radius, 0, 2 * Math.PI);51                     ctx.fill();52                 }53
View Code

 

其中绘制到hitCanvas上的时候将lineWidth扩大加上了eraserRadius(圆形橡皮擦半径),下图即为绘制到hitCanvas上的colorKey颜色线条,每个线条颜色值是上图中的key值colorKey。另外线条粗细明显比上面的白色线条要粗很多,因为橡皮擦是个cur鼠标样式它的半径很大,但获取的鼠标点击位置还只是一个像素点坐标,所以为了扩大鼠标点到线条上的范围将其变粗。

 

2. 线擦除和点擦除

这样线擦除就很容易实现,只需要找到橡皮擦点到画布上的坐标点的色值,就其从hash集合中根据colorKey删除掉该项,即实现了删除整条线。

点擦除就需要考虑到从两端擦除或者从中间擦除的情况:

1         if (that.isErasePoint) { 2                     line.points.foreach(function (i, p) { 3                         //橡皮擦距离该线条上点的距离是否在橡皮擦半径范围内 4                         if (Math.pow(p.x - point.x, 2) + Math.pow(p.y - point.y, 2) <= Math.pow(eraserRadius, 2)) { 5                             isSeparate = true;//已经找到橡皮擦半径范围内的点,该点不存入两个集合中的任何一个 6                         } else { 7                             if (isSeparate)//找到后将之后的点存入另一个点集合points2中 8                                 points2.add(p); 9                             else//找到之前将点存入点集合points1中10                                 points1.add(p);11                         }12                     })13                     //遍历完线条points上的所有点后。根据points1和points2是否为空处理点擦除后的线条14                     if (points1.length() >= 1 && points2.length() >= 1) {
//points1和points2都不为空,说明从中间擦除变为两条线15 var preLine = editor.commonEditLogic.clonePenLine(line);16 line.points = points1;17 var linePen = editor.bdCanvas.elementFactory.createPenLine(point, line.lineWidth, line.lineColor);18 linePen.points = points2; editor.bdCanvas.activeElement.setPenLine(linePen.colorKey, linePen);19 } else if (points1.length() == 0 && points2.length() >= 1) {
//从一端擦除20 line.points = points2;21 } else if (points1.length() >= 1 && points2.length() == 0) {
//从一端擦除22 line.points = points1;23 } else if (points1.length() == 0 && points2.length() == 0) {
//线条上的点全部被擦除,删除该线条24 editor.bdCanvas.activeElement.delPenLine(line.colorKey);26 }27 editor.courseware.currentBlackboard.draw(false, true);30 }

 

转载于:https://www.cnblogs.com/fangsmile/p/7171789.html

你可能感兴趣的文章
JS中使用正则表达式
查看>>
我的友情链接
查看>>
VM with share disk configuration
查看>>
解决:Loading kernel module CAP_SYS_MODULE CAP_NET_ADMIN alias netdev-eth0 instead
查看>>
oracle 常用查询
查看>>
QT常用类
查看>>
PHP cURL下载/导出文件
查看>>
java之ArrayList集合
查看>>
系统集成项目管理工程师2011年下半年试题
查看>>
我的友情链接
查看>>
wav2letter-基于深度学习的语音识别
查看>>
二、数据类型
查看>>
多节点CDN缓存加速系统wdcdn2.2版本发布(20111115)
查看>>
Java class.forname()和newinstance
查看>>
Java 命令行编译 获得参数
查看>>
Shell 脚本入二
查看>>
Fastboot刷Android系统
查看>>
(DBA之路【二】)mysql 主流存储引擎的特点
查看>>
基于UDP协议的网络程序
查看>>
Linux常用网络工具traceroute路由扫描
查看>>