原生canvas建造绘图小器材的踩坑和爬坑
副问题[/!--empirenews.page--]
最近在写一个相同截图里的浅显绘图的小器材,画线,画矩形,画圆,可以选择颜色,就像这样 写的进程中碰着了一些坑,还好爬出来了,也获得几位大佬的指点,轻微打仗了一下zrender,在这里记录一下。 坑1,绘制进程的预览 用canvas画线没什么题目,moveTo和lineTo就好了,来一段代码凑字数(:joy:) 鼠标按下,开始绘制,记录初始鼠标的位置 startPaint = (e)=>{ this.startPaintFlag = true; this.paintstartX = e.clientX; this.paintstartY = e.clientY; } 鼠标抬起,遏制绘制 stopPaint = (e)=>{ this.startPaintFlag = false; } painting = (e)=>{ const {activeColor, activeShape} = this.state; 绘制进程中 if(this.startPaintFlag){ const ctx = this.canvas.getContext("2d"); ctx.strokeStyle = activeColor; ctx.lineWidth = 2; ctx.beginPath(); if(activeShape === 'pen'){ ctx.moveTo(this.paintstartX, this.paintstartY); ctx.lineTo(e.clientX, e.clientY); } if(activeShape === 'circle'){ const r = Math.sqrt(Math.pow(e.clientX - this.paintstartX, 2) + Math.pow(e.clientY - this.paintstartY, 2)); ctx.arc(this.paintstartX, this.paintstartY, r, 0, 2*Math.PI) } if(activeShape === 'rect'){ ctx.rect(this.paintstartX, this.paintstartY, e.clientX - this.paintstartX, e.clientY - this.paintstartY); } ctx.stroke(); 记录此次移动的最后位置,供下一次绘制行使 this.paintstartX = e.clientX; this.paintstartY = e.clientY; } } 可是画矩形和圆就失事了,由于截图器材画矩形和圆的时辰,是有预览结果的,就是我一边画,我一边能看到我画出的外形是多大,假如凭证画线的思绪来,会获得这样的一串图形 很好领略,由于mousemove的时辰一向在改变位置和间隔。那么假如我一开始就记录下位置,在画矩形和圆的时辰不改变初始位置呢,那么会获得以下图形 也很好领略,由于没有擦除,每次绘制的图形都在画布上。那擦除不就好了?欠好,由于在画布上画的不是只有一个图形,假如我先画线,再画圆,那么一擦除,之前画的线就没了,令人纠结QAQ 我有过一个思绪是,只擦除这个图形内部的外形,好比上面这一堆齐心圆,我只擦除最后绘制的谁人圆内部的内容,痛惜照旧不可,一方面内部也许有此外线事先绘制了,一方面图形可以拖动放大,也可以拖动缩小,那么怎么办呢? 在叹了一口大气,喝了一杯水,注视了一下窗外之后,想出了一个步伐,我在画布上再叠一个画布不就好了,我在叠上去的这个画布上就可觉得所欲为了不是咩。 来个表示图,玄色框框是我们展收?的画布,玄色外形暗示已经绘制上去的内容,赤色框框是我们在画有预览结果的图形时所行使的姑且画布,赤色外形暗示我们鼠标拖动进程中绘制的预览内容,每次必要绘制预览内容我们就天生一个姑且画布,放在顶层,为所欲为的绘制,绘制完毕(鼠标抬起)将姑且画布烧毁,在展收?的画布(玄色框框)上绘制最终的图形 来一段代码辅佐领略 startPaint = (e) => { this.startPaintFlag = true; this.paintstartX = e.clientX; this.paintstartY = e.clientY; 画矩形和圆形时姑且天生一个canvas if (this.state.activeShape !== "pen") { this.tempCanvas = document.createElement("canvas"); this.tempCanvas.width = this.canvas.width; this.tempCanvas.height = this.canvas.height; 配置一些定位样式 this.tempCanvas.style.cssText = "position: absolute; top: 0; left: 0; z-index: 0;"; append到必要的容器元素里 document.querySelector(".contain").appendChild(this.tempCanvas); } }; stopPaint = (e) => { this.startPaintFlag = false; const { activeShape, activeColor } = this.state; if (activeShape !== "pen") { 从容器元素里删除姑且画布 document.querySelector(".contain").removeChild(this.tempCanvas); this.tempCanvas = null; 将lastDrawData记录的绘制数据,绘制到展收?的画布上 const ctx = this.canvas.getContext("2d"); ctx.strokeStyle = activeColor; ctx.lineWidth = 2; ctx.beginPath(); if (activeShape === "circle") { const { x, y, r } = this.lastDrawData; ctx.arc(x, y, r, 0, 2 * Math.PI); } else { const { x, y, width, height } = this.lastDrawData; ctx.rect(x, y, width, height); } ctx.stroke(); this.lastDrawData = null; } }; painting = (e) => { const { activeColor, activeShape } = this.state; if (this.startPaintFlag) { const ctx = this.canvas.getContext("2d"); ctx.strokeStyle = activeColor; ctx.lineWidth = 2; 画线的逻辑不动 if (activeShape === "pen") { ctx.beginPath(); ctx.moveTo(this.paintstartX, this.paintstartY); ctx.lineTo(e.clientX, e.clientY); ctx.stroke(); this.paintstartX = e.clientX; this.paintstartY = e.clientY; } else { 有预览的图形绘制在姑且画布上 const tempCtx = this.tempCanvas.getContext("2d"); tempCtx.strokeStyle = activeColor; tempCtx.lineWidth = 2; 每次绘制前破除画布 tempCtx.clearRect(0, 0, this.canvas.width, this.canvas.height); tempCtx.beginPath(); if (activeShape === "circle") { const r = Math.sqrt( Math.pow(e.clientX - this.paintstartX, 2) + Math.pow(e.clientY - this.paintstartY, 2) ); tempCtx.arc(this.paintstartX, this.paintstartY, r, 0, 2 * Math.PI); 绘制的数据记录在一个变量里 this.lastDrawData = { x: this.paintstartX, y: this.paintstartY, r, }; } else { tempCtx.rect( this.paintstartX, this.paintstartY, e.clientX - this.paintstartX, e.clientY - this.paintstartY ); this.lastDrawData = { x: this.paintstartX, y: this.paintstartY, width: e.clientX - this.paintstartX, height: e.clientY - this.paintstartY, }; } tempCtx.stroke(); } } }; 坑2,窗口巨细改观 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |