![](/img/trans.png)
[英]getting drag event on canvas when all elements marked draggable=false
[英]Draggable canvas image getting stuck at the border when getting dragged outside the canvas
我正在使用 React,我有一個 canvas,里面有一個可以拖動的正方形。 當正方形接觸到邊界時,我希望它被重置回它的起始 position。當一切都緩慢而流暢時,這種行為工作正常,但如果我快速拖動鼠標,圖像就會卡住。 卡住我的意思是圖像變得無響應導致頁面重新加載,或者它在將鼠標返回到 canvas 時快速返回到其原始 position。
const Canvas = props => {
useEffect(() =>{
const canvas = canvasRef.current
const context = canvas.getContext('2d')
canvas.width = canvas.getBoundingClientRect().width
canvas.height = canvas.getBoundingClientRect().height
setCanvasWidth(canvas.width);
setCanvasHeight(canvas.height);
canvas.addEventListener('mousedown', e => {
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left; //x position within the element.
var y = e.clientY - rect.top; //y position within the element.
if(x>playerX && (x<playerX+playerWidth) && y>playerY && (y<playerY+playerHeight) && (gameStatus==false)){
setGameStatus(true);
setPlayerStatus(true);
else if(x>playerX && (x<playerX+playerWidth) && y>playerY && (y<playerY+playerHeight) && (gameStatus==true)){
setPlayerStatus(true);
}
});
canvas.addEventListener('mousemove', e => {
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left; //x position within the element.
var y = e.clientY - rect.top; //y position within the element.
//if you are currently controlling the player, x and y coordinates are set to mouse
if(playerStatus){
setPlayerX(x - playerWidth/2);
setPlayerY(y - playerHeight/2);
}
//if the box edges touch the borders
if(
((playerX <= 0 || playerX >= canvasWidth-playerWidth || playerY <= 0 || playerY >= canvasHeight-playerHeight)&&gameStatus)
){
console.log('playerX: '+playerX)
console.log('playerY: '+playerY)
console.log('CanvasWidthLeft: '+ canvasWidth*(0.0001))
console.log('CanvasWidthRight: '+ canvasWidth)
console.log('CanvasHeightUp: '+ canvasHeight*(0.0001))
console.log('CanvasHeightDown: '+ canvasHeight)
setPlayerX(canvasWidth*(0.5) - playerWidth/2)
setPlayerY(canvasHeight*(0.5) - playerHeight/2)
setPlayerStatus(false);
setGameStatus(false);
});
canvas.addEventListener('mouseup', () => {
setPlayerStatus(false);
})
context.fillStyle = '#00f4cc'
context.fillRect(playerX, playerY, playerWidth, playerHeight)
canvas 的工作方式是讓上面的 3 個事件監聽器。 正方形從 canvas 的中間開始,單擊它時playerStatus and gameStatus
狀態會更改以指示正方形是可拖動的。 如果正方形的邊緣接觸到邊框,它將快速回到起點。 當事情進展緩慢時一切正常,但如果事情很快就會出現故障。 有誰知道“立即”阻止正方形移動並在它觸及邊界時迅速回到原位的解決方案? 謝謝!
編輯:
以下是我嘗試但未解決的更多解決方案:
canvas.addEventListener('mouseleave', (e) => {
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left; //x position within the element.
var y = e.clientY - rect.top; //y position within the element.
if(gameStatus){
canvas.draggable = false;
}
})
canvas.addEventListener('mouseout', (e) => {
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left; //x position within the element.
var y = e.clientY - rect.top; //y position within the element.
if(gameStatus){
setPlayerX( 100 )
setPlayerY( 100 )
}
})
您可以使用mouseleave
來檢測鼠標何時離開 canvas 並在那里重置 position,其他一切似乎都正常,您可能在未顯示的功能上遇到其他一些性能問題......
下面是小樣本,我有相同的 3 個事件監聽器,加上mouseleave
const canvas = document.getElementById("canvas") const ctx = canvas.getContext("2d") var player = { x: canvas.width / 2, y: canvas.height / 2, draggable: false } function draw() { ctx.beginPath() ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.arc(player.x, player.y, 10, 0, 2 * Math.PI); ctx.fill() requestAnimationFrame(draw); } draw() canvas.addEventListener('mouseleave', e => { player = { x: canvas.width / 2, y: canvas.height / 2, draggable: false } }) canvas.addEventListener('mousedown', e => { var rect = e.target.getBoundingClientRect(); var x = e.clientX - rect.left; var y = e.clientY - rect.top; player.draggable = Math.hypot(x - player.x, y - player.y) < 20 }); canvas.addEventListener('mousemove', e => { if (player.draggable) { var rect = e.target.getBoundingClientRect(); player.x = e.clientX - rect.left; player.y = e.clientY - rect.top; } }); canvas.addEventListener('mouseup', () => { player.draggable = false })
canvas { border:solid }
<canvas id="canvas"> </canvas>
這是另一個帶正方形的:
const canvas = document.getElementById("canvas") const ctx = canvas.getContext("2d") var player = { x: canvas.width / 2, y: canvas.height / 2, draggable: false } function draw() { ctx.beginPath() ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillRect(player.x -10, player.y -10, 20, 20); requestAnimationFrame(draw); } draw() canvas.addEventListener('mouseleave', e => { player = { x: canvas.width / 2, y: canvas.height / 2, draggable: false } }) canvas.addEventListener('mousedown', e => { var rect = e.target.getBoundingClientRect(); var x = e.clientX - rect.left; var y = e.clientY - rect.top; player.draggable = x > player.x -10 && x < player.x +10 && y > player.y -10 && y < player.y +10 }); canvas.addEventListener('mousemove', e => { if (player.draggable) { var rect = e.target.getBoundingClientRect(); player.x = e.clientX - rect.left; player.y = e.clientY - rect.top; } }); canvas.addEventListener('mouseup', () => { player.draggable = false })
canvas { border:solid }
<canvas id="canvas"> </canvas>
所需要的只是改變玩家何時可拖動的條件
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.