ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

小程序 canvas type=2d 来做画画板

2021-08-04 18:02:38  阅读:146  来源: 互联网

标签:canvas const ctx 2d return drawCurrent type any


 组件里的 canvas

 
 
        <canvas
         class="handWriting"
          id="handWriting"
          canvas-id="handWriting"
          type="2d"
          disable-scroll="true"
          @touchstart="uploadScaleStart"
          @touchmove="uploadScaleMove"
          @touchend="uploadScaleEnd"
          @touchcancel="uploadScaleEnd"
          @tap.stop
        />
this.handwriting = new Handwriting(
      {
        canvasName: 'handWriting',
      },
      this
    )
import { systemObj, loadImgSync, canvasToUrlSync } from '../../utils/utils'

class Handwriting {
  // 内置数据
  ctx: any
  canvas: any
  canvasWidth = 300
  canvasHeight = 600
  canvasSaveImgs: any = []
  drawCurrent = 0
  beginPoint: any = {}
  points: any = []
  canvasName = ''
  that = {}

  firstTouch = true // 第一次触发
  lineColorVal = ''
  lineColorAlpha = 1
  lineSize = 10
  isClear = false // 橡皮擦

  constructor(opts: any, _this: any) {
    this.canvasName = opts.canvasName || 'handWriting'
    this.that = _this
    this.init()
  }

  init() {
    const query = uni.createSelectorQuery().in(this.that)
    const config = { node: true, size: true }
    query
      .select(`#${this.canvasName}`)
      .fields(config, (res: any) => {
        // console.log('canvas init:=>', res, systemObj)
        const canvas = res.node
        const ctx = canvas.getContext('2d')
        const { pixelRatio: dpr } = systemObj
        const width = res.width * dpr
        const height = res.height * dpr
        canvas.width = width
        canvas.height = height
        ctx.scale(dpr, dpr)
        this.ctx = ctx
        this.canvas = canvas
        this.canvasWidth = width
        this.canvasHeight = height
        // ctx.fillRect(10, 10, 33, 33) // test
      })
      .exec()
  }
  // 笔迹开始
  uploadScaleStart(event: any) {
    // console.log('start', event)
    const e = event.mp
    if (e.type !== 'touchstart') return false
    const { x, y } = e.touches[0]
    this.points.push({ x, y })
    this.beginPoint = { x, y }
    this.ctx.strokeStyle = `rgba(${this.lineColorVal}, ${this.lineColorAlpha})`
    this.ctx.lineWidth = this.lineSize

    if (systemObj.platform !== 'devtools') {
      this.ctx.lineCap = 'round'
      let type = 'source-over'
      this.isClear && (type = 'destination-out')
      this.ctx.globalCompositeOperation = type
    }

    // if (this.firstTouch) {
    //   this.firstTouch = false
    // }
  }
  drawLine(beginPoint: any, controlPoint: any, endPoint: any) {
    this.ctx.beginPath()
    this.ctx.moveTo(beginPoint.x, beginPoint.y)
    this.ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, endPoint.x, endPoint.y)
    this.ctx.stroke()
    this.ctx.closePath()
  }
  // 笔迹移动
  uploadScaleMove(event: any) {
    // console.log('move')
    let e = event.mp
    if (e.type !== 'touchmove') return false
    if (e.cancelable) {
      // 判断默认行为是否已经被禁用
      if (!e.defaultPrevented) {
        e.preventDefault()
      }
    }
    const { x, y } = e.touches[0]
    this.points.push({ x, y })
    if (this.points.length > 3) {
      const lastTwoPoints = this.points.slice(-2)
      const controlPoint = lastTwoPoints[0]
      const endPoint = {
        x: (lastTwoPoints[0].x + lastTwoPoints[1].x) / 2,
        y: (lastTwoPoints[0].y + lastTwoPoints[1].y) / 2,
      }
      this.drawLine(this.beginPoint, controlPoint, endPoint)
      this.beginPoint = endPoint
    }
  }
  // 笔迹结束
  async uploadScaleEnd(event: any) {
    const e = event.mp
    if (e.type != 'touchend') return 0
    const { x, y } = e.changedTouches[0]
    this.points.push({ x, y })

    if (this.points.length > 3) {
      const lastTwoPoints = this.points.slice(-2)
      const controlPoint = lastTwoPoints[0]
      const endPoint = lastTwoPoints[1]
      this.drawLine(this.beginPoint, controlPoint, endPoint)
    }
    this.beginPoint = null
    this.points = []

    await this.drawEnd()
  }
  async getCanvasUrl() {
    return await canvasToUrlSync(this.canvas)
  }
  async drawEnd() {
    const saveSteps = this.canvasSaveImgs.length
    if (this.drawCurrent > 0) {
      this.canvasSaveImgs.length = saveSteps - this.drawCurrent
      this.drawCurrent = 0
    }
    this.canvasSaveImgs.push(await this.getCanvasUrl())
  }
  selectColorEvent(val: any) {
    this.lineColorVal = val
    this.isClear = false
  }
  selectLineSize(val: any) {
    this.lineSize = val
  }
  clearEvent() {
    this.isClear = true
  }
  noClearEvent() {
    this.isClear = false
  }
  clearAllCanvas() {
    this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
  }
  async stepChange(type: string) {
    const saveSteps = this.canvasSaveImgs.length

    if (type === 'last') {
      if (this.drawCurrent < saveSteps) {
        this.drawCurrent++
      } else {
        return
      }
    }
    if (type === 'next') {
      if (this.drawCurrent > 0) {
        this.drawCurrent--
      } else {
        return
      }
    }

    this.clearAllCanvas()
    this.ctx.globalCompositeOperation = 'source-over'

    if (this.drawCurrent === saveSteps) {
      return
    }

    const index = saveSteps - this.drawCurrent - 1
    const { pixelRatio: dpr } = systemObj
    const img: any = await loadImgSync(this.canvas, this.canvasSaveImgs[index])
    this.ctx.drawImage(
      img,
      0,
      0,
      this.canvasWidth,
      this.canvasHeight,
      0,
      0,
      this.canvasWidth / dpr,
      this.canvasHeight / dpr
    )
  }
  getHelpfulData() {
    return {
      drawCurrent: this.drawCurrent,
      saveSteps: this.canvasSaveImgs.length,
    }
  }
}

export default Handwriting

 

utils.js

export function loadImgSync(canvas: any, url: string) {
  const img = canvas.createImage()
  img.src = url
  return new Promise((resolve, reject) => {
    img.onload = () => {
      resolve(img)
    }
  })
}

export function canvasToUrlSync(canvas: any) {
  return new Promise((resolve, reject) => {
    wx.canvasToTempFilePath({
      canvas,
      success: async (res: any) => {
        // console.log('tools-url:>', res.tempFilePath)
        // uni.previewImage({
        //   urls: [res.tempFilePath]
        // })
        resolve(res.tempFilePath)
      },
      fail: (err) => {
        console.log('图片生成失败:' + JSON.stringify(err))
        reject()
      },
    })
  })
}

export const systemInfo = uni.getSystemInfoSync()

 

 

标签:canvas,const,ctx,2d,return,drawCurrent,type,any
来源: https://www.cnblogs.com/xiangsj/p/15100105.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有