Hovering over a set of elements in Raphaeljs

I have a set that only contains a rectangle.

var hoverTrigger = this.paper.set();
var outline = this.paper.rect();

Upon hover, the rectangle is supposed to expand, and some links are added to it, and upon mouse off, the links disappear and the rectangle becomes small again.

hoverTrigger.hover(function () {
  var link = this.paper.text();
}, function() {

However, it seems like the hover function is being applied to each item in the set individually, and not the whole set, because when you go to mouse over a link, the hover off function fires and the link disappears. Sometimes the box gets hover on and hover off events in quick succession and spazzes.

Is there a way to apply a hover to a set of things, so that mousing between two things in the set doesn't trigger hover off?



Having faced this limitation myself recently, I decided to write a small extension to Raphael called hoverInBounds that resolves it.

Simply, once the mouse enters the element we keep track of when it actually moves outside its bounds - executing the hover out function then, not before.

Demo: http://jsfiddle.net/amustill/Bh276/1

Raphael.el.hoverInBounds = function(inFunc, outFunc) {
    var inBounds = false;

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

    // 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;

    return this;

Place the above block of code before you create your Raphael paper object.


I hit on this problem before. I found 2 solutions.

Create a rectangle over other elements with opacity set to 0

var paper = new Raphael( 0, 0, 100, 100 );
var rect = paper.rect( 0, 0, 100, 100 ).attr({ opacity: 0 });
rect.hover( func_in, func_out );

This only works for elements that have 1 overall action like click.

The other option is to cancel the hover function when hovering over a set of elements

var funcOutTimer;

set.hover( function( ) {
    if( funcOutTimer ) { // Hovered into this element in less than 100 milliseconds => cancel
        window.clearTimeout( funcOutTimer);
    } else {
    // do stuff
function( ) {
    funcOutTimer = setTimeout( function( ) {
        // do stuff
    }, 100 ); // wait for 100 milliseconds before executing hover out function

Basically the hover in function is only executed when first entering a set of elements for the first time and the hover out function will only execute once when finally the element you have hovered into is not part of that set.


I found that this works with the following

myCircleElement.hover (
    function(e) { myTextElement.animate({opacity:1}, 800); },
    function(e) {
        var x = e.layerX || e.x,
        y = e.layerY || e.y;
        // Return `false` if we're still inside the element's bounds                                        
        if (this.isPointInside(x, y)) return false;
        // otherwise do something here.. eg below
        myTextElement.animate({opacity:0}, 800); //

The method Bruno details have this minor issue:

If you create a rectangle over the other elements, if the other elements are text then those texts can't be selected in the web page. But it works.

By the way the attribute "opacity": 0 is not enough, I had to add the "fill": "white" attribute in my case.

You need to bring the object to the front like this: obj.toFront(); obj is a raphael shape like "rect", etc.

I tested it on a mouseover and mouseout event and it works.

Check my fiddle here: link to fiddle

function withArray(x,y){
    var rect = paper.rect(x, y, 100, 60).attr({
        fill: "green"
    rect.text = paper.text(x+(100/2), y + 30, 'rect w/array').attr({
        'font-size': 12,
        "fill": "white"
    var rectover = paper.rect(x,y,100,60).attr({
        fill: "white",
        opacity: 0
    var myArray = paper.set();
    myArray.push(rect, rect.text, rectover);
    myArray.mouseover(function() {
    var anim = Raphael.animation({
    transform: ['S', 1.5, 1.5, (rect.attr("x")), (rect.attr("y"))]
        }, 100, "backOut", function() {
    }).mouseout(function() {
        var anim = Raphael.animation({
            transform: [""]
        }, 50, "backOut", function() {


Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.