canvas添加图片,canvas绘制一张图片
前言
图片编辑器虽然是一个涂鸦工具,但在当前疫情形势下,也可以作为老师修改学生在线提交作业的工具。可以大大减轻老师批改作业的工作量。我相信这个软件是有市场的。
这次不具体介绍canvas的各种操作画布的API,相信你在网上也能找到很多关于画布涂鸦的开源代码。即便如此,我相信真正使用画布涂鸦的公司实际项目并不多,转换成图片编辑器的更少,用于编辑多张图片然后统一保存上传的更是少之又少。下面我就以我曾经写过的一个画布涂鸦为基础,记录几个图片编辑的发展和思考过程。
图片编辑器产品需求
先说要求。由于涉及到实际公司的项目开发,符合要求的图片编辑器可能只是编辑单张图片,或者给你一个图片列表,也就是多张图片的编辑。在用户保存之前,用户可以来回切换现在编辑哪张图片,记住每张照片的编辑操作都要允许撤销。最后统一点击保存按钮,未经编辑的图片将被丢弃,经过编辑的带有涂鸦的图片将被上传到服务器。
备考,一定要知道相关知识点。
html2canvas的使用
2 html2canvas这个插件实际上是把网页上的普通html元素转换成画布。那么为什么要把html元素转换成canvas呢?那是因为canva有很多html元素没有的特性,比如在canvas上画图,画线等等,canvas直接提供api把canvas上显示的内容引导成图片。是不是有点类似截图?html2canvas就是利用了这一点。我刚开始用html2canvas的时候,公司的h5项目里有一个平板项目。你需要在平板电脑上签名,然后导出签名的图片并上传。后来web端出现了图片编辑器的项目,使用了插件html2canvas。下面简单介绍一下这个插件。
介绍
html2canvas的2个缺点:
由html2canvas转换而来的画布在最终的视觉效果中并没有100%还原原始元素,也就是说会丢失一些像素。
2安装html2canvas
NP install html 2 can vas html 2 can vas简介
使用从“html 2canvas”html 2 can vas导入2 can vas
如果将一个带有图像(无论是img标签还是背景图像)的html元素转换成画布,生成的画布中的img或背景图像缺失,变成白底,控制台告诉你该图像是跨域的。解决方案如下:
下面第1项必须满足,然后第2项和第3项根据html元素是img标签还是背景图片添加不同的配置项。
1.图片服务器配置Access-Control-Allow-Origin或使用代理。
2.在2.html2canvas: true的配置项中配置使用CORS
3.将crossOrigin=anonymous 添加到3.img标签中。
把html转换成画布,解决图片的跨域问题。
2 HTML画布(DOM,{USE CORS: true,//背景图片跨域缩放:window.devicePixelratio,//像素比例宽度:dom.offsetwidth高度:dom.offsetheight})。然后(canvas={//get base 64 let base 64=canvas . todate URL()})因为html2canvas把普通html转化成了Canvas,Canvas有自己转换成base64的方法,base64格式的文件可以作为img标签的src直接显示在页面上。
img:src= base64 /此时如果要上传生成的图片,base64是不能直接上传的,所以需要将base64转换成blob格式。所以,如下:我们把获得的base64数据传入base64ToBlob函数,最后返回函数的结果就是Blob数据。请注意:这个方法只是一个将base64转换成blob的通用方法。
base64转blob
function base64 toblob(base64){ var arr=base64 . split(,),mime=arr[0]。匹配(/:(。*?);/)[1],bstr=atob(arr[1]),n=bstr.length,u8 arr=new uint 8 array(n);while(n-){ u8arr[n]=bstr . charcodeat(n);} return (new blob ([u8arr],{ type:mime })}其实canvas自带了一个方法,将canas转换成blob对象。
canvas转blob
Canvas.toBlob(file={ //此时,file是Blob数据格式。//成功上传到blob后,需要在blob数据中添加name属性,否则稍后上传到服务器时会出现错误:size not set file . name= cover . png })但是在实际的项目开发中,部分较低版本的手机浏览器中的部分canvas元素不支持toBlob方法,报错toBlob不是函数。所以我们需要对目前不支持canvas.toBlo方法的浏览器做polyfill。
DOM canvas element公开了HTMLCanvasElement接口,该接口提供了用于操作canvas元素的布局和表示的属性和方法。HTMLCanvasElement接口继承了Element接口的属性和方法。(来自MDN)
toBlob方法兼容性写法
如果(!htmlcanvaselement . prototype . toBlob){ object . define property(htmlcanvaselement . prototype, to blob ,{ value: function (callback,type,quality){ var binStr=atob(this . today aurl(type,quality))。split(,)[1])var len=binstr . length var arr=new uint 8 array(len)for(var I=0;我lenI){ arr[I]=binstr . charcodeat(I)} callback(new Blob([arr],{type: type image/png}}}以上代码判断当前浏览器HTMLCanvasElement.prototype是否包含toBlob方法,如果没有,则为htmlcanvaselement.prototype添加toBlob方法。
到目前为止,无论是base64直接转换成blob还是canvas直接转换成blob,最终目的都是为了上传blob数据到服务器。请注意:当前页面的blob数据存储在缓冲区中,而不是上传到计算机硬盘中的本地文件,因此需要添加属性isLocalFile:false。fileData属性接收一个数组,如果是图片,则是一个长度为1,元素为blob格式的数组。上传文件到服务器这里就不介绍了。
提交blob到服务器
//传输完图像数据后,提交给服务器async upload(blo Barr){ const OSS=await this。$ upload OSS . init({ file data:blo Barr,islocal file: false,onprogress: percent={},on success:(RES)={ console . log(RES)} })if(OSS){ const data=await OSS . start()if(!Data.code) {this。$ message . error(data . message)} } } } } { 0 } } } } { 0 } } { 0 } } { 0 } } { 0 } } { 0 } } { 0 } } { 0 } } { 0 } } { 0 } } { 0 } } { 0 } } { 0 } } { 0 } } { 0 } } }以下将详细介绍基于现有画布板一步一步开发多个图片编辑器的思路和过程。
基于canvas的图片编辑器的怎么做?
1.既然要编辑图片,自然要给我们提供图片的地址,可能是本地相对路径,也可能是远程地址,也可能是一张或多张图片。因此,操作的数据结构是一个数组。如果只有一个图像,它是一个长度为1的数组,元素是图像地址。另外,需要解决生成的图像只有涂鸦部分,背景为白色,头像或图像丢失的问题。上面已经提供了详细的解决方案。
2.图片编辑器肯定是通用组件,所以根据父组件传入的图片src的一个数组,填充一个长度相同的二维数组。二维数组中的元素记录了每张图片的编辑历史的集合,即每次操作canvas时生成的base64数据。当图片在编辑前初始化时,默认情况下填充空数组[]。这里有一个填充数组的好方法,fill。值得注意的是:如果fill的内容是引用类型,会导致fill的每一项都是同一个引用,在操作其中一项时会导致其他所有元素一起变化。
//结果:[[],[],]this . canvasarrbase=array(length)。填充(0)。map (item={return []}) 2。单击不同的图片,将图片的src传输到编辑器组件中,并将src用作画布的背景图像。这时候你可以直观的看到一张图片,显示在dom中。
3.开始在页面上涂鸦画布。为了避免无法在surface等触摸屏设备上使用画布涂鸦或图片编辑器,请使用触摸事件而不是鼠标事件。
//开始绘制canvas . addevent listener( touch Start ,e={.},false)//绘图canvas . addevent listener( touch move ,e={.},False) //结束绘制canvas . addevent listener( Touched ,e={.},假)4。在进入图片编辑器之前,将点击图片的索引和图片所在的图片数组,一起作为道具,发送到图片编辑器中。记住当前正在编辑哪张图片currentIndex,以便在这张图片上记录涂鸦或撤销操作。每次用户在画布上操作,也就是开始touchstart,然后touchmove,最后touchend,都会显示当前画布的内容(所有内容,而不仅仅是刚刚涂鸦的那个)。类似于git的每次提交,哪怕只提交一行代码,git都会生成整个项目的快照,而不是只记录这次修改的一行代码。git rollback是快照的回滚),包括这张背景图。用canvas.toDateUrl()生成base64,推送到我们上面介绍的this . canvasarrbase[currentindex]中。这时currenindex所在的数组中的图片又多了一条历史记录,就是刚刚涂鸦的图片已经被我们保存了。这是画布图像编辑器撤销的基础。有了它,我们知道撤销后要显示什么。
new graffiti操作生成的快照存储在currentIndex的数组中。这个。画布arr base[这个。current index]。推(画布。TodataURL ()) 5。切换图片是指改变画布的背景图像,改变currentIndex,然后在新的当前索引上编辑另一张图片。其实也是同样的步骤,只是在当前编辑的图片的推送画布上显示而已。
6.重点来了。怎么取消?怎么撤销?如何在画布上一步一步的撤销,看到最后的绘画记录?
随着每一张图片的编辑,每一张图片都会产生一些历史记录,我们用这些历史记录进行回滚和撤销。当我们点击取消当前编辑的图片时,我们需要将上一个画布中显示的画布内容绘制到当前画布中。取消的时候可以直接删除我们存储的数据源,所以只需要使用canvas.drawImage()方法将要显示的记录绘制到canvas中。
drawImage方法有许多参数。单击查看详细信息。
let new base arr=this . canvasarrbase[this . current index]let { offset width:canvas width,set height:canvas height }=canvas//生成新图片let image=new Image()//将图像的src赋给当前需要显示的base64的值(即让用户看到取消的图像)。image . src=this . canvasarrbase[this . current index][new base arr . length-1]//分配img的src后,使用onload监控图像的加载,加载完成后再进行绘制。如果不添加onload,绘图可能会失败。image . onload=function(){ canvas . draw image(image,0,0,canvas width,canvas height)} 7。关于性能优化:由于你不知道用户会拿多大的图片进行编辑,所以如果有9张图片,每张图片会被编辑10次。那么内存中的base64数据量会非常大,可能会导致页面切换或者取消涂鸦历史时页面卡顿。为了避免这种情况,我会在切换图片之前只存储当前图片最后一张图片的base64。
8.提交保存前,判断this.canvasArrBase中每一项的长度,如果大于0,则编辑,否则过滤掉。然后用上面说的上传方法上传到服务器,就OK了!
总结
在学习油画的道路上,总能给我带来一些惊喜和惊喜。一些知名的工具,如echart、高德地图等。都是基于画布制作的。我曾经有个同事是echart的大神。受他的影响,我逐渐体会到了埃恰特的力量。希望能在这样一个开源社区里和大家一起学习,一起进步。
关于canvas如何实现编辑多张图片的图片编辑器的这篇文章到此为止。有关canvas picture editor的更多信息,请搜索以前的文章或继续浏览下面的相关文章。希望你以后能支持我!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。