溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

小程序中如何實(shí)現(xiàn)canvas拖動(dòng)功能

發(fā)布時(shí)間:2021-11-30 09:04:30 來源:億速云 閱讀:881 作者:小新 欄目:移動(dòng)開發(fā)

這篇文章給大家分享的是有關(guān)小程序中如何實(shí)現(xiàn)canvas拖動(dòng)功能的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

創(chuàng)建畫布
<canvas type="2d" id="myCanvas" style="height: 600px; width: 500px;"></canvas>

data數(shù)據(jù)

// 鼠標(biāo)狀態(tài)
statusConfig : {
      idle: 0,       //正常狀態(tài)
      Drag_start: 1, //拖拽開始
      Dragging: 2,   //拖拽中
},
// canvas 狀態(tài)
canvasInfo : {
   // 圓的狀態(tài)
   status: 0,
   // 鼠標(biāo)在在圓圈里位置放里頭
   dragTarget: null,
   // 點(diǎn)擊圓時(shí)的的位置
   lastEvtPos: {x: null, y: null},
},

在畫布上畫兩個(gè)圓

onLoad: function (options) {
    // 設(shè)置畫布,獲得畫布的上下文 ctx
    this.getCanvas();
},
getCanvas(){
    // 根據(jù)id獲取canvas元素,微信小程序無法使用document, 我們需要使用wx.createSelectorQuery()來代替
    const query = wx.createSelectorQuery()
    query.select('#myCanvas')
      .fields({ node: true, size: true })
      .exec((res) => {
        const canvas = res[0].node
        // 設(shè)置畫布的比例
        canvas.width="500";
        canvas.height="600";
        const ctx = canvas.getContext('2d')
        // 在畫布上畫兩個(gè)圓,將ctx傳遞過去繪畫
        this.drawCircle(ctx, 100, 100, 20);
        this.drawCircle(ctx, 200, 200, 10);
        // 將我們繪畫的信息保存起來,之后移動(dòng)后需要清空畫板重新畫
        var circles = []
        circles.push({x: 100, y: 100, r: 20});
        circles.push({x: 200, y: 200, r: 10});
        // 不要忘記保存哦
        this.setData({
         circles
        })
      })
   },
// 畫圓
drawCircle(ctx, cx, cy, r){
    ctx.save()
    ctx.beginPath()
    ctx.strokeStyle = 'yellow'
    ctx.lineWidth = 3
    ctx.arc(cx, cy, r, 0, 2 * Math.PI)
    ctx.stroke()
    ctx.closePath()
    ctx.restore()
},

小程序中如何實(shí)現(xiàn)canvas拖動(dòng)功能

給畫布設(shè)3個(gè)觸控事件

<canvas type="2d" id="myCanvas" 
 bindtouchstart="handleCanvasStart"  bindtouchmove="handleCanvasMove"  bindtouchend="handleCanvasEnd"
 style="height: 600px; width: 500px;">
</canvas>
類型觸發(fā)條件
touchstart手指觸摸動(dòng)作開始
touchmove手指觸摸后移動(dòng)
touchcancel手指觸摸動(dòng)作被打斷,如來電提醒,彈窗
touchend手指觸摸動(dòng)作結(jié)束
tap手指觸摸后馬上離開

觸摸動(dòng)作開始,若點(diǎn)擊點(diǎn)在圓中,改變canvasInfo中的信息

handleCanvasStart(e){
    // 獲取點(diǎn)擊點(diǎn)的位置
    const canvasPosition = this.getCanvasPosition(e);
    // 判斷點(diǎn)擊點(diǎn)的位置在不在圈里,如果不在返回false, 在返回圓的信息
    const circleRef = this.ifInCircle(canvasPosition);
    const {canvasInfo, statusConfig} = this.data;
    // 在圓里的話,改變圓此時(shí)的狀態(tài)信息
    if(circleRef){
      canvasInfo.dragTarget = circleRef;
      //改變拖動(dòng)狀態(tài) idle -> Drag_start
      canvasInfo.status = statusConfig.Drag_start;
      canvasInfo.lastEvtPos = canvasPosition;
    }
    this.setData({
      canvasInfo
    })
  },
// 獲取點(diǎn)擊點(diǎn)的位置
getCanvasPosition(e){
    return{
      x: e.changedTouches[0].x,
      y: e.changedTouches[0].y
    }
},

// 看點(diǎn)擊點(diǎn)擊點(diǎn)是不是在圈里
ifInCircle(pos){
    const {circles} = this.data;
    for( let i = 0 ; i < circles.length; i++ ){
      // 判斷點(diǎn)擊點(diǎn)到圓心是不是小于半徑
      if( this.getDistance(circles[i], pos) < circles[i].r ){
        return circles[i]
      }
    }
    return false
  },
// 獲取兩點(diǎn)之間的距離(數(shù)學(xué)公式)
getDistance(p1, p2){
    return Math.sqrt((p1.x-p2.x) ** 2 + (p1.y-p2.y) ** 2)
}

手指觸摸后移動(dòng) , 重新繪制圓

handleCanvasMove(e){
    const canvasPosition = this.getCanvasPosition(e);
    const {canvasInfo, statusConfig, circles} = this.data;
    // 是拖拽開始狀態(tài),滑動(dòng)的大小大于5(防抖)
    if( canvasInfo.status === statusConfig.Drag_start && 
      this.getDistance(canvasPosition, canvasInfo.lastEvtPos) > 5){
        // 改變拖動(dòng)狀態(tài) Drag_start ->  Dragging
        canvasInfo.status = statusConfig.Dragging;
    }else if( canvasInfo.status === statusConfig.Dragging ){
        canvasInfo.dragTarget.x = canvasPosition.x;
        canvasInfo.dragTarget.y = canvasPosition.y;
        // 重新繪制
        const query = wx.createSelectorQuery()
        query.select('#myCanvas')
          .fields({ node: true, size: true })
          .exec((res) => {
            const canvas = res[0].node
            canvas.width="500";
            canvas.height="600";
            const ctx = canvas.getContext('2d')
            // 遍歷circles,把圓重新畫一遍
            circles.forEach(c => this.drawCircle(ctx, c.x, c.y, c.r))
          })
    }

    this.setData({
      canvasInfo,
    })
  }

手指觸摸動(dòng)作結(jié)束 ,改變 canvasInfo在狀態(tài)重新變成idle

 handleCanvasEnd(e){
    const {canvasInfo, statusConfig} = this.data;
    if( canvasInfo.status === statusConfig.Dragging ){
    // 改變拖動(dòng)狀態(tài) Dragging ->  idle
      canvasInfo.status = statusConfig.idle;
      this.setData({
        canvasInfo
      })
    }
  }

感謝各位的閱讀!關(guān)于“小程序中如何實(shí)現(xiàn)canvas拖動(dòng)功能”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI