HTML5 Canvas Event Handling---Go

Source: Internet
Author: User

Dom is a very important part of the Web front-end domain, not only when working with HTML elements, but also with the use of the DOM, as well as graphical programming. SVG drawings, for example, are inserted into the page as DOM nodes, which means that the DOM method can be used to manipulate the graph. For example, there is a <path id= "P1" > element that can be added directly with jquery Click event $ (' #p1 '). Click (function () {...}). However, this DOM processing method is no longer applicable in the HTML5 canvas, and canvas uses a different set of mechanisms, no matter how many graphics are drawn on the canvas, the canvas is a whole, and the graph itself is actually part of the canvas, cannot be obtained separately, so it is not possible to add JavaScript events directly to a graph.

Limitations of Canvas

In the canvas, all the graphics are drawn on the frame, and the drawing method does not output the drawing elements as a return value, and JS cannot get the graphical elements that have been drawn. Like what:

    1. CVS = document.getElementById (' MyCanvas '); <?xml:namespace prefix = o ns = "Urn:schemas-microsoft-com:office:office" />
    2. Cvs.addeventlistener (' click ', Function (e) {
    3. //...
    4. }, False);
Copy Code


This code draws a rectangle in the canvas label, and first you see that the Rect method that draws the graph has no return value. If you open the browser's developer tool, you can also see that the canvas tag does not add anything inside, but the canvas element in JS and the current context, there is no content to represent the new graphics.

Therefore, the DOM method used by the front-end is not applicable in canvas. For example, click the rectangle in the canvas above, and the entire canvas element is actually clicked.

Binding events to a canvas element

Since events can only reach the level of the canvas element, it is necessary to add code for processing if you want to go further and identify which graphics inside the canvas the click takes. The basic idea is to bind the event to the canvas element, check the location of the event object when the event occurs, and then check which graphics cover that location. In the example above, a rectangle is drawn that overrides the range of x-axis 10-110 and y-axis 10-110. As long as the mouse click in this range, it can be considered as a click on the rectangle, you can manually trigger the rectangle to handle the click event. The idea is actually relatively simple, but it's a little bit more complicated to implement. Not only will the efficiency of this judging process be considered, but some places also need to re-determine the event type, setting the capture and bubbling mechanism to redefine a canvas's interior.

The first thing to do is to bind the event to the canvas element, such as a drawing inside a canvas to tie a point-click event, you need to proxy the event via the canvas element:

    1. CVS = document.getElementById (' MyCanvas '); <?xml:namespace prefix = o ns = "Urn:schemas-microsoft-com:office:office" />
    2. CTX = Canvas.getcontext (' 2d ');
    3. Therect = Ctx.rect (10, 10, 100, 100);
    4. Ctx.stroke ();
    5. Console.log (Therect); Undefined
Copy Code

Next you need to determine where the event object occurs, and the Layerx and Layery properties of the event object e represent coordinates in the canvas's internal coordinate system. But this property opera does not support, Safari is also intended to remove, so to do some compatible wording:

    1. function geteventposition (EV) {
    2. var x, y;
    3. if (Ev.layerx | | ev.layerx = = 0) {
    4. x = Ev.layerx;
    5. y = ev.layery;
    6. } else if (Ev.offsetx | | ev.offsetx = = 0) {//Opera
    7. x = Ev.offsetx;
    8. y = ev.offsety;
    9. }
    10. return {x:x, y:y};
    11. }
    12. Note: Using the above function, you need to set the position of the canvas element to absolute.
Copy Code


Now that you have the coordinates of the event object, here's what you want to know about the graphics in the canvas and what the coordinates are.

Ispointinpath method

The Ispointinpath method of the canvas determines whether a graphic in the current context overrides a coordinate, such as:

    1. CVS = document.getElementById (' MyCanvas ');
    2. CTX = Canvas.getcontext (' 2d ');
    3. Ctx.rect (10, 10, 100, 100);
    4. Ctx.stroke ();
    5. Ctx.ispointinpath (50, 50); True
    6. Ctx.ispointinpath (5, 5); False
Copy Code


Next, add an event to determine whether a click event occurred on the rectangle:

    1. Cvs.addeventlistener (' click ', Function (e) {
    2. p = geteventposition (e);
    3. if (Ctx.ispointinpath (p.x, p.y)) {
    4. Clicked on the rectangle
    5. }
    6. }, False);
Copy Code


The above is the basic method of handling the canvas event, but the above code is still limited, because the Ispointinpath method only determines the path in the current context, so when more than one drawing is drawn in the canvas, the event can only be judged in the context of the last graphic, such as:

    1. CVS = document.getElementById (' MyCanvas ');
    2. CTX = Canvas.getcontext (' 2d ');
    3. Ctx.beginpath ();
    4. Ctx.rect (10, 10, 100, 100);
    5. Ctx.stroke ();
    6. Ctx.ispointinpath (20, 20); True
    7. Ctx.beginpath ();
    8. Ctx.rect (110, 110, 100, 100);
    9. Ctx.stroke ();
    10. Ctx.ispointinpath (150, 150); True
    11. Ctx.ispointinpath (20, 20); False
Copy Code


As you can see from the above code, the Ispointinpath method can only identify the graphics path in the current context, and the previously drawn path cannot be traced back. The solution to this problem is to redraw all graphics when a Click event occurs, using the Ispointinpath method for each drawing, to determine if the event coordinates are within the scope of the graph.


Cyclic redraw and event bubbling


In order to achieve cyclic redrawing, it is necessary to save the basic parameters of the graph in advance:

    1. arr = [
    2. {x:10, y:10, width:100, height:100},
    3. {x:110, y:110, width:100, height:100}
    4. ];
    5. CVS = document.getElementById (' MyCanvas ');
    6. CTX = Canvas.getcontext (' 2d ');
    7. Draw ();
    8. function Draw () {
    9. Ctx.clearrech (0, 0, cvs.width, cvs.height);
    10. Arr.foreach (function (v) {
    11. Ctx.beginpath ();
    12. Ctx.rect (v.x, V.y, V.width, v.height);
    13. Ctx.stroke ();
    14. });
    15. }
Copy Code


The code of the polygon is saved in advance with the basic parameters of the two rectangles, and each time the draw method is called, these basic parameters are called and used to draw two rectangles. The Clearrect method is also used to empty the canvas when redrawing. The next thing to do is to increase the event proxy and use the Ispointinpath method for each context when redrawing:

    1. Cvs.addeventlistener (' click ', Function (e) {
    2. p = geteventposition (e);
    3. Draw (P);
    4. }, False);
Copy Code

When an event occurs, the coordinates of the event object are passed to the draw method for processing. Here are some minor changes to the Draw method:

    1. function Draw (p) {
    2. var who = [];
    3. Ctx.clearrech (0, 0, cvs.width, cvs.height);
    4. Arr.foreach (function (v, i) {
    5. Ctx.beginpath ();
    6. Ctx.rect (v.x, V.y, V.width, v.height);
    7. Ctx.stroke ();
    8. if (P && ctx.ispointinpath (p.x, p.y)) {
    9. If the event coordinates are passed in, use Ispointinpath to determine
    10. If the current environment overrides this coordinate, the index value of the current environment is placed in the array
    11. Who.push (i);
    12. }
    13. });
    14. Depending on the index value in the array, the corresponding element can be found in the ARR array.
    15. return to WHO;
    16. }
Copy Code


In the above code, when the Click event occurs, the Draw method performs a redraw and checks to see if each shape overwrites the event coordinates during the redraw process, and if it is true, it is treated as a click on the graph and puts the index value of the graph into the array, and the array as the return value of the Draw method. In this processing mechanism, if there are n graphs in the canvas, they are partially overlapping, and the Click event happens on this overlapping area, then there will be N members in the return array of the draw method. This is a bit like event bubbling, where the last member of the array is at the top of the canvas, while the first member is at the bottom, and we can treat the topmost member as E.target, while the other member is the node that is passed to during the bubbling process. This is, of course, the simplest way to do this, and if you really want to simulate DOM processing, set up a parent-child relationship for the graph.

These are the basic methods of handling the canvas event. In the actual application, how to cache the graphics parameters, how to cycle redraw, and how to handle event bubbling, you also need to take some thought to deal with the actual situation. In addition, click is a relatively good event to handle, the relative trouble is mouseover, Mouseout and MouseMove these events, because once the mouse into the canvas element, always occurs is the MouseMove event, So if you want to set a single mouseover or mouseout for a graphic, you also need to record the path of the mouse movement and set the entry and exit status for the graphic. Due to the complexity of the processing steps, you must be more concerned about performance issues.

Original link: http://www.xyhtml5.com/

HTML5 Canvas Event Handling---Go

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.