效果展現javascript
getImageData()
返回ImageData
對象,該對象爲畫布上指定的矩形複製像素數據html
putImageData()
把圖像數據(從指定的 ImageData
對象)放回畫布上java
clearRect()
在給定的矩形內清除指定的像素git
toDataURL()
返回canvas圖像的URLgithub
lineTo()
添加一個新點,建立從該點到最後指定點的線條canvas
stroke()
繪製已定義的路徑數組
beginPath()
起始一條路徑,或重置當前路徑this
moveTo()
把路徑移動到畫布中的指定點,不建立線條spa
strokeStyle
設置或返回用於筆觸的顏色、漸變或模式code
shadowBlur
設置或返回用於陰影的模糊級別
shadowColor
設置或返回用於陰影的顏色
lineWidth
設置或返回當前的線條寬度
更多API請參考 canvas基本使用
基礎線條繪製功能
筆觸顏色修改
筆刷粗細調整
撤回、前進、狀況功能
生成圖片
colors
: 筆觸顏色列表
brushs
: 筆刷對應的粗細
context
: canvas context
imgUrl
: 用於存放保存圖片的地址
canvasMoveUse
: 是否容許執行move時候繪製線條
preDrawAry
: 存儲當前表面狀態數組-上一步
nextDrawAry
: 存儲當前表面狀態數組-下一步
middleAry
: 中間數組
lineWidth
: 線條寬度
lineColor
: 線條顏色
shadowBlur
: 陰影
data() { return { colors: ['#fef4ac','#0018ba','#ffc200','#f32f15','#cccccc','#5ab639'], brushs: [{ className: 'small fa fa-paint-brush', lineWidth: 3 },{ className: 'middle fa fa-paint-brush', lineWidth: 6 },{ className: 'big fa fa-paint-brush', lineWidth: 12 }], context: {}, imgUrl: [], canvasMoveUse: true, preDrawAry: [], nextDrawAry: [], middleAry: [], config: { lineWidth: 1, lineColor: "#f2849e", shadowBlur: 2 } } }
setCanvasStyle() { this.context.lineWidth = this.config.lineWidth this.context.shadowBlur = this.config.shadowBlur this.context.shadowColor = this.config.lineColor this.context.strokeStyle = this.config.lineColor }
筆觸顏色及粗細相關設置(點擊修改config數據):
<!-- 畫筆顏色 --> <li v-for="item in colors" :class="{'active':config.lineColor === item}" :style="{ background: item }" @click="setColor(item)" ></li>
<!-- 畫筆粗細 --> <span v-for="pen in brushs" :class="[pen.className,{'active': config.lineWidth === pen.lineWidth}]" @click="setBrush(pen.lineWidth)" ></span>
// 當在屏幕中移動時即開始繪製準備 beginPath(e){ const canvas = document.querySelector('#canvas') if (e.target !== canvas) { this.context.beginPath() } }
// 在canvas中鼠標按下 canvasDown(e) { // 讓move方法可用 this.canvasMoveUse = true // client是基於整個頁面的座標 // offset是cavas距離頂部以及左邊的距離 const canvasX = e.clientX - e.target.parentNode.offsetLeft const canvasY = e.clientY - e.target.parentNode.offsetTop // 設置canvas的配置 this.setCanvasStyle() //清除子路徑 this.context.beginPath() // 移動的起點 this.context.moveTo(canvasX, canvasY) //當前繪圖表面狀態 const preData = this.context.getImageData(0, 0, 600, 400) //當前繪圖表面進棧 // 按下至關於新的操做的開始,因此把當前記錄數據放到prev中 this.preDrawAry.push(preData) },
// canvas中鼠標移動 canvasMove(e) { if(this.canvasMoveUse) { // 只有容許移動時調用 const t = e.target let canvasX let canvasY // 因爲手機端和pc端獲取頁面座標方式不一樣,因此須要作出判斷 if(this.isPc()){ canvasX = e.clientX - t.parentNode.offsetLeft canvasY = e.clientY - t.parentNode.offsetTop }else { canvasX = e.changedTouches[0].clientX - t.parentNode.offsetLeft canvasY = e.changedTouches[0].clientY - t.parentNode.offsetTop } // 鏈接到移動的位置並上色 this.context.lineTo(canvasX, canvasY) this.context.stroke() } },
// canvas中鼠標放開 canvasUp(e){ const preData = this.context.getImageData(0, 0, 600, 400) if (!this.nextDrawAry.length) { // 在沒有撤銷過的狀況下,將當前數據放入prev //當前繪圖表面進棧 this.middleAry.push(preData) } else { // 在撤銷的狀況下,將在後面步驟的數據狀況記錄 this.middleAry = [] this.middleAry = this.middleAry.concat(this.preDrawAry) this.middleAry.push(preData) this.nextDrawAry = [] } // 設置move時不可繪製 this.canvasMoveUse = false }
爲了保證移動端的可用性,加入touchstart等。
<canvas id="canvas" class="fl" width="600" height="400" @mousedown="canvasDown($event)" @mouseup="canvasUp($event)" @mousemove="canvasMove($event)" @touchstart="canvasDown($event)" @touchend="canvasUp($event)" @touchmove="canvasMove($event)" >
// 撤銷 if (this.preDrawAry.length) { const popData = this.preDrawAry.pop() const midData = this.middleAry[this.preDrawAry.length + 1] this.nextDrawAry.push(midData) this.context.putImageData(popData, 0, 0) }
// 前進 if (this.nextDrawAry.length) { const popData = this.nextDrawAry.pop() const midData = this.middleAry[this.middleAry.length - this.nextDrawAry.length - 2] this.preDrawAry.push(midData) this.context.putImageData(popData, 0, 0) }
// 清空 this.context.clearRect(0, 0, this.context.canvas.width, this.context.canvas.height) // 清空先後數據 this.preDrawAry = [] this.nextDrawAry = [] // middleAry恢復到默認數據 this.middleAry = [this.middleAry[0]]