Jump to content
Search Community

Adding JavaScript Event Listeners to SVG objects

Gary Horsman test
Moderator Tag

Go to solution Solved by Jonathan,

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

I'm able to animate two SVGs, each with a class of 'widget', upon loading the page. But when I add event listeners for mouse events to animate them on rollover, nothing happens when I mouse over or out of the SVG objects.

 

Do SVGs have to be treated differently than other images for the event listeners to work?

Link to comment
Share on other sites

Hello Gary Horsman, And Welcome to the GreenSock Forums!

 

You don't have to do anything special for SVG.

 

Working example:

See the Pen BeHqb by jonathan (@jonathan) on CodePen

 

Whats happening is since you are trying to bind the event handler on more than one element you need to add your events through a for loop. Since widget will return an Array, since you are targeting a class (with multiple elements). When you console out your widget variable the output looks like this in the console:

HTMLCollection[img#imgWidgetEmail.widget ghd_widget_email.svg, img#imgWidgetPortfolio.widget ghd_widge...olio.svg]

Using a for loop to iterate over class elements array:

// JavaScript Document
window.onload = function(){
    //put all your GSAP and timelines here
	
	//establish the variables or elements that you want to animate
	var widget = document.getElementsByClassName("widget");
        // outputs array collection
        // console.log(widget);
	
	//set up the timeline for the animation
	var tl = new TimelineMax();
	
	//animation instructions for the type and widget buttons
	tl.from(widget, 1, {scale:0.25, opacity:0, ease:Bounce.easeOut});
	
	//rollovers for widget buttons
        for (i = 0; i < widget.length; i++) {
            widget[i].addEventListener("mouseover", function() {
	             tl.to(this, 0.5, {scale:1.15, ease:Elastic.easeInOut});
            }, false);
            widget[i].addEventListener("mouseout", function() {
	             tl.to(this, 0.5, {scale:1});
            }, false);
        }
}

Also since scaleX and scaleY are the same value to animate, then you can just use scale.

 

You could also opt for using jQuery to take advantage of fast cross browser event binding and it's selector engine.

 

Does that help? :)

Link to comment
Share on other sites

Thanks for the quick response.

 

That works great! (Though I would have never figured that out on my own—my JavaScript is still very remedial.)

 

If I had used unique ID's for each button, that would be a workaround. But I'd still have to add event listeners to each ID, which means more code, right?

 

But this makes sense for when I want to apply the same two event handlers to, say, each of 10 buttons on one page, as long as they all belonged to the same class. Then this would be an efficient way to pass those to each element in the array defined by that class.

 

(So much to learn.)

 

Does jQuery have to be loaded in a page for me to use it as the selector engine, or can I just have GSAP loaded on its own?

Link to comment
Share on other sites

  • Solution

No worries. .. jQuery would have to be loaded on the page to take advantage of fast cross browser event binding.

 

GSAP allows you to select all kinds of selectors regardless of having jQuery loaded. But if you don't need jQuery, then just using the simple for loop to iterate through your buttons with the same class is perfectly acceptable just using native javascript. ;)

 

To make your code cross browser so it accepts older versions of IE that don't support addEventListener, and use attachEvent instead:

window.onload = function(){
//put all your GSAP and timelines here
    
    //establish the variables or elements that you want to animate
    var widget = document.getElementsByClassName("widget");
// outputs array collection
    // console.log(widget);
    
    //set up the timeline for the animation
    var tl = new TimelineMax();
    
    //animation instructions for the type and widget buttons
    tl.from(widget, 1, {scale:0.25, opacity:0, ease:Bounce.easeOut});
    
    //rollovers for widget buttons
    for (i = 0; i < widget.length; i++) {
        // check for support of addEventListener
        if (window.addEventListener) {
           widget[i].addEventListener("mouseover", function() {
              tl.to(this, 0.5, {scale:1.15, ease:Elastic.easeInOut});
           }, false);
           widget[i].addEventListener("mouseout", function() {
              tl.to(this, 0.5, {scale:1});
           }, false);
        } else {
           widget[i].attachEvent("mouseover", function() {
               tl.to(this, 0.5, {scale:1.15, ease:Elastic.easeInOut});
           }, false);
           widget[i].attachEvent("mouseout", function() {
               tl.to(this, 0.5, {scale:1});
           }, false);
        }
}
}

Here are some links to GSAP Docs to help you get familiar with GSAP.: 

:)

Link to comment
Share on other sites

Yes, I saw somewhere something about the attachEvent method for old IE. Good fallback.

 

I find it interesting that you can animate all elements in an array with one line of code, but you have to run each one separately through a loop to attach a listener. There's probably some hidden logic to that.

 

Thanks, Jonathan. You're a lifesaver.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...