Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
vadbiz

Text Twitching TweenMax Bug

Go to solution Solved by GreenSock,

Recommended Posts

Good afternoon, colleagues!
Please tell me, in the solution below, for some reason, sometimes there is a "twitching" of the line that moves.

Moreover, in my project - it sometimes "jerks" (as if it starts anew every time, and does not continue) - uploaded to codepen.io - everything works stably, nothing jumps.

With what it can be connected?
How to make the RIGHT implementation?

Sincerely.

See the Pen XWNJaeK by alexverb_msk (@alexverb_msk) on CodePen

Link to comment
Share on other sites

Are you saying that the CodePen works perfectly, but when you run the same code elsewhere it's glitchy? It's super difficult to troubleshoot when we can't see the issue :(

 

If you've got it on a page where there are a lot of other things animating, perhaps the browser is having a hard time keeping up with the painting (graphics rendering). That's unrelated to GSAP. It's always best to keep the number of pixels that change on the screen to a minimum. 

 

When I look at your codepen, the "Development" line seems fine, but the "Design" line below it is sorta popping into existence and repeating. Is that intentional? 

Link to comment
Share on other sites

1 hour ago, GreenSock said:

Are you saying that the CodePen works perfectly, but when you run the same code elsewhere it's glitchy? It's super difficult to troubleshoot when we can't see the issue :(

 

If you've got it on a page where there are a lot of other things animating, perhaps the browser is having a hard time keeping up with the painting (graphics rendering). That's unrelated to GSAP. It's always best to keep the number of pixels that change on the screen to a minimum. 

 

When I look at your codepen, the "Development" line seems fine, but the "Design" line below it is sorta popping into existence and repeating. Is that intentional? 

Please tell me a similar implementation with functions:
1) it is obligatory to repeat the same word.
2) to be able to change the speed from the data tag.
3) to be able to change direction.
4) so that the line also moves "continuously".

Perhaps by changing the code and solution - everything will work fine.
All other animation except the creeping line - everything works well on the page.

 

Perhaps the syntax is deprecated?

Link to comment
Share on other sites

This is what happens to me:

 

Link to comment
Share on other sites

The issue is logical: You're appending words to the element in both cases but when it's going to the right you're not shifting the start position to the left to compensate. You should do that.

 

Additionally we highly recommend upgrading to GSAP 3 syntax. Upgrading is easy!

  • Like 1
Link to comment
Share on other sites

  • Solution
On 2/1/2021 at 12:16 AM, vadbiz said:

Please tell me a similar implementation with functions:
1) it is obligatory to repeat the same word.
2) to be able to change the speed from the data tag.
3) to be able to change direction.
4) so that the line also moves "continuously".

Perhaps by changing the code and solution - everything will work fine.

We've had several people ask about this type of effect, so I just built a GSAP effect that makes this a lot simpler for you (or anyone). Here's a fork of your original CodePen with it in place: 

See the Pen oNYXzYB?editors=0010 by GreenSock (@GreenSock) on CodePen

 

So you can just paste that gsap.registerEffect(...) code into your project, and then it's super simple to make anything have that effect:

gsap.effects.ticker(".hero__ticker-init"); 

That's it!

 

You can control the speed and direction with attributes like:

<div data-speed="8" data-direction="right"></div>

I noticed a problem with your original implementation - if the screen was resized, it didn't adjust, so there could be gaps that showed up. The effect here automatically listens for "resize" events on the window, and dynamically adjusts. Seems to work relatively well. I haven't done tons of testing on this, but hopefully it's at least a good starting point for you. 

 

Here's the raw effect (you don't really have to understand it all to use it): 

