How can I animate the fill of a path with Raphaël.js?

1k views Asked by At

I am trying to use the hoverIntent.js with Raphaël.js at This Demo to handle the handlerIn function not immediately and waits until the user's mouse slows down enough before making the call of any function( like Hover) but I am getting this error:

Uncaught TypeError: Failed to execute 'animate' on 'Element': The provided value is not of type '(AnimationEffect or sequence<Dictionary>)'

enter image description here

Can you please let me know why this is happening? and does Raphaël.js has any built in function to do the same job?

2

There are 2 answers

3
Ian On BEST ANSWER

Raphael has an animate function, so this should work if set correctly. The problem is 'this' will not be referring to a Raphael element, it will refer to a JQuery element, so we need to change this.

We can do this with javascripts .bind() method, so here is an example how it would look if we wanted to apply it to every element (you can get rid of the loop if you only want to add it to a single element).

This is the key bit (just look at the middle line, ie the function bind bit)..this means the Raphael element "boxes[el]" will be passed into 'this'.

Object.keys( boxes ).forEach( function( el ) {
    $( boxes[ el ].node ).hoverIntent( hoverFunc.bind( boxes[ el ] ) );
} );

So the whole lot could look like this...


   var Draw = Raphael("canvas", 200, 200);
    var boxes = {
        BC: Draw.path("M50 50, L50,60, L60,60 L60,50 L50,50").attr({
            fill: "#000"
        }),

        ON: Draw.path("M70 70, L70,80, L80,80 L80,70 L70,70").attr({
            fill: "#000"
        }),
        NB: Draw.path("M90 90, L90,100, L100,100 L100,90 L90,90").attr({
            fill: "#000"
        })
    }

    function hoverFunc() {
        this.animate({
            "fill": "#F38A03"
        }, 500);
    }

    Object.keys( boxes ).forEach( function( el ) {
        $( boxes[ el ].node ).hoverIntent( hoverFunc.bind( boxes[ el ] ) );
    } );    

jsfiddle

jsfiddle with hover out

3
Cymen On

The issue is you are trying to call .animate on a path. You can easy debug problems like this by toggling on 'catch uncaught exceptions' in the Google Chrome debugger and then you can interact with the JavaScript including the state (so you can access this on the console and see what it is set to and try setting properties on it).

To get the .animate property, you need to wrap the node in a jQuery call so something like $(this).animate(...) however jQuery doesn't appear to be able to animate SVG. So you need to figure out another way to do it.

Here is an example that works without the .animate: http://jsfiddle.net/h4nBx/13/

When working with SVG, it is time to go beyond jQuery because it is not going to be very helpful (in my experience). A good place to start is reading the standard:

SVG 1.1 Animation: http://www.w3.org/TR/SVG/animate.html

Based on that, you could try adding an animate tag inside of the path element:

<animate attributeType="CSS" attributeName="fill" 
         from="???" to="#F38A03" dur="5s" />

Inside of the path tag as seen here with it inside of a rect tag.

However, I suspect that might not work. I would instead look at adding a class to the path and using CSS to do the animation via that class. See examples of that here.