实例解析程序中 canvas 拖动功能的实现方式

why 309 2024-06-24

本篇文章给大家通过代码实例来讲解一下微信小程序canvas拖动元素功能的实现方法,希望对大家有所帮助!

通过实例了解一下小程序中怎么实现canvas拖动功能

创建画布

1

<canvas type="2d" id="myCanvas" style="height: 600px; width: 500px;"></canvas>

data数据

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

// 鼠标状态

statusConfig : {

      idle: 0,       //正常状态

      Drag_start: 1, //拖拽开始

      Dragging: 2,   //拖拽中

},

// canvas 状态

canvasInfo : {

   // 圆的状态

   status: 0,

   // 鼠标在在圆圈里位置放里头

   dragTarget: null,

   // 点击圆时的的位置

   lastEvtPos: {x: null, y: null},

},

在画布上画两个圆

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

onLoad: function (options) {

    // 设置画布,获得画布的上下文 ctx

    this.getCanvas();

},

getCanvas(){

    // 根据id获取canvas元素,微信小程序无法使用document, 我们需要使用wx.createSelectorQuery()来代替

    const query = wx.createSelectorQuery()

    query.select(&#39;#myCanvas&#39;)

      .fields({ node: true, size: true })

      .exec((res) => {

        const canvas = res[0].node

        // 设置画布的比例

        canvas.width="500";

        canvas.height="600";

        const ctx = canvas.getContext(&#39;2d&#39;)

        // 在画布上画两个圆,将ctx传递过去绘画

        this.drawCircle(ctx, 100, 100, 20);

        this.drawCircle(ctx, 200, 200, 10);

        // 将我们绘画的信息保存起来,之后移动后需要清空画板重新画

        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 = &#39;yellow&#39;

    ctx.lineWidth = 3

    ctx.arc(cx, cy, r, 0, 2 * Math.PI)

    ctx.stroke()

    ctx.closePath()

    ctx.restore()

},

image.png

给画布设3个触控事件

1

2

3

4

<canvas type="2d" id="myCanvas"

 bindtouchstart="handleCanvasStart"  bindtouchmove="handleCanvasMove"  bindtouchend="handleCanvasEnd"

 style="height: 600px; width: 500px;">

</canvas>

类型触发条件
touchstart手指触摸动作开始
touchmove手指触摸后移动
touchcancel手指触摸动作被打断,如来电提醒,弹窗
touchend手指触摸动作结束
tap手指触摸后马上离开

触摸动作开始,若点击点在圆中,改变canvasInfo中的信息

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

handleCanvasStart(e){

    // 获取点击点的位置

    const canvasPosition = this.getCanvasPosition(e);

    // 判断点击点的位置在不在圈里,如果不在返回false, 在返回圆的信息

    const circleRef = this.ifInCircle(canvasPosition);

    const {canvasInfo, statusConfig} = this.data;

    // 在圆里的话,改变圆此时的状态信息

    if(circleRef){

      canvasInfo.dragTarget = circleRef;

      //改变拖动状态 idle -> Drag_start

      canvasInfo.status = statusConfig.Drag_start;

      canvasInfo.lastEvtPos = canvasPosition;

    }

    this.setData({

      canvasInfo

    })

  },

// 获取点击点的位置

getCanvasPosition(e){

    return{

      x: e.changedTouches[0].x,

      y: e.changedTouches[0].y

    }

},

 

// 看点击点击点是不是在圈里

ifInCircle(pos){

    const {circles} = this.data;

    for( let i = 0 ; i < circles.length; i++ ){

      // 判断点击点到圆心是不是小于半径

      if( this.getDistance(circles[i], pos) < circles[i].r ){

        return circles[i]

      }

    }

    return false

  },

// 获取两点之间的距离(数学公式)

getDistance(p1, p2){

    return Math.sqrt((p1.x-p2.x) ** 2 + (p1.y-p2.y) ** 2)

}

手指触摸后移动 , 重新绘制圆

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

handleCanvasMove(e){

    const canvasPosition = this.getCanvasPosition(e);

    const {canvasInfo, statusConfig, circles} = this.data;

    // 是拖拽开始状态,滑动的大小大于5(防抖)

    if( canvasInfo.status === statusConfig.Drag_start &&

      this.getDistance(canvasPosition, canvasInfo.lastEvtPos) > 5){

        // 改变拖动状态 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(&#39;#myCanvas&#39;)

          .fields({ node: true, size: true })

          .exec((res) => {

            const canvas = res[0].node

            canvas.width="500";

            canvas.height="600";

            const ctx = canvas.getContext(&#39;2d&#39;)

            // 遍历circles,把圆重新画一遍

            circles.forEach(c => this.drawCircle(ctx, c.x, c.y, c.r))

          })

    }

 

    this.setData({

      canvasInfo,

    })

  }

手指触摸动作结束 ,改变 canvasInfo在状态重新变成idle

1

2

3

4

5

6

7

8

9

10

handleCanvasEnd(e){

   const {canvasInfo, statusConfig} = this.data;

   if( canvasInfo.status === statusConfig.Dragging ){

   // 改变拖动状态 Dragging ->  idle

     canvasInfo.status = statusConfig.idle;

     this.setData({

       canvasInfo

     })

   }

 }



版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:小程序实战之简单小程序监控功能的实现方法
下一篇:小程序中 textarea 层级过高穿透问题的解决方案浅析
相关文章

 发表评论

暂时没有评论,来抢沙发吧~