uni-app中canvas的拖动事件是否存在bug?

发布于 1周前 作者 bupafengyu 来自 Uni-App

uni-app中canvas的拖动事件是否存在bug?

代码如上,一个简单的canvas拖动图片的demo,在uniapp内置浏览器中点击图片,出现了2个奇怪的现象

  1. 没有拖动,也调用拖动的函数(如图1)
  2. 明明点击的位置在图片上,而图片的高度是100,得到的clientY=129,明显不对。(如图2)

该代码运行到微信小程序开发者工具,没有上面两个问题。运行改成PC模式也没有上面两个问题

图片

图片1 图片2

代码示例

<template>  
  <view class="container">  
    <canvas canvas-id="puzzleCanvas" @touchstart="handleStart" @touchmove="handleMove" @touchend="handleEnd"  
            @mousedown="handleStart" @mousemove="handleMove" @mouseup="handleEnd"></canvas>  
  </view>  
</template>  

<script>  
export default {  
  data() {  
    return {  
      ctx: null,  
      pieces: [  
        { x: 0, y: 0, width: 100, height: 100, image: '/static/p1.png' },  
        { x: 100, y: 0, width: 100, height: 100, image: '/static/p2.png' },  
        // 更多拼块  
      ],  
      currentPiece: null,  
      offsetX: 0,  
      offsetY: 0,  
      isDragging: false  
    };  
  },  
  mounted() {  
    const canvas = uni.createCanvasContext('puzzleCanvas', this);  
    this.ctx = canvas;  
    this.drawPieces();  
  },  
  methods: {  
    drawPieces() {  
      this.pieces.forEach(piece => {  
        const img = piece.image;  
        // 根据路径绘制图片  
        this.ctx.drawImage(img, piece.x, piece.y, piece.width, piece.height);  
      });  
      this.ctx.draw();  
    },  
    handleStart(event) {  
      this.$showlog("点击开始")  
      const point = this.getPoint(event);  
      this.currentPiece = this.pieces.find(piece => this.isPointInPiece(point, piece));  
      this.$showlog("currentPiece",this.currentPiece)  
      if (this.currentPiece) {  
        this.offsetX = point.x - this.currentPiece.x;  
        this.offsetY = point.y - this.currentPiece.y;  
        this.isDragging = true;  
      }  
    },  
    handleMove(event) {  
      this.$showlog("点击拖动")  
      if (this.isDragging && this.currentPiece) {  
        const point = this.getPoint(event);  
        this.currentPiece.x = point.x - this.offsetX;  
        this.currentPiece.y = point.y - this.offsetY;  
        this.redrawCanvas();  
      }  
    },  
    handleEnd(event) {  
      this.$showlog("点击结束")  
      this.isDragging = false;  
      this.currentPiece = null;  
    },  
    getPoint(event) {  
      this.$showlog("getPoint",event)  
      const touch = event.touches ? event.touches[0] : event;  
      return { x: touch.clientX, y: touch.clientY };  
    },  
    isPointInPiece(point, piece) {  
      return (  
        point.x > piece.x &&  
        point.x < piece.x + piece.width &&  
        point.y > piece.y &&  
        point.y < piece.y + piece.height  
      );  
    },  
    redrawCanvas() {  
      this.ctx.clearRect(0, 0, 750, 750); // 清空画布,750是canvas的宽度和高度  
      this.drawPieces();  
    }  
  }  
}  
</script>  

<style>  
.container {  
  /* position: relative; */  
  width: 750rpx;  
  height: 450rpx;  
}  

canvas {  
  width: 750rpx;  
  height: 450rpx;  
  background-color: #335566;  
}  
</style>

1 回复

在uni-app中,关于canvas的拖动事件是否存在bug,这通常取决于具体的实现方式和平台差异。为了帮助你更好地理解和排查可能的问题,下面提供一个基本的canvas拖动事件实现的代码案例。如果你遇到特定的问题,可以根据这个基础代码进行调整和测试。

首先,确保你的uni-app项目已经正确配置了canvas组件。以下是一个简单的canvas拖动事件的实现示例:

<template>
  <view class="container">
    <canvas
      canvas-id="myCanvas"
      style="width: 300px; height: 300px; border: 1px solid #000;"
      @touchstart="onTouchStart"
      @touchmove="onTouchMove"
      @touchend="onTouchEnd"
    ></canvas>
  </view>
</template>

<script>
export default {
  data() {
    return {
      lastX: 0,
      lastY: 0,
      offsetX: 0,
      offsetY: 0,
      isDragging: false,
    };
  },
  methods: {
    onTouchStart(e) {
      const touch = e.touches[0];
      this.lastX = touch.clientX - this.offsetX;
      this.lastY = touch.clientY - this.offsetY;
      this.isDragging = true;
    },
    onTouchMove(e) {
      if (!this.isDragging) return;
      const touch = e.touches[0];
      this.offsetX = touch.clientX - this.lastX;
      this.offsetY = touch.clientY - this.lastY;
      
      // 假设我们有一个矩形要拖动,这里更新它的位置
      const ctx = uni.createCanvasContext('myCanvas');
      ctx.clearRect(0, 0, 300, 300); // 清除画布
      ctx.setFillStyle('red');
      ctx.fillRect(this.offsetX, this.offsetY, 50, 50); // 绘制矩形
      ctx.draw();
    },
    onTouchEnd() {
      this.isDragging = false;
    },
  },
};
</script>

<style>
.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}
</style>

在这个示例中,我们使用了touchstarttouchmovetouchend事件来处理canvas上的拖动操作。onTouchStart方法记录触摸开始的位置,onTouchMove方法根据触摸移动的位置更新canvas上的图形(在这个例子中是一个矩形),onTouchEnd方法停止拖动。

请注意,这个示例假设你正在绘制一个简单的矩形,并且这个矩形可以拖动。如果你在实际应用中遇到更复杂的情况(比如多个图形的拖动、复杂的碰撞检测等),你可能需要更复杂的逻辑来处理。

如果你发现具体的bug或问题,建议查看uni-app的官方文档或社区论坛,看看是否有其他开发者遇到并解决了类似的问题。同时,确保你的uni-app和依赖库都是最新版本,以利用最新的功能和修复。

回到顶部