views:

17

answers:

1

I've got an animation on my canvas where I have some images (drawn using drawImage()). For the sake of simplicity, let's say there's only two images. These images are following a circular path in faux-3d space such that sometimes one image overlaps the other and other times the second image overlaps the first. These images are also scaled as they move "closer" or "further" from the viewer.

Each of these images is an object with the following (simplified) code:

function slide_object() {
    this.x = 0.0; // x = position along path (in radians)
    this.xpos = 0.0; // x position on canvas
    this.ypos = 0.0; // y position on canvas
    this.scale = 0.0;
    this.name = ""; // a string to be displayed when slide is moused over
    this.imgx = 0.0; // width of original image
    this.imgy = 0.0; // height of original image

    this.init = function (abspath, startx, name) { // startx = path offset (in radians)
        this.name = name;
        this.x = (startx % (Math.PI * 2));
        var slide_image = new Image();
        slide_image.src = abspath;
        this.img = slide_image;
        calcObjPositions(0, this); // calculate's the image's position, then draws it
    };
    this.getDims = function () { // called by calcObjPositions when animation is started
        this.imgx = this.img.width / 2;
        this.imgy = this.img.height / 2;
    }
}

Each of these objects is stored in an array called slides.

In order to overlap the images appropriately, the drawObjs function first sorts the slides array in order of slides[i].scale from smallest to largest, then draws the images starting with slides[0].

On $(document).ready() I run an init function that, among other things, adds an event listener to the canvas:

canvas = document.getElementById(canvas_id);
canvas.addEventListener('mousemove', mouse_handler, false);

The purpose of this handler is to determine where the mouse is and whether the mouse is over one of the slides (which will modify a <div> on the page via jQuery).

Here's my problem -- I'm trying to figure out how to determine which slide the mouse is over at any given time. Essentially, I need code to fill in the following logic (most likely in the mouse_handler() function):

// if (mouse is over a slide) {
//     slideName = get .name of moused-over slide;
// } else {
//     slideName = "";
// }
// $("#slideName").html(slideName);

Any thoughts?

A: 

Looks like I just needed some sleep before I could figure this one out.

I've got everything I need to determine the size of the image and it's placement on the canvas.

I added the following function to my slide_object:

    this.getBounds = function () {
        var bounds = new Array();
        bounds[0] = Math.ceil(this.xpos); // xmin
        bounds[1] = bounds[0] + Math.ceil(this.imgx * this.scale); // xmax
        bounds[2] = Math.ceil(this.ypos); // ymin
        bounds[3] = bounds[2] + Math.ceil(this.imgy * this.scale); // ymax
        return bounds;
    };

Then in my mouse_handler function, I get the index of the currently moused-over slide from a function I call isWithinBounds() which takes a mouse x and mouse y position:

function isWithinBounds(mx,my) {
    var index = -1;
    for ( var i in slides ) { 
        bounds = slides[i].getBounds();
        if ((mx >= bounds[0] && mx <= bounds[1]) && (my >= bounds[2] && my <= bounds[3])) {
            index = i;
        }
    }
    return index;
}

Since slides is sorted in order of scale, smallest to largest, each iteration will either replace or preserve the value of index. If there's more than one image occupying a space, the top-most slide's index gets returned.

The only problem now is to figure out how to make the code more efficient. Chrome runs the animation without any lag. Firefox has some and I haven't even thought about implementing excanvas.js yet for IE users. For browsers lacking canvas support, the canvas object is simply hidden with display:none.

Jazzerus