0
votes

I have created a series of buttons with Raphael that uses a special hover function I borrowed here (see first solution), it basically tells the hover to keep 'hovering' where ever I am inside the circle, regardless of whether my cursor is either on text or the circle. I have used it as shown in this jsfiddle - the hover function can be found in the most top part of the code and is activated right at the bottom of the code. However, whenever I surround the Raphael canvas with any other div that contains the following:

  • css margins and padding
  • content in div

The special hover function stops working, as shown here. What happens is that my circle buttons revert back to the pre-hover state whenever my cursor goes onto the text part in the middle of the circle. I've realized if I put the Raphael canvas above all the other other divs in the html code, it will work or if I remove all content and styling, it'll work. I can't really do either option. I figured the fault might have something to do with this:

Raphael.el.hoverInBounds = function (inFunc, outFunc) {

    var inBounds = false;

    // Mouseover function. Only execute if `inBounds` is false.
    this.mouseover(function () {
        if (!inBounds) {
            inBounds = true;
            inFunc.call(this);
        }
    });

    // Mouseout function
    this.mouseout(function (e) {
        var x = e.offsetX || e.clientX,
            y = e.offsetY || e.clientY;

        // Return `false` if we're still inside the element's bounds
        if (this.isPointInside(x, y)) return false;

        inBounds = false;
        outFunc.call(this);
    });

    return this;
}

The 'clientX, clientY' part to be exact - after doing some research it seems to me that maybe the function is doing calculations involving the whole page and having content and margin/paddings cause a miscalculation or no calculation at all. I could be wrong. I'm only a beginner at Javascript/Raphael. My questions are: what is causing my hover function to not work properly, and is there any solution/workaround? Thankyou.

1

1 Answers

0
votes

I can't think of a simple answer, so this is a bit fiddly, but may work. Note, I don't think this works in Opera, but I think it may just be a case for checking for how its handling the event coordinate (clientX or layerX etc).

text { pointer-events: none; }

Will turn off events for the text object. This will then allow the svg shape to take all of the events, otherwise it conflicts.

As you now really need events still, you could add an extra mousemove handler over the element, and then check if its within the bounding area of the text itself.

You will need to do some tweaking to make it feel right, maybe adjust the area checked by a few pixels to be larger than the bounding box.

this.mousemove( function(e) {
        var x = e.layerX || e.offsetX || e.clientX,
            y = e.layerY || e.offsetY || e.clientY;
        var bb = this.text.getBBox();
        if( (x >= bb.x) && (x <= bb.x + bb.width) && (y>=bb.y) && (y<=bb.y+bb.height) ) {
            label.attr("text", this.text.attr("href"));
        } else {
            label.attr({
               text: "Mouse over on circles for file name"
            });
        };
    });

Note, I don't particularly like the UI, I think what you want to do is non-intuitive, to have one animated object on an event, and a separate event on a separate area that isn't based on that animation inside. It feels wrong, but it may go some way to finding the correct solution.

jsfiddle