Jump to content
Search Community

clearProps of Timeline

SigSam test
Moderator Tag

Go to solution Solved by Diaco,

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 wanting to be able to destroy a timeline (based on resizing). When i destroy the timeline, i want to remove all of it's initial set-up CSS.

Here is how a timeline is set-up:

var scene = new TimelineLite();
 
    scene
      .add("start", 0);
 
    scene
      .from(panel, 20, {
        opacity: 0
      }, "start")
      .from(panelText, 20, {
        y: "+=60px"
      }, "start")
      .from(background, 20, {
        scale: "1.15"
      }, "start")
 
With this, the panel is set to Opacity 0 initially. 
I have timelines within timelines as each panel (17 of them) animate in various combinations.
I don't want the timeline active on mobile so i can disable it, but is there a method like clearProps for removing all CSS generated by all the timelines? Or must this be done outside of GSAP?
 
The codepen attached (i got from the closest post i could find relating to this issue) demonstrates it resetting to the start, but the elements still have their CSS properties.

See the Pen LKdqk by GreenSock (@GreenSock) on CodePen

Link to comment
Share on other sites

Hi SigSam,

 

but is there a method like clearProps for removing all CSS generated by all the timelines?

 

There is not an API method that loops through all children of a Timeline, finds their targets (objects that were tweened) and does a clearProps on them. 

However the API has enough hooks so that you could write something that does that. To start down that route, check out the getChildren() method:  http://greensock.com/docs/#/HTML5/GSAP/TimelineLite/getChildren/

 

Another option would be to track the targets of your tweens yourself in an Array or make use of your DOM structure and advanced string selectors to find the elements that need to be cleared. Perhaps just find all child elements of a particular element and clear them all.

  • Like 3
Link to comment
Share on other sites

Here's a function that will return a unique list of all the elements in a timeline.

 

function getTargets(timeline) {

  function addTargets(list, target) {

    if (Array.isArray(target)) target.forEach(checkTarget);
    else if (target.nodeType === 1) list.push(target);
    else if (target.jquery) target.each(function() { list.push(this); });

    function checkTarget(el) {
      if (el.jquery) list.push(el[0]);
      else if (el.nodeType === 1) list.push(el);
      else if (typeof el === "string") list.push(document.querySelector(el));
    }
    return list;
  }

  return timeline
    .getChildren(true, true, false)
    .map(function(tween) { return tween.target; })
    .reduce(addTargets, [])
    .filter(function(target, i, list) { return list.indexOf(target) === i; });
}

See the Pen NPyKrM by osublake (@osublake) on CodePen

  • Like 3
Link to comment
Share on other sites

  • Solution

Hi guys :)

 

how about this :

var scene = new TimelineLite();

scene.add("start", 0)
.from("#red", 5, {opacity: 0},"start")
.from("#green", 5, {y: "+=60px"},"start")
.from("#blue", 5, {scale: "1.15"},"start")

$("#kill").click(function() {
    var targets = scene.getChildren();
    scene.kill();
    for (var i=0; i<targets.length; i++) {
      console.log(targets[i].target.selector) // check the console
      TweenMax.set(targets[i].target.selector, {clearProps:"all"});
      /* if you dont use jquery
      console.log(targets[i].target[0].id) 
      TweenMax.set(targets[i].target[0], {clearProps:"all"});
      */    
     };
 });

 

See the Pen RNQwyE by MAW (@MAW) on CodePen

  • Like 4
Link to comment
Share on other sites

Thanks for all of your help. I've been loving GSAP and it's handling of multiple timelines.

 

As i had scenes (timelines) within the main story (timeline), I just had to check in the loop if they weren't null. The final result:

 

var targets = story.getChildren();
story.kill();
for (var i=0; i<targets.length; i++) {
  if (targets[i].target != null) {
     TweenLite.set(targets[i].target, {clearProps:"all"});
  }
}
Link to comment
Share on other sites

  • 5 months later...

Hi guys :)

 

how about this :

var scene = new TimelineLite();

scene.add("start", 0)
.from("#red", 5, {opacity: 0},"start")
.from("#green", 5, {y: "+=60px"},"start")
.from("#blue", 5, {scale: "1.15"},"start")

$("#kill").click(function() {
    var targets = scene.getChildren();
    scene.kill();
    for (var i=0; i<targets.length; i++) {
      console.log(targets[i].target.selector) // check the console
      TweenMax.set(targets[i].target.selector, {clearProps:"all"});
      /* if you dont use jquery
      console.log(targets[i].target[0].id) 
      TweenMax.set(targets[i].target[0], {clearProps:"all"});
      */    
     };
 });

 

See the Pen RNQwyE by MAW (@MAW) on CodePen

 

What about using this function for multiple Timelines at once? I mean clearing properties that are set with multiple Timelines on multiple targets which some of them are common in all Timelines, Could I do this like this? Because I get an error saying "can not tween a null target" !!

function clearProps(scene) {
        var targets = scene.getChildren();
        for (var i = 0; i <= targets.length; i++) {
            TweenMax.set(targets[i].target.selector, {
                clearProps: "all"
            });
        }
}
    
function clearAllProps() {
       
        var timeLines = [firstSwipeRight, secondSwipeRight, directSelect];
        for (var x = 0; x <= timeLines.length; x++) {
            clearProps(timeLines[x]);
        }
}
Link to comment
Share on other sites

Look at the comments Diaco left below his code. If you're not using jQuery, there is no selector property, so that could be your problem. If that's not the issue, make a demo so we can check it out.

 

