天天看點

利用vue制作線上塗鴉闆Canvas API簡介功能需求說明初始化資料設定繪畫配置

效果展示
利用vue制作線上塗鴉闆Canvas API簡介功能需求說明初始化資料設定繪畫配置

Canvas API簡介

調用方法

  • getImageData()

    傳回

    ImageData

    對象,該對象為畫布上指定的矩形複制像素資料
  • putImageData()

    把圖像資料(從指定的

    ImageData

    對象)放回畫布上
  • clearRect()

    在給定的矩形内清除指定的像素
  • toDataURL()

    傳回canvas圖像的URL
  • lineTo()

    添加一個新點,建立從該點到最後指定點的線條
  • stroke()

    繪制已定義的路徑
  • beginPath()

    起始一條路徑,或重置目前路徑
  • moveTo()

    把路徑移動到畫布中的指定點,不建立線條

調用屬性

  • strokeStyle

    設定或傳回用于筆觸的顔色、漸變或模式
  • 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]]
           
demo位址
檢視代碼

繼續閱讀