《JS原理、方法與實踐》- canvas遊戲

遊戲其實就是在動畫的基礎上添加了控制,也就是添加鍵盤和鼠標的事件監聽。添加事件的方法前面已經學過,添加鍵盤事件和普通節點對象的鍵盤事件相同,只是canvas中的鼠標事件需要做一些處理。

鼠標事件

在鼠標事件中,鼠標指針所處位置的座標是非常重要的屬性,鼠標事件中只能獲取相對於屏幕左上角和相對瀏覽器文檔左上角的座標,而canvas中使用的是自己的座標系,因此需要將獲取的座標轉換爲canvas中的座標。在轉換之前,首先獲取canvas在瀏覽器中的位置,可以通過getBoundingClientRect方法獲取。例如下面的方法將瀏覽器中的座標轉換爲canvas中的座標:

        function convertToCanvas(canvas, x, y){
            var canvasElement = canvas.getBoundingClientRect();
            return {
                x: (x - canvasElement.left) * (canvas.width / canvasElement.width),
                y: (y - canvasElement.top) * (canvas.height / canvasElement.height)
            };
        }

轉換邏輯:

  • 先使用鼠標事件中相對於瀏覽器文檔的座標減去canvas左上角的座標
  • 然後進行相應的縮放

示例:
點中圓中5分,沒點中扣3分。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <canvas id='c2d' width="300" height="300">瀏覽器不支持canvas</canvas>
    <script>
        const canvas = document.getElementById('c2d');
        
        function convertToCanvas(canvas, x, y){
            var canvasElement = canvas.getBoundingClientRect();
            return {
                x: (x - canvasElement.left) * (canvas.width / canvasElement.width),
                y: (y - canvasElement.top) * (canvas.height / canvasElement.height)
            };
        }
        
        if (canvas.getContext) {
            let ctx = canvas.getContext('2d');

            let path, scoreArea = {w:300, h:50};
            function drawObj(){
                const offsetX = 0, offsetY = scoreArea.h;
                
                ctx.save();
                ctx.clearRect(offsetX, offsetY, 300,300);

                const r = 30;
                const x = r + offsetX + Math.round(Math.random() * (canvas.width - 2 * r - offsetX));
                const y = r + offsetY + Math.round(Math.random() * (canvas.height - 2 * r -offsetY));

                path = new Path2D();
                path.arc(x,y,r,0,2*Math.PI);
                ctx.stroke(path);
            }

            window.setInterval(drawObj, 2000);

            let score = 3;

            function drawScore(isTrue){
                score += isTrue ? 5 : -3;

                ctx.save();
                ctx.fillStyle = 'red';
                ctx.clearRect(0,0,scoreArea.w, scoreArea.h);
                ctx.fillText('得分:' + score, 30,30);
                ctx.restore();
            }

            drawScore(false);

            canvas.onclick = function(event){
                const p = convertToCanvas(canvas, event.pageX, event.pageY);
                drawScore(ctx.isPointInPath(path,p.x,p.y));
            }

        }
    </script>
</body>

</html>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章