gsap.registerEffect({
	name: "ticker",
	effect(targets, config) {
		buildTickers({
			targets: targets,
			clone: config.clone || (el => {
				let clone = el.children[0].cloneNode(true);
				el.insertBefore(clone, el.children[0]);
				return clone;
			})
		});
		function buildTickers(config, originals) {
			let tickers;
			if (originals && originals.clones) { // on window resizes, we should delete the old clones and reset the widths
				originals.clones.forEach(el => el && el.parentNode && el.parentNode.removeChild(el));
				originals.forEach((el, i) => originals.inlineWidths[i] ? (el.style.width = originals.inlineWidths[i]) : el.style.removeProperty("width"));
				tickers = originals;
			} else {
				tickers = config.targets;
			}
			const clones = tickers.clones = [],
				inlineWidths = tickers.inlineWidths = [];
			tickers.forEach((el, index) => {
				inlineWidths[index] = el.style.width;
				el.style.width = "10000px"; // to let the children grow as much as necessary (otherwise it'll often be cropped to the viewport width)
				el.children[0].style.display = "inline-block";
				let width = el.children[0].offsetWidth,
					cloneCount = Math.ceil(window.innerWidth / width),
					right = el.dataset.direction === "right",
					i;
				el.style.width = width * (cloneCount + 1) + "px";
				for (i = 0; i < cloneCount; i++) {
					clones.push(config.clone(el));
				}
				gsap.fromTo(el, {
					x: right ? -width : 0
				}, {
					x: right ? 0 : -width,
					duration: width / 100 / parseFloat(el.dataset.speed || 1),
					repeat: -1,
					overwrite: "auto",
					ease: "none"
				});
			});
			// rerun on window resizes, otherwise there could be gaps if the user makes the window bigger.
			originals || window.addEventListener("resize", () => buildTickers(config, tickers));
		}
	}
});

Hopefully that gives you something that you can work with, or at least analyze some of the logic. 

 

Enjoy!

  • Like 4
Link to comment
Share on other sites

On 2/2/2021 at 10:42 AM, GreenSock said:

We've had several people ask about this type of effect, so I just built a GSAP effect that makes this a lot simpler for you (or anyone). Here's a fork of your original CodePen with it in place: 

 

 

 

So you can just paste that gsap.registerEffect(...) code into your project, and then it's super simple to make anything have that effect:


gsap.effects.ticker(".hero__ticker-init"); 

That's it!

 

You can control the speed and direction with attributes like:


<div data-speed="8" data-direction="right"></div>

I noticed a problem with your original implementation - if the screen was resized, it didn't adjust, so there could be gaps that showed up. The effect here automatically listens for "resize" events on the window, and dynamically adjusts. Seems to work relatively well. I haven't done tons of testing on this, but hopefully it's at least a good starting point for you. 

 

Here's the raw effect (you don't really have to understand it all to use it): 


gsap.registerEffect({
	name: "ticker",
	effect(targets, config) {
		buildTickers({
			targets: targets,
			clone: config.clone || (el => {
				let clone = el.children[0].cloneNode(true);
				el.insertBefore(clone, el.children[0]);
				return clone;
			})
		});
		function buildTickers(config, originals) {
			let tickers;
			if (originals && originals.clones) { // on window resizes, we should delete the old clones and reset the widths
				originals.clones.forEach(el => el && el.parentNode && el.parentNode.removeChild(el));
				originals.forEach((el, i) => originals.inlineWidths[i] ? (el.style.width = originals.inlineWidths[i]) : el.style.removeProperty("width"));
				tickers = originals;
			} else {
				tickers = config.targets;
			}
			const clones = tickers.clones = [],
				inlineWidths = tickers.inlineWidths = [];
			tickers.forEach((el, index) => {
				inlineWidths[index] = el.style.width;
				el.style.width = "10000px"; // to let the children grow as much as necessary (otherwise it'll often be cropped to the viewport width)
				el.children[0].style.display = "inline-block";
				let width = el.children[0].offsetWidth,
					cloneCount = Math.ceil(window.innerWidth / width),
					right = el.dataset.direction === "right",
					i;
				el.style.width = width * (cloneCount + 1) + "px";
				for (i = 0; i < cloneCount; i++) {
					clones.push(config.clone(el));
				}
				gsap.fromTo(el, {
					x: right ? -width : 0
				}, {
					x: right ? 0 : -width,
					duration: width / 100 / parseFloat(el.dataset.speed || 1),
					repeat: -1,
					overwrite: "auto",
					ease: "none"
				});
			});
			// rerun on window resizes, otherwise there could be gaps if the user makes the window bigger.
			originals || window.addEventListener("resize", () => buildTickers(config, tickers));
		}
	}
});

Hopefully that gives you something that you can work with, or at least analyze some of the logic. 

 

Enjoy!

Thank you!

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