获取canvas画布内容(清除canvas画布内容点擦除+线擦除)
获取canvas画布内容
清除canvas画布内容点擦除+线擦除清空canvas画布内容
1、重置宽或高
由于canvas每当高度或宽度被重设时,画布内容就会被清空,因此可以用以下方法清空:(此方法仅限需要清除全部内容的情况)
var c=document.getElementById("myCanvas"); c.width=c.width;
2、clearRect
var c=document.getElementById("myCanvas"); var ctx=c.getContext("2d"); ctx.fillStyle="red"; ctx.fillRect(0,0,300,150); 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
使用异或操作对源图像与目标图像进行组合。
<!DOCTYPE html> <html> <head> <style> canvas { border:1px solid #d3d3d3; margin-right:10px; margin-bottom:20px; } </style> </head> <body> <script> var gco=new Array(); gco.push("source-atop"); gco.push("source-in"); gco.push("source-out"); gco.push("source-over"); gco.push("destination-atop"); gco.push("destination-in"); gco.push("destination-out"); gco.push("destination-over"); gco.push("lighter"); gco.push("copy"); gco.push("xor"); for (n=0;n<gco.length;n++) { document.write("<li id='p_" + n + "' style='float:left;'>" + gco[n] + ":<br>"); var c=document.createElement("canvas"); c.width=120; c.height=100; document.getElementById("p_" + n).appendChild(c); var ctx=c.getContext("2d"); ctx.fillStyle="blue"; ctx.fillRect(10,10,50,50); ctx.globalCompositeOperation=gco[n]; ctx.beginPath(); ctx.fillStyle="red"; ctx.arc(50,50,30,0,2*Math.PI); ctx.fill(); document.write("</li>"); } </script> </body> </html>
可以看出如果设置成destination-out,就可以清除canvas现有的像素点的图像。
清除绘制到画布上的线条(点擦除,线擦除)
在我最近实现的项目中有画笔功能, 同时画笔画出的线条可以被橡皮擦擦除,有点擦除和线擦除两种方式。
使用以上两种方法也可以,但是如果这些线条不止绘制一次的话呢,中间有其他操作(例如绘制的内容变换一次后)那上面的方法就不容易做到了,因为要反复绘制存储每次擦除后的数据,简单的为了能达到该目的,可以将整个canvas画布转化成base64编码的image,后面再次绘制的时候把这个image数据再绘制到canvas上,可以继续在这个canvas上进行绘制和擦除内容。但是怎么样也不好做到线擦除的功能了!
下面介绍另外一种存储绘制路径点坐标的方法去实现绘制线条后的点擦除和线擦除的功能。
首先介绍下存储线条的数据结构,之前写的一篇《js实现存储对象的数据结构hashTable和list》大家可以先大致看看hash结构的实现,但是key和value快速查找的优势需要清楚。另外在canvas画的各种形状和线条,我们是如何知道点击到哪个元素哪条线?《软件项目技术点(4)——实现点击画布上元素》这篇博客里有说明实现原理。
1. 线条存储及绘制
项目中我存储的线条hash结构的对象如下:
展开第一个线条key值为“#8c471a”的具体信息如下,value值其中有colorKey,lineColor,lineWidth,以及最重要的List结构的points对象,是一个存储了该线条所有点坐标集合的List对象。
下面的一段代码,实现了绘制该线条到画布。使用二次贝塞尔函数使得绘制出来的线条流畅平滑没有折痕,当只有一个点时可绘制出一个圆点。
var count = this.points.length(); var p: Core.Point = this.points.get(0); if (isDrawHit) { ctx.strokeStyle = this.colorKey; } else { ctx.strokeStyle = this.lineColor; } ctx.lineCap = "round"; ctx.lineJoin = 'round';//转折的时候不出现尖角 if (ctx.canvas.id == "hitCanvas") ctx.lineWidth = this.lineWidth + eraserRadius;//扩大hit上线条的范围,橡皮半径 else ctx.lineWidth = this.lineWidth; ctx.beginPath(); if (count >= 2) { ctx.moveTo(p.x, p.y); for (var i = 1; i < count - 2; i++) { // p = this.points.get(i); // ctx.lineTo(p.x, p.y); if (this.points.get(i).x == this.points.get(i + 1).x && this.points.get(i).y == this.points.get(i + 1).y) continue; var c = (this.points.get(i).x + this.points.get(i + 1).x) / 2; var d = (this.points.get(i).y + this.points.get(i + 1).y) / 2; ctx.quadraticCurveTo(this.points.get(i).x, this.points.get(i).y, c, d); //二次贝塞曲线函数 } // For the last 2 points if (count >= 3) { ctx.quadraticCurveTo( this.points.get(i).x, this.points.get(i).y, this.points.get(i + 1).x, this.points.get(i + 1).y ); } else if (count >= 2) { ctx.lineTo(this.points.get(1).x, this.points.get(1).y); } ctx.stroke(); } else { if (isDrawHit) { ctx.fillStyle = this.colorKey; } else { ctx.fillStyle = this.lineColor; } if (ctx.canvas.id == "hitCanvas") var radius = this.lineWidth + eraserRadius;//扩大hit上线条的范围,橡皮半径 else var radius = this.lineWidth; ctx.arc(this.points.get(0).x, this.points.get(0).y, radius, 0, 2 * Math.PI); ctx.fill(); }
其中绘制到hitCanvas上的时候将lineWidth扩大加上了eraserRadius(圆形橡皮擦半径),下图即为绘制到hitCanvas上的colorKey颜色线条,每个线条颜色值是上图中的key值colorKey。另外线条粗细明显比上面的白色线条要粗很多,因为橡皮擦是个cur鼠标样式它的半径很大,但获取的鼠标点击位置还只是一个像素点坐标,所以为了扩大鼠标点到线条上的范围将其变粗。
2. 线擦除和点擦除
这样线擦除就很容易实现,只需要找到橡皮擦点到画布上的坐标点的色值,就其从hash集合中根据colorKey删除掉该项,即实现了删除整条线。
点擦除就需要考虑到从两端擦除或者从中间擦除的情况:
if (that.isErasePoint) { line.points.foreach(function (i, p) { //橡皮擦距离该线条上点的距离是否在橡皮擦半径范围内 if (Math.pow(p.x - point.x, 2) + Math.pow(p.y - point.y, 2) <= Math.pow(eraserRadius, 2)) { isSeparate = true; //已经找到橡皮擦半径范围内的点,该点不存入两个集合中的任何一个 } else { if (isSeparate) //找到后将之后的点存入另一个点集合points中 points2.add(p); else//找到之前将点存入点集合points1中 points.add(p); } }) //遍历完线条points上的所有点后。根据points1和points2是否为空处理点擦除后的线条 if (points1.length() >= 1 && points2.length() >= 1) { //points1和points2都不为空,说明从中间擦除变为两条线 var preLine = editor.commonEditLogic.clonePenLine(line); line.points = points1; var linePen = editor.bdCanvas.elementFactory.createPenLine(point, line.lineWidth, line.lineColor); linePen.points = points2; editor.bdCanvas.activeElement.setPenLine(linePen.colorKey, linePen); } else if (points1.length() == 0 && points2.length() >= 1) { //从一端擦除 line.points = points2; } else if (points1.length() >= 1 && points2.length() == 0) { //从一端擦除 line.points = points1; } else if (points1.length() == 0 && points2.length() == 0) { //线条上的点全部被擦除,删除该线条 editor.bdCanvas.activeElement.delPenLine(line.colorKey); } editor.courseware.currentBlackboard.draw(false, true); }
到此这篇关于清除canvas画布内容(点擦除+线擦除)的文章就介绍到这了,更多相关canvas画布清除内容请搜索开心学习网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持开心学习网!
- html5 canvas绘图(使用html5 canvas绘制圆环动效)
- 如何使用html5的canvas图(html5 canvas实现给图片添加平铺水印)
- canvas如何保存当前的图片(canvas如何实现多张图片编辑的图片编辑器)
- canvas 缩放后字发虚(canvas 绘图时位置偏离的问题解决)
- canvas实现字体粒子爆炸特效(javascript canvas实现雨滴效果)
- canvas图片显示报错(html2canvas生成的图片偏移不完整的解决方法)
- canvas绘制动态线条(5分钟实现Canvas鼠标跟随动画背景)
- canvas画布多次渲染失败(深入了解canvas在移动端绘制模糊的问题解决)
- canvas设置点击(Canvas高级路径操作之拖拽对象的实现)
- html使用canvas画矩形(CSS、SVG和canvas分别实现文本文字纹理叠加效果)
- canvas绘制渐变图形(Canvas实现放大镜效果完整案例分析附代码)
- canvas俄罗斯方块(JavaScript canvas实现俄罗斯方块游戏)
- canvas技术开发(用canvas显示验证码的实现)
- html5的canvas图形绘制技术(导出HTML5 Canvas图片并上传服务器功能)
- canvas 裁剪画布(Canvas图片分割效果的实现)
- canvas宽高技巧(canvas画图被放大且模糊的解决方法)
- 收藏 春节假期,这些景区巨划算(收藏春节假期这些景区巨划算)
- 景区游玩,这些安全知识要牢记(这些安全知识要牢记)
- 各地出招烘 热 旅游(各地出招烘热旅游)
- 2021款起亚霸锐到店了 更换车标,竞争宝马X5有戏吗(2021款起亚霸锐到店了)
- 新款起亚霸锐实拍,比普拉多气派,配3.0T V6,引入国内或许能大卖(新款起亚霸锐实拍)
- ()
热门推荐
- cubeide调试问题(如何使用宝塔安装ionCube扩展)
- nodejs数据采集(nodejs获取表单数据的三种方法实例)
- vue插槽实例(Vue中插槽slot的使用方法与应用场景详析)
- extjs中treepanel属性和方法
- sql中去除重复记录的关键字(sqlserver查询去掉重复数据的实现)
- 进程和线程的区别有哪些
- tick数据间隔时间为2秒(让你一看就明白的$nextTick讲解)
- ubuntu安装cmake(详解ubuntu安装CMake的几种方式)
- idea如何运行tomcat项目(在IDEA 2020.3.1中部署Tomcat并且创建第一个web项目的过程详解)
- ubuntu20.04开启ssh(详解Ubuntu20.04用Xshell通过SSH连接报错的服务问题)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9