I'm running a scroll event that triggers TweenMax animations, and I'm noticing that, while it looks good on Chrome, there is a considerable amount of lag on Firefox. Does anyone have a suggestion about how to handle this scroll event as efficiently as possible? Also, is there something about Firefox's rendering that I'm not aware of that might be causing this? Any leads would be appreciated!
The gist is that I'm looking for containers on my page called "customers", which each contain three individual "customer" elements. When a div that matches "customers" scrolls into view, trigger a TweenMax animation, and add a class called "animated", which prevents the element from re-animating subsequently.
Here is a fiddle with the basic demonstration:
http://jsfiddle.net/epp37jsq/
EDIT
To clarify, the fiddle only demonstrates the behavior of my animation function. The lag does not occur there because the file size is quite small. On the actual site, I have 11 groups of 3 "customers." The image is the same, but pulled in 33 times. In the future, the images will be unique. In essence, the animation is being called for each of these 11 groups. I'm looking for suggestions on how to improve the speed of my page.
And my code:
var scrollTimer = null;
$(window).scroll(function () {
if (scrollTimer) {
clearTimeout(scrollTimer); // clear any previous pending timer
}
scrollTimer = setTimeout(handleScroll, 500); // set new timer
console.log("fired!");
});
function handleScroll() {
scrollTimer = null;
$('.customers').each(function() {
if (!$(this).hasClass('animated')) {
if ($(this).isOnScreen(0.45, 0.45)) {
TweenMax.staggerFromTo($(this).find('.customer'), 0.3, {
y: 50,
opacity: 0
}, {
y: 0,
opacity: 1,
ease: Power2.easeOut
}, 0.15);
$(this).addClass('animated');
}
}
});
}
Usually with Firefox, translating on the x or y axis can cause some jank. Sometimes adding a slight rotation:0.001 to your tween can help make your tween more smooth in Firefox.
http://jsfiddle.net/pwkja058/
Also using the GSAP special property autoAlpha instead of opacity can help increase performance
TweenMax.staggerFromTo($(this).find('.customer'), 0.3, {
y: 200,
rotation:0.01, /* add a slight rotation */
autoAlpha: 0 /* use instead of opacity */
}, {
y: 0,
rotation:0.01, /* add a slight rotation */
autoAlpha: 1, /* use instead of opacity */
ease: Power2.easeOut
}, 0.15);
autoAlpha is part of the GSAP CSSPlugin:
http://greensock.com/docs/#/HTML5/GSAP/Plugins/CSSPlugin/
autoAlpha - Identical to opacity except that when the value hits 0 the visibility property will be set to "hidden" in order to improve browser rendering performance and prevent clicks/interactivity on the target. When the value is anything other than 0, visibility will be set to "inherit". It is not set to "visible" in order to honor inheritance (imagine the parent element is hidden - setting the child to visible explicitly would cause it to appear when that's probably not what was intended). And for convenience, if the element's visibility is initially set to "hidden" and opacity is 1, it will assume opacity should also start at 0. This makes it simple to start things out on your page as invisible (set your css visibility:hidden) and then fade them in whenever you want.
Related
I made a slider with Swiper.js which automatically scrolls in a loop.
My code: https://codepen.io/BehnamAzg/pen/NWzmBKo
I wanted it to stop scrolling when it's being hovered, so I add this code:
autoplay: {
disableOnInteraction: false,
pauseOnMouseEnter: true
}
This is working fine, but the speed of scrolling is too high
so to adjust that I have to add a speed (transition duration) to it. but by adding this it makes the mouseEnter a delay to make an effect.
For example:
If I set the "speed" to 5000ms, it would take 5 seconds till the slider stops scrolling when it's hovered.
I don't want this "speed attribute" effects my hovering, I want it to immediately stop the scrolling.
For solving this, I tried to add a delay instead of speed but it will remove the smoothness of scrolling.
I tried to set the transition duration to zero while being hovered with CSS, but that also didn't work:
.swiper:hover > .swiper-wrapper {
transition-duration: 0 !important;
}
I also tried to add a swiper.setProgress(progress, speed) to it and set the speed to zero, it did work but it will mess up the progress of the slider:
$(".swiper").each(function(elem, target){
var test = target.swiper;
$(this).hover(function() {
test.setProgress(0, 0);
}, function() {
test.setProgress(0, 5000);
});
});
I don't know what to do anymore, any suggestions?!
I am creating a simple slot machine and currently using TileSprite to achieve the effects that I want - for the spinning. So far, everything works. However, after the timer stops the initial spin, I want to smoothly scroll the texture to the correct 'result' position:
R1TimerTrigger: function()
{
R1Scroll = false;
game.add.tween(SpriteReel[0].tilePosition).to( { y: R1Result }, 1000, Phaser.Easing.Bounce.Out, false);
}
There are some immediate problems, in that apparently the native tween does not recognize properties of children. Is there a way to solve this, or an alternative approach that does not use tween to achieve the result?
You code looks fine to me and the tween should work on the tile sprite as expected.
Are you starting the tween? You can start the tween automatically using 'true' as the 'autoStart' parameter
to(properties, duration, ease, autoStart, delay, repeat, yoyo)
game.add.tween(SpriteReel[0].tilePosition).to( { y: R1Result }, 1000, Phaser.Easing.Bounce.Out, true);
Working example here https://phaser.io/sandbox/edit/iTLritEj
Look in the Play and Create tabs
I have a sequence of images fading out and then back in which appears to work well for about 2 loops. Unfortunately after that it goes crazy and the sequences appears to go completely random.
I have done a fiddle so you can see what's going on https://jsfiddle.net/MichaelCaley/Lmm3kp4m/
var imgshow = function(){
$(".img1").delay(2000).animate({
opacity: 0
}, 3000, function(){
$(".img2").delay(2000).animate({
opacity: 0
}, 3000, function(){
$(".img3").delay(2000).animate({
opacity: 0
}, 3000, function(){
$(".img1").delay(2000).animate({
opacity: 1
}, 3000, function(){
$(".img2, .img3").animate({
"opacity": "1"
}, 0, function(){
imgshow();
});
});
});
});
});
}
imgshow();
After the first run through I've done a sort of reset step which is supposed to be the only time 2 classes are changing at the same time, but when I watch the loop go through I start to see that multiple divs begin fading throughout the process which I just cannot understand.
Thank you for your help
It's very easy to get confused or lost in callback hell, especially with jQuery animations and especially especially when using delay. May I suggest something a bit more clean, in my opinion at least.
// Get all images that need to be looped.
var images = $('.some-class-all-images-share');
// Create an array to store images that have already been shown.
var cycled = $([]);
// Start an interval, which calls the same function every 5 seconds.
setInterval(function(){
// Get the first image from the images array.
var image = images.unshift();
// If the images array is empty, reset everything.
if (images.length === 0) {
images = cycled;
cycled = $([]);
images.removeClass('transparent');
}
// Add a the class 'transparent' to the image.
image.addClass('transparent');
// Add the image to the cycled images array.
cycled.add(image);
}, 5000);
In the CSS:
.some-class-all-images-share {
/* This means that whenever the opacity of the element changes, it will do so gradually, over three seconds, instead of instantly.*/
transition: opacity 3s;
}
.transparent {
opacity: 0;
}
Now every image will get the transparent class applied to it, one by one. This will trigger a three second long animation, and when all images except for the last one have been animated, it will restart.
This way you don't need another callback for each image and it should be, overall much more manageable.
So I'm trying to have these two divs push each-other, but FPS is taking a huge hit, and I know it's due to dom repainting... But can I avoid it?
http://codepen.io/Strongarm/pen/obXmmg
document.getElementById("left").addEventListener("click", function(){
TweenMax.to(".left", 0.5, {width:"100%"});
TweenMax.to(".right", 0.5, {width:"0%", opacity: 0});
fullScreen = true;
});
document.getElementById("right").addEventListener("click", function(){
TweenMax.to(".left", 0.5, {width:"0%", opacity: 0});
TweenMax.to(".right", 0.5, {width:"100%"});
fullScreen = true;
});
Depending on your situation, you may be able to animate the "transform" attribute instead. This link describes why transform is better when it comes to moving elements around - it's possible that it will help with resizing too.
For obvious reasons this won't work in all cases, but you could try:
TweenMax.to(".left", 1, {transform: scaleX(100%)});
TweenMax.to(".right", 1, {transform: scaleX(0%)});
I have been using parallax for some time and I have been using CSS animations , transforms and etc in order to get the results that I want. But after reading some stuff about Velocity , thought giving it a try.
The problem is the animations are having some kind of delay. Probably because I'm not applying velocity correctly, but I have researched and it seems that I'm doing is correct.
$ability.velocity({
translateX: '-50px',
opacity: '0'
});
$(document).on('scroll', function(){
var wScroll = $(this).scrollTop();
if(wScroll > $('.ability-self').offset().top - $(window).height()/1.2){
$ability.velocity({
translateX: "0",
opacity: '1'
});
} else{
$ability.velocity({
translateX: '-70px',
opacity: 0
});
}
The problem with that is that the animation only happens 1 or 2 seconds after I scroll after the element. I have checked if any CSS attribute might be interfering, but I didn't find a relevant one.
Is my JS bad?
Assuming your use of Velocity is correct, your code is causing a lot of stress for the browser.
What you should do is first cache the layout values that don't change:
var window_h = $(window).height()/1.2
and:
var ability_top = $('.ability-self').offset().top
And second, debounce the scroll event handler, since scroll is triggered a lot and you only need to respond once every frame, or possibly even less. For debouncing you could use lodash's or Underscore's _.debounce() or just copy paste the implementation, so your code would look like:
$(document).on('scroll', _.debounce(function(){
// code here...
}, 50))