Or you could try that helper function I made above which will return a unique list of all the elements. The reason I made that is because a timeline target is not always an element, which might be the source of your problem. It could be a jQuery object, a node-list, an element, a string, a function, an array of different things, etc.

 

Check out my demo above. I mixed a bunch of timelines and random things together just to show how it would sort out unique targets.

  • Like 1
Link to comment
Share on other sites

  • 2 years later...

Old topic, but I thought I'd share my lil' enhancement, which helps me quite a lot!

 

EDIT:

Question: Whats the best way to find out if clearProps is already set? I cant get it to work.

`targets[f].vars.css.clearProps produces an error`
`TypeError: undefined is not an object (evaluating 'n[e].vars.css.clearProps')`

 

// EDIT!
// Don't copy yet!
// I still need to find out how to check if clearProps is already set

TimelineMax.prototype.clearProps = function( props, overwrite ) {

	// which props? (default is "all")
	var props = typeof props !== "undefined" ? props : "all";

	// overwrite existing clearProps? (default: true)
	var overwrite = typeof overwrite !== "undefined" ? overwrite : true;

	var targets = this.getChildren();
	if (targets.length > 0) {

		// only onComplete clearProps
		this.eventCallback("onComplete", function() {

			for (var f = 0; f < targets.length; f++) {
              	// targets[f].vars.css.clearProps produces an error
              	// TypeError: undefined is not an object (evaluating 'n[e].vars.css.clearProps')
				if (targets[f]....... CLEARPROPS??? ......) continue;
				TweenMax.set(targets[f].target, { clearProps: props });
			}

		})
	}

	return this;
} 

 

Used like this:

var tl = new TimelineMax()
	tl
		.to(".top-bar", 1, { x: 50 })
		.to(".bottom-bar", 1, { x: 100 })
		.from(".bam", 1, { scale: 2009239 })
		.staggerTo(".things", 15, { rotation: "+=2" })
		.set(".bla", { display: "none" })
		// ...

		// too lazy to write ,  clearProps: "all" aaaall the time?
		.clearProps()
	;

 

 

Or:

var tl = new TimelineMax()
	tl
		.to(".top-bar", 1, { opacity: 0, x: 50 })
		.to(".bottom-bar", 1, { opacity: 0, x: 100 })
		.from(".bam", 1, { opacity: 0, x: 200, scale: 2009239, clearProps: "x" }) // only need x to clear 
		
		.clearProps("opacity", false) // only clear opacity and don't overwrite existing clearProps!  
	;

 

Link to comment
Share on other sites

  • 2 years later...

Hi there,

 

Racking my brains on how to accomplish this with GSAP 3, here's what I have:

 

const killTimeline = (timeline) => {
    const targets = timeline.getChildren();

    targets.forEach(target => {
        console.log(target._targets)

        timeline.set(target._targets, {clearProps: "all"});
    });

    timeline.kill();
};

Trying to clear all properties of a given timeline when user resizes to below tablet width and kill the timeline.

 

Is this best practice? I'm always struggling with responsive destroying & enabling timelines for different viewports.

 

Many thanks in advance.

 

 

  • Thanks 1
Link to comment
Share on other sites

@ainsley_clark We recommend not using any variables with _ before the name. We recommend using .targets() instead:

const killTimeline = (timeline) => {
  const targets = timeline.getChildren();
  
  timeline.kill();
  
  for(let i = 0; i < targets.length; i++) {
    if(targets[i].targets().length) {
       gsap.set(targets[i].targets(), {clearProps:"all"});
    }
  }
};

See the Pen KKwRdWw by GreenSock (@GreenSock) on CodePen

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

  • 1 year later...

HI guys,

 

Im relatively new to GSAP, and so far, so good. But I have a problem that is driving me insane, which I believe is the same issue stated in this thread (but its resolution did not work for me).

 

I have a simple timeline, which changes some SVG styles when the mouse doesn't move for 500ms. If the mouse moves, the timeline is paused, and then restarted again. This all works well, the timeline fires correctly, styles change, and the onComplete code does its thing.

 

My problem: The styles modified by the timeline will not go away, no matter what combinations of the many approaches to clear, kill, clearProps, and everything else I could find. the DOM node for the SVG circle ALWAYS has a style tag with the fill color used in the timeline.  

 

What am I missing? I was hoping this would be simple, so I wouldnt have to put together a codepen :)

Ideally, when the timeline completes, this DOM node should never know GSAP was there - full revert, no sneaky fingers in attributes, nothing. Isnt there a way to properly kill this thing cleanly?

 

thanks

Brent

 

    MouseMoveTimeout(){
        window.clearTimeout(this.moveTimeout);
        this.tl.pause(0);

        this.moveTimeout = window.setTimeout(()=>{
            this.tl.restart();
        }, 500);
    }

 

            this.tl = gsap.timeline({onComplete: () => {
				// tried everything here that i could find in every forum to clear the style attribute
	
                this.lineCreate.x1 = this.snapCircle.x;
                this.lineCreate.y1 = this.snapCircle.y;      
                this.lineCreate.x2 = this.snapCircle.x;
                this.lineCreate.y2 = this.snapCircle.y;
                
            }, paused:true, defaults: { ease: "none" }})
            .to(this.todoCircle, {duration:.5, fill:"#0C00FF", attr:{r:2}})
            .to(this.todoCircle, {duration:.1, fill: "#0FFF00"})
            .to(this.todoCircle, {duration:.1, fill: "#0C00FF"})
            .set(this.todoCircle, {clearProps: "all"}); // this didnt work either

 

 

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...