HTML5 画布上的多个事件侦听器
我一直在尝试严格使用 HTML5 和 JavaScript 创建游戏,但遇到了一个我似乎无法解决的问题。为了尝试避免使用第三方类/库,我正在创建自己的类来处理 HTML5 canvas 元素中的自定义按钮。我几乎让它们工作,然后在意识到每次画布重绘时我的事件侦听器不断相互添加后,不得不重新编写大部分脚本(我之前在 mouseDown 事件侦听器中使用了匿名函数,但是此后改用了不同的方法)。
首先,我的事件侦听器现在使用一个函数,该函数保存对我尝试使用的任何按钮的引用。然后调用我的原型的 mouseDownFunc,它检查按钮实例尺寸的边界,然后最终调用引用的 onPress()
(这实际上是每个按钮都使用的重写方法,因此每个按钮都有一个按下时的自定义指令集)。
因此,如果您仍在继续(我知道,在没有看到完整脚本的情况下会有点混乱),问题是因为我的事件侦听器使用相同的函数,所以它们会覆盖以前的事件侦听器,因此只有最后按钮正确添加了功能。总而言之,如何向画布元素添加多个事件侦听器,这些侦听器都使用相同的函数而不删除以前的事件侦听器。请注意,我尝试在不使用 jQuery 或其他第三方扩展的情况下执行此操作。
如果需要有关我的代码的更多信息以便更容易理解,请告诉我。预先感谢任何类型的反馈。
编辑:也许这可能有帮助。请注意,这不是完整的代码,但包含要点:
添加按钮:
this.test_button = new CreateButton(this, 'test_button');
this.test_button.onPress = function() {
alert('Blue button works!');
};
this.test_button.create(200, 50, 30, 200, 'text');
在按钮上使用 create()
时,将检查并存储变量以及保存的数组所有当前按钮(因此可以随时引用它们)。然后运行: this.that.custom_canvas.addEventListener('mousedown', this.create.prototype.mouseDownFunc, false);
当调用 mouseDownFunc 时,会发生以下情况:
CreateButton.prototype.create.prototype.mouseDownFunc = function(e) {
var mouse_x = e.clientX-this.offsetLeft;
var mouse_y = e.clientY-this.offsetTop;
// Check if the mini-button button was actually clicked
if(mouse_x >= test2.x && mouse_y >= test2.y && mouse_x <= (test2.x + test2.width) && mouse_y <= (test2.y + test2.height)){
alert('clicked and working!');
test2.onPress(); // A reference to the saved function
}
};
目前,我的 test2 是对任何给定对象的引用——它是一个全局变量,但是在解决了这些其他问题之后,我将处理摆脱全局变量的问题(我知道,我知道——这只是一个临时的快速修复)。
I've been trying to create a game in strictly HTML5 and JavaScript and have run into an issue that I can't seem to wrap my head around. In an attempt to try and avoid using third party classes/libraries, I'm creating my own class for handling custom buttons within the HTML5 canvas element. I almost got them to work and then had to re-write most of the script after realizing that my event listeners kept adding on top of each other every time the canvas redrew (I was using an anonymous function in the mouseDown event listener before, but have since switched to a different method).
First of all, my event listeners now use a function which holds a reference to whichever button I'm trying to use. My prototype's mouseDownFunc is then called, it checks the boundary of the button instance's dimensions, and then finally calls a referenced onPress()
(which is actually an overridden method that every button uses, so each button has a custom set of instructions when pressed).
So, if you're still following along (I know, it's a bit confusing without seeing the full script), the problem is that because my event listeners are using the same function, they're overwriting the previous event listener, so only the last button added functions correctly. To sum this all up, how can I add multiple event listeners to the canvas element, which all use the same function without erasing the previous event listeners. Note that I'm trying to do this without the use of jQuery or other third-party extensions.
If more information is needed in regards to my code so that it's easier to understand, let me know. Thanks in advance for any type of feedback.
Edit: Perhaps this might help. Note that this isn't the complete code, but contains the main points:
Adding a button:
this.test_button = new CreateButton(this, 'test_button');
this.test_button.onPress = function() {
alert('Blue button works!');
};
this.test_button.create(200, 50, 30, 200, 'text');
When using create()
on a button, variables are checked and stored, as well as an array that holds onto all current buttons (so they can be referenced at any point). Then this is run: this.that.custom_canvas.addEventListener('mousedown', this.create.prototype.mouseDownFunc, false);
When mouseDownFunc is called, this takes place:
CreateButton.prototype.create.prototype.mouseDownFunc = function(e) {
var mouse_x = e.clientX-this.offsetLeft;
var mouse_y = e.clientY-this.offsetTop;
// Check if the mini-button button was actually clicked
if(mouse_x >= test2.x && mouse_y >= test2.y && mouse_x <= (test2.x + test2.width) && mouse_y <= (test2.y + test2.height)){
alert('clicked and working!');
test2.onPress(); // A reference to the saved function
}
};
Currently, my test2 is a reference to any given object -- it's a global var, but after I get these other issues fixed, I'll deal with getting rid of the global var (I know, I know - it was just a temporary quick-fix).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
也许您可以创建一个事件来调用路由函数来检查事件发生在元素上的位置,然后委托给另一个函数,而不是为每个可能的按钮设置事件侦听器,并在函数中检查框大小。
Maybe instead of an event listener for each and every possible button, and checking box size within the function, you could create a single event that calls a routing function to check where on the element the event occurred, and then delegate to another function
您需要设计一些东西来处理程序中的事件调度。您似乎有一些组件,其侦听器都杂乱无章。您可以构建树形数据结构(https://en.wikipedia.org/wiki/Tree_ %28data_struct%29),这是组件中事件调度的层次结构(例如按钮、文本区域等)。这个想法是,当遍历树时,事件将以有序的方式处理。该树将根据用户与程序的交互方式进行重新组织。举一个简单的例子,要启动这棵树,也许可以优先考虑最近绘制的组件(在包含要绘制的所有内容的列表的某个结构中)作为事件侦听器,以首先接收事件处理。然后,如果一个组件被另一个组件阻止,则被阻止的组件(例如覆盖按钮的按钮)的事件处理可能会被禁用或安排在稍后发生,具体取决于您的实现。当然,您的实现可能更复杂,但您需要跟踪事件处理。 Java 使用组件层次结构数据结构来处理各种 GUI 事件,您可以在此处了解更多信息 http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html
You need to design something to handle the event dispatch in your program. You seem to have components that have their listeners all disorganized. You could build a tree data structure (https://en.wikipedia.org/wiki/Tree_%28data_structure%29) that is a hierarchy for the event dispatch in your components ( such as buttons, text areas etc.). The idea is that when the tree is traversed the events will be handled in an ordered fashion. The tree would be reorganized based on how the user interacts with your program. For a simple example, to start this tree could perhaps prioritize the most recently drawn component (out of some structure that holds a list of everything to be drawn) as the event listener to receive event handling first. Then, if a component is blocked by another component the blocked component (like a button covering the button) it's event handling could either be disabled or scheduled to happen later depending on your implementation. Of course your implementation may be more complex, but you need to keep track the event handling. Java uses a component heirarchy data structure to handle a wide variety of GUI events that you can learn more about here http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html