在 Web 浏览器中创建可点击的网格
我想在 HTML5 画布上绘制 10 x 10 正方形的网格,并在正方形上显示数字 1-100。单击方块应调用 JavaScript 函数,并将方块的数字作为变量传递给函数。
I want to draw a grid of 10 x 10 squares on a HTML5 canvas with number 1-100 displayed on the squares. Clicking a square should call a JavaScript function with the square's number passed as a variable to the function.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,我鼓励您阅读涉及 HTML5 Canvas 的另一个问题的此答案。你需要明白没有正方形。为了检测“正方形”上的单击,您必须跟踪从每个画布坐标到它逻辑上包含的正方形的映射,处理整个画布上的单个单击事件,计算出哪个正方形(s) 您想要更改,然后根据您想要的更改重新绘制画布。
然后,既然您似乎不反对使用更合适的技术,我鼓励您在任一 HTML 中执行此操作(其中每个“方块”类似于
,这绝对是-使用 CSS 定位、调整大小和颜色)或 SVG(如果您需要能够旋转的正方形,或者想要引入其他形状,则使用
)。HTML 和 SVG 都是“保留模式”图形模式系统,其中绘制形状会“保留”该形状的概念。您可以移动形状、更改其颜色、大小等,计算机将自动为您重新绘制它。此外,对于您的用例来说更重要的是,您可以(使用 HTML 和 SVG):
编辑:我用 JavaScript 和 HTML 创建了一个简单的实现:http://jsfiddle.net/6qkdP/2/
这是核心代码,以防 JSFiddle 宕机:
First, I encourage you to read this answer to another question involving the HTML5 Canvas. You need to understand that there are no squares. In order to detect a click on a 'square', you would have to keep track of a mapping from each canvas coordinate to the square(s) that it logically contains, handle a single click event on the entire canvas, work out which square(s) you want to change, and then redraw the canvas with the changes you want.
Then—since you seem to have no objection to using a more appropriate technology—I encourage you to do this in either HTML (where each 'square' is something like a
<div>
that is absolutely-positioned and sized and colored using CSS), or SVG (using<rect>
if you need the squares to be able to be rotated, or want to introduce other shapes).HTML and SVG are both 'retained-mode' graphics mode systems, where drawing a shape 'retains' the concept of that shape. You can move the shape, change its colors, size, etc. and the computer will automatically redraw it for you. Moreover, and more importantly for your use case, you can (with both HTML and SVG):
Edit: I've created a simple implementation in JavaScript and HTML: http://jsfiddle.net/6qkdP/2/
Here's the core code, in case JSFiddle is down:
使用 HTML 元素而不是在画布上绘制这些内容或使用 SVG 是另一种选择,而且很可能更可取。
遵循 Phrogz 的建议,请参阅此处了解 SVG 实现:
jsfiddle 示例
Using HTML elements rather than drawing these things on a canvas or using SVG is another option and quite possibly preferable.
Following up on Phrogz's suggestions, see here for an SVG implementation:
jsfiddle example
正如接受的答案所示,如果这就是您的全部设计,那么在 HTML/CSS 中执行此操作是最简单的,但这里有一个使用的示例对于那些使用 canvas 的用例可能更有意义的人来说,canvas 是一种替代方案(并且与 HTML/CSS 并置)。
问题的第一步归结为找出用户鼠标在画布中的位置,这需要知道画布元素的偏移量。这与查找元素中的鼠标位置相同,因此在这方面canvas确实没有什么独特之处。我正在使用 event.offsetX/Y 来执行此操作。
在画布上绘制网格相当于行和列的嵌套循环。使用
tileSize
变量来控制步数。基本数学可让您根据宽度和高度以及行和列值找出鼠标所在的图块(坐标和/或单元格编号)。使用context.fill...
方法写入文本和绘制正方形。为了保持理智,我将所有内容保留为 0 索引,但您可以将其标准化为显示前的最后一步(不过,不要在逻辑中混合 1 索引)。最后,将 事件监听器 添加到 canvas 元素以检测鼠标操作,这将触发鼠标位置和所选图块的重新计算以及画布的重新渲染。我将大部分逻辑附加到 mousemove,因为它更容易可视化,但如果您选择,相同的代码也适用于单击事件。
请记住,以下方法并不是特别注重性能;我仅在光标在单元格之间移动时重新渲染,但部分重新绘制或移动覆盖层以指示突出显示的元素会更快(如果可用)。我忽略了很多微观优化。将此视为概念验证。
As the accepted answer shows, doing this in HTML/CSS is easiest if this is all your design amounts to, but here's an example using canvas as an alternative for folks whose use case might make more sense in canvas (and to juxtapose against HTML/CSS).
The first step of the problem boils down to figuring out where in the canvas the user's mouse is, and that requires knowing the offset of the canvas element. This is the same as finding the mouse position in an element, so there's really nothing unique to canvas here in this respect. I'm using
event.offsetX/Y
to do this.Drawing a grid on canvas amounts to a nested loop for rows and columns. Use a
tileSize
variable to control the step amount. Basic math lets you figure out which tile (coordinates and/or cell number) your mouse is in based on the width and height and row and column values. Usecontext.fill...
methods to write text and draw squares. I've kept everything 0-indexed for sanity, but you can normalize this as a final step before display (don't mix 1-indexing in your logic, though).Finally, add event listeners to the canvas element to detect mouse actions which will trigger re-computations of the mouse position and selected tile and re-renders of the canvas. I attached most of the logic to mousemove because it's easier to visualize, but the same code applies to click events if you choose.
Keep in mind that the below approach is not particularly performance-conscious; I only re-render when the cursor moves between cells, but partial re-drawing or moving an overlay to indicate the highlighted element would be faster (if available). There are a lot of micro-optimizations I've ignored. Consider this a proof-of-concept.