当前位置: 首页 > 知识库问答 >
问题:

如何将事件侦听器(click)添加到画布对象?

萧晔
2023-03-14

我正在用canvas构建一个新的Javascript游戏,我想为每个对象添加一个事件监听器。我想画一个有用的操纵杆(箭头),当游戏从智能手机/平板电脑打开。所以,玩家可以通过点击每个箭头来移动角色。

这就是我所拥有的:

game.js:

class Game {
    constructor() {
        this.touchDevice = false;
        this.joystickDown = new Down();
        this.joystickLeft = new Left();
        this.joystickRight = new Right();
        this.joystickUp = new Up();
        this.imgDownArrow = new Image();
        this.imgLeftArrow = new Image();
        this.imgRightArrow = new Image();
        this.imgUpArrow = new Image();
        this.gameStruct = new Object();
        this.gameLoaded = true;
        this.gameOver = false;
    }
}

    initialize(width = 640, height = 480) {
        console.log("Game initialized");
        this.canvas = document.getElementById("canvas");
        this.canvas.width = width;
        this.canvas.height= height;

        if(this.canvas && this.canvas.getContext) {
            this.ctx = this.canvas.getContext("2d");
            if(this.ctx) {
                this.ctx.strokeStyle="#000";

                this.gameStruct.ctx = this.ctx;
                this.gameStruct.canvas = this.canvas;

                function is_touch_device() {  
                    try {  
                      document.createEvent("TouchEvent");
                      return true;  
                    } catch (e) {  
                      return false;  
                    }  
                  }

                this.touchDevice = is_touch_device();

                if(this.touchDevice) {                  
                    this.imgDownArrow.src = "img/joystick/arrow_down.png";
                    this.imgLeftArrow.src = "img/joystick/arrow_left.png";
                    this.imgRightArrow.src = "img/joystick/arrow_right.png";
                    this.imgUpArrow.src = "img/joystick/arrow_up.png";

                    this.gameStruct.imgDownArrow = this.imgDownArrow;
                    this.gameStruct.imgLeftArrow = this.imgLeftArrow;
                    this.gameStruct.imgRightArrow = this.imgRightArrow;
                    this.gameStruct.imgUpArrow = this.imgUpArrow;

                    this.joystickDown.initialize(this.gameStruct);
                    this.joystickLeft.initialize(this.gameStruct);
                    this.joystickRight.initialize(this.gameStruct);
                    this.joystickUp.initialize(this.gameStruct);                    
                }

            } else 
                alert("error_context");
            }
    }

    animate() {
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);

        if(!this.gameOver) {
            this.player.draw();
            if(this.touchDevice) {
                this.joystickDown.draw();
                this.joystickLeft.draw();
                this.joystickRight.draw();
                this.joystickUp.draw();
            }
        }
        window.requestAnimationFrame(this.animate.bind(this));
    }

class Down {
    constructor() {
    }

    initialize(gameStruct) {

        this.gameStruct = gameStruct;
        this.ctx = gameStruct.ctx;
        this.width = gameStruct.canvas.width / 15;
        this.height = gameStruct.canvas.width / 15;
        this.x = (gameStruct.canvas.width) - (this.width*2);
        this.y = gameStruct.canvas.height-this.height;
        this.limitTop = 0;
        this.limitBottom = gameStruct.canvas.height;
        this.limitLeft = 0;
        this.limitRight = gameStruct.canvas.width;
        this.shiftX = this.width / 8;
        this.shiftY = this.height / 8;
        console.log("Joystick initialized");
        return this;
    }

    draw() {
        this.ctx.drawImage(this.gameStruct.imgDownArrow, this.x, this.y, this.width, this.height);
        addEventListener("click", function() {
            console.log("clicked");
        });
        return this.gameStruct;
    }
}

共有1个答案

邹开畅
2023-03-14

它运行click如此多次的原因是您要在draw函数中html" target="_blank">添加事件监听器,每个帧都会调用该事件监听器,每个按钮只调用一次。如果游戏是60fps并且只运行了一秒,那么240个事件监听器都在做同样的事情!

事件侦听器不会消失,所以您只需要添加一个。而且,只要使用addeVentListener()就可以将事件侦听器添加到document对象中。这不是问题,因为您的画布占用了整个屏幕,但是您可以使用This.canvas.AddEventListener()(在game类内部)将事件监听器附加到画布。我认为在initialize函数中使用效果最好。

现在,关于只在按钮上注册click:不幸的是,您不能向不是HTML节点的对象添加事件侦听器。我找到的唯一解决方法是添加一个事件监听器,它在每次单击画布时都运行,然后循环所有按钮,检查单击是否在按钮的范围内。

class Game {
    //...
    initialize() {
        //...

        // I put the buttons in an array so that you can loop through them.
        let buttons = [this.joystickDown, this.joystickUp, this.joystickLeft, this.joystickRight];
        this.canvas.addEventListener('mousedown', function(evt) {
            // The X and Y coordinates of the mouse, relative to the top left corner
            let x = evt.clientX;
            let y = evt.clientY;

            for (let button of buttons) {
                // checkClick is a method you'll have to add to the joystick classes. It'll
                // take in X and Y coordinates and tell if they are within the button.
                if (button.checkClick(x, y)) {
                    // This is a method you'll have on the joystick classes to handle the click.
                    button.handleClick();
                }
            }
        });
        //...
    }
    //...
}
 类似资料:
  • 问题内容: 我有一个删除ID的列表视图。我想为具有特定类的所有元素添加一个侦听器,并发出确认警报。 我的问题是,这似乎只会将侦听器添加到它找到的类的第一个元素。我尝试使用,但是没有用。 清单: 问题答案: 您应该使用。它返回NodeList,但是仅返回找到的第一个元素: 然后,您将循环: 另外,只有在时,您才应该阻止Default 。 还值得注意的是,此方法仅对与绑定的事件处理程序有用。对于你应该

  • 我的代码使用jQuery。我有一个密码输入框,我想要得到输入的密码任何时候。 下面是我的代码: 我确信这是一个正确的代码,因为当我在浏览器的控制台中输入它时,它可以工作,但当我重新加载页面时,它就不工作了 我能做什么?

  • 问题内容: 我有一个ArrayList,它向其中动态添加了一些对象,并且有一个JButton。运行我的程序时ArrayList为空,并且JButton设置为setEnabled(false)。我想在ArrayList中有2个或更多元素时启用我的按钮,如果ArrayList有一项或为空则再次禁用它。我该如何实现? 问题答案: 没有任何种类的通知机制。 我建议您编写自己的实现,该实现将委托给私有的实现

  • 我可以在下面的代码中为添加事件侦听器,但不能添加到。 是不是因为twitter做了一些事情不让我这么做?有办法绕过它吗?

  • 是否有办法将AWT侦听器添加到SWT组件? 我以前制作了一个主要在AWT和Swing组件中运行的应用程序。现在,我有热键功能,它依赖于一个定制的库,该库监听全局键事件并返回相应的AWT键代码。 当我改变整个应用程序并使用SWT组件时,我的问题就出现了。正如我们所知,一些键现在返回一个不同的键代码,这扰乱了整个热键功能。 我想到的最初解决方案是: A.使用javax。摆动jtextfield作为my

  • 问题内容: 我试图在控制器的initialize()方法中将TextArea的textProperty绑定到StringProperty。 值更改时,侦听器会监听这两个对象,以执行某些行为。 但是有些奇怪的事情发生了。 我建立了一个简单的模型来重现这种情况。 Main.java sample.fxml 我认为以上代码与该问题无关。但以防万一,我把它放在这里。 这是控制器。 Controller.j