• 沒有找到結果。

The application requirements for the user interface include dragging, that is, mouse down, mouse move and mouse up, for re-positioning items and double clicking for producing a duplicate copy of an item. I decided to use buttons for the other end-user actions: removing an item from the canvas and creating an image to be saved. The button action is straight-forward. I write two instances of the HTML5 button element with the onClick attributes set to the appropriate function.

<button onClick="saveasimage();">Open window with image (which you can save into image file)

</button></br>

<button onClick="removeobj();">Remove last object moved </button>

The saveasimage function will be explained in the next section. The removeobj function deletes the last moved object from the stuff array. The last moved object is the last one in the array. This makes the coding extremely simple:

function removeobj() { stuff.pop();

drawstuff();

}

A pop for any array deletes the last element. The function then invokes the drawstuff function to display all but the last element. By the way, if the button is clicked at the start of the application, the last element pushed on the stuff array will be deleted. If this is unacceptable, you can add a check to prevent this from happening. The cost is that it needs to be done every time the user clicks on the button.

Fortunately, HTML5 provides the mouse events that we need for this application. In the init function, I include the following lines:

canvas1 = document.getElementById('canvas');

canvas1.onmousedown = function () { return false; };

canvas1.addEventListener('dblclick',makenewitem,false);

canvas1.addEventListener('mousedown',startdragging,false);

The first statement sets the canvas1 variable to reference the canvas element. The second statement is necessary to turn off the default action for the cursor. I also included a style directive for the canvas, which made the positioning absolute and then positioned the canvas 80 pixels from the top. This is ample space for the directions and the buttons.

canvas {position:absolute; top:80px;

cursor:crosshair;

}

The third and fourth statements set up event handling for double click and mouse button down events. We should appreciate the fact that we as programmers do not have to write code to distinguish mouse down, click and double click.

clicked on. You probably have seen the mouse cursor coordinate code before, in the Essential Guide to HTML5, for example. The looping through the array is done in reverse order. Calls are made to the overcheck method, defined appropriately for the different types of objects. If there is a hit, then the makenewitem function calls the clone function to make a copy of that item. The code modifies the x and y slightly so the new item is not directly on top of the original. The new item is added to the array and there is a break to leave the for loop.

function makenewitem(ev) {

As I indicated earlier, the clone function makes a copy of an element in the stuff array. You may ask, why not just write

item = stuff[i];

The answer is that this assignment does not create a new, distinct value. JavaScript merely sets the item variable to point to the same thing as the ith member of stuff. This is called ‘copy by reference’. We don’t want that. We want a brand new, separate thing that we can change. The way to copy is

demonstrated in the clone function. A new object is created and then a for-loop is invoked. The for(var info in obj) says: for every attribute of obj, set an equivalently named attribute in item to the value of the attribute.

So the effect of the two functions is to duplicate whatever element is under the mouse cursor. You or your end-user can then mouse down on the original or the cloned object and move it around.

The startdragged function proceeds as indicated to determine what object was under the mouse.

The code then determines what I (and others) call the offsets in x and y of the mouse coordinates versus the x, y position of the object. This is because we want the object to move around maintaining the same relationship between object and mouse. Some folks call this the flypaper effect. It is as if the mouse cursor came down on the object and stuck like flypaper. The offsetx and offsety are global variables.

Note that the coding works for objects for which the x, y values refer to the upper left corner (pictures and rectangles), to the center (ovals) and to a specific internal point (hearts).

The coding then performs a series of operations that has the effect of moving this object to the end of the array. The first statement is a copy by reference operation to set the variable item. The next step saves the index for the last element of the stuff array to the global variable thingInMotion. This variable will be used by the function moveit. The splice statement removes the original element and the push statement adds it to the array at the end. The statement referencing cursor is the way to specify a cursor.

The “pointer” refers to one of the built-in options. The last two statements in the function set up the event handling for moving the mouse and releasing the button on the mouse. This event handling will be removed in the dropit function.

function startdragging(ev) {

The moveit function moves the object referenced by thingInMotion and uses the offsetx and offsety variables to move the object. The drawstuff function is invoked to show the modified canvas.

var my;

stuff[thingInMotion].x = mx-offsetx; //adjust for flypaper dragging stuff[thingInMotion].y = my-offsety;

drawstuff();

}

A mousemove event is triggered if the mouse moves a single pixel in any direction. If this seems too much, remember that the computer does it, not you or I. The user gets a smooth response to moving the mouse.

The dropit function is invoked at a mouseup event. The response is to remove, stop the listening for moving and releasing the mouse and then changing the cursor back to the crosshairs.

function dropit(ev) {

canvas1.removeEventListener('mousemove',moveit,false);

canvas1.removeEventListener('mouseup',dropit,false);

canvas1.style.cursor = "crosshair"; //change back to crosshair }

To summarize, the user interface for this application involves two buttons and two types of mouse actions. The drag and drop operation is implemented using a set of functions.