簡體   English   中英

可拖動 canvas 圖像被拖到 canvas 之外時卡在邊界

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM