Improving performance of JavaScript transitions - javascript

I have a JavaScript-driven parallax slider, adapted from this tutorial (http://tympanus.net/codrops/2011/01/03/parallax-slider/), and a small script which fades the slider image out after scrolling past a certain point.
Here is the script:
$(document).ready(function() {
$(window).scroll(function () {
var $slider = $('.pxs_slider');
var sTop = $('body').scrollTop();
var sTop_ff = $('html').scrollTop();
var opacity = 1;
if(sTop < 40) {
opacity = 1;
if(sTop_ff < 40) {
opacity = 1;
} else {
opacity = 0;
}
} else {
opacity = 0;
}
$slider.css('opacity', opacity);
});
});
It all works fine, but scrolling becomes significantly sluggish during this transition. However, I've found it only really has this issue in Chrome of all browsers. There is no performance hit in Firefox.
Is there a more efficient approach to this effect I could try?

Cache $('.pxs_slider') so it's not queried every time the scrollbar moves is the big one:
$(document).ready(function() {
var $slider = $('.pxs_slider');
$(window).scroll(function() {
var sTop = $('body').scrollTop();
var sTop_ff = $('html').scrollTop();
var opacity = 1;
if(sTop < 40) {
opacity = 1;
if(sTop_ff < 40) {
opacity = 1;
} else {
opacity = 0;
}
} else {
opacity = 0;
}
$slider.css('opacity', opacity);
});
});
Also, $(window).scrollTop(), I believe, is the correct way:
$(document).ready(function() {
var $slider = $('.pxs_slider');
$(window).scroll(function() {
$slider.css('opacity', $(window).scrollTop() < 40 ? 1 : 0);
});
});

Related

Javascript animate on scroll position

I am trying to get a scrolling animation like here (notice the circle figure fading in when you scroll down):
http://demo.atticthemes.com/skoty/
This is what I have sofar, but it keeps hanging somehow:
http://jsfiddle.net/v4zjgwL6/
var timer;
var triggerHeight = $("#bar").offset().top;
var headerAvatar = $(".header-avatar-wrapper");
$(window).scroll(function() {
if(timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout(function() {
var y = $(window).scrollTop();
if(y > triggerHeight - 220) {
headerAvatar.css("visibility", "visible");
headerAvatar.animate({opacity: 1}, 200);
} else {
headerAvatar.animate({opacity: 0}, 200);
headerAvatar.css("visibility", "hidden");
}
}, 10);
});
You don't need to use a timer, the way you have implemented it causes performance drops.
I would suggest to use css classes instead:
var triggerHeight = $("#bar").offset().top;
var headerAvatar = $(".header-avatar-wrapper");
$(window).scroll(function() {
var y = $(window).scrollTop();
if (y > triggerHeight - 220 && !headerAvatar.hasClass("visible")) {
headerAvatar.addClass("visible");
} else if(y <= triggerHeight - 220 && headerAvatar.hasClass("visible")) {
headerAvatar.removeClass("visible");
}
});
I have also added this class in CSS:
.header-avatar-wrapper.visible{
opacity: 1;
visibility: visible;
}
JSFiddle demo
Or alternatively, use jQuery's .fadeIn() and fadeOut() functions:
var triggerHeight = $("#bar").offset().top;
var headerAvatar = $(".header-avatar-wrapper");
$(window).scroll(function() {
var y = $(window).scrollTop();
if (y > triggerHeight - 220 && headerAvatar.css("display") == "none") {
headerAvatar.fadeIn();
} else if(y <= triggerHeight - 220 && headerAvatar.css("display") == "block") {
headerAvatar.fadeOut();
}
});
In CSS I removed the opacity and visibility properties from .header-avatar-wrapper and added display: none; instead.
JSFiddle demo
Looks like you're only handling the cases where you need to change state (shown or hide the element) and not the cases where nothing should change. This causes you to continuously re-show (re-animate) the thing, which makes it flicker.
It's early and I have not yet had coffee, but something like this should fix you up. :)
var timer;
var triggerHeight = $("#bar").offset().top;
var headerAvatar = $(".header-avatar-wrapper");
var shown; // NEW
$(window).scroll(function() {
if(timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout(function() {
var y = $(window).scrollTop();
var shouldShow = y > triggerHeight - 220; // CHANGED
if(!shown && shouldShow) { // CHANGED
shown = true; // NEW
headerAvatar.css("visibility", "visible");
headerAvatar.animate({opacity: 1}, 200);
} else if (shown && !shouldShow) { // CHANGED
shown = false; // NEW
headerAvatar.animate({opacity: 0}, 200);
headerAvatar.css("visibility", "hidden");
}
}, 10); });
Proof: http://jsfiddle.net/bvaughn/oL85oj41/

Execute function IF another function is complete NOT when

I am having trouble creating a slider that pauses on hover, because I execute the animation function again on mouse off, if I flick the mouse over it rapidly (thereby calling the function multiple times) it starts to play up, I would like it so that the function is only called if the other function is complete, otherwise it does not call at all (to avoid queue build up and messy animations)
What's the easiest/best way to do this?
$(document).ready(function() {
//get variables
var slide_width = $('.slider_container').width();
var number_of_slides = $('.slider_container .slide').length;
var slider_width = slide_width*number_of_slides;
//set element dimensions
$('.slide').width(slide_width);
$('.slider').width(slider_width);
var n = 1;
$('.slider_container').hover(function() {
//Mouse on
n = 0;
$('.slider').stop(true, false);
}, function() {
//Mouse off
n = 1;
if (fnct == 0) sliderLoop();
});
//Called in Slide Loop
function animateSlider() {
$('.slider').delay(3000).animate({ marginLeft: -(slide_width * i) }, function() {
i++;
sliderLoop();
});
}
var i = 0;
var fnct = 0
//Called in Doc Load
function sliderLoop() {
fnct = 1
if(n == 1) {
if (i < number_of_slides) {
animateSlider();
}
else
{
i = 0;
sliderLoop();
}
}
fnct = 0
}
sliderLoop();
});
The slider works fine normally, but if I quickly move my mouse on and off it, then the slider starts jolting back and forth rapidly...been trying to come up with a solution for this for hours now..
Here's what fixed it, works a charm!
$(document).ready(function() {
//get variables
var slide_width = $('.slider_container').width();
var number_of_slides = $('.slider_container .slide').length;
var slider_width = slide_width*number_of_slides;
//set element dimensions
$('.slide').width(slide_width);
$('.slider').width(slider_width);
var n = 1;
var t = 0;
$('.slider_container').hover(function() {
clearInterval(t);
}, function() {
t = setInterval(sliderLoop,3000);
});
var marginSize = i = 1;
var fnctcmp = 0;
//Called in Doc Load
function sliderLoop() {
if (i < number_of_slides) {
marginSize = -(slide_width * i++);
}
else
{
marginSize = i = 1;
}
$('.slider').animate({ marginLeft: marginSize });
}
t = setInterval(sliderLoop,3000);
});

Item appearing when reaching a certain height (scroll effect)

I just found this code :
script type="text/javascript">
$(document).ready(function() {
$(window).scroll(function () {
var height = $('body').height();
var scrollTop = $('body').scrollTop();
var opacity = 1;
if(scrollTop > 400) {
opacity = 0;
}
$('.social').css('opacity', opacity);
});
});
Although, i'd like to reverse these effects. I'd like the element to start opactiy : 0 and fadein when reaching a certain height (in this case 400).
Thanks
Although I'm not sure if you really tried it yourself, I'd say:
$(document).ready(function() {
$(window).scroll(function () {
var height = $('body').height();
var scrollTop = $('body').scrollTop();
var opacity = 0;
if(scrollTop > 400) {
opacity = 1;
}
$('.social').css('opacity', opacity);
});
});
(not tested, but I'm pretty confident that's what you were looking for.)

How to add scroll background effect to multiple elements with different settings?

In this demo http://www.htmldrive.net/items/demo/527/Animated-background-image-with-jQuery
This code is for one background only. I want to add multiple background with different direction and speed.
var scrollSpeed = 70;
var step = 1;
var current = 0;
var imageWidth = 2247;
var headerWidth = 800;
var restartPosition = -(imageWidth - headerWidth);
function scrollBg(){
current -= step;
if (current == restartPosition){
current = 0;
}
$('#header').css("background-position",current+"px 0");
}
var init = setInterval("scrollBg()", scrollSpeed);
Currently it has settings for
$('#header').css("background-position",current+"px 0");
In a website I want to use this effect on #footer or #content background also. but with different speed and direction.
And is there any better and more optimized jquery method to achieve same effect?
And can we get same effect using CSS 3, without javascript?
Just saw the OP's answer, but decided to post anyway:
I've created a jQuery plugin to do this:
(function($) {
$.fn.scrollingBackground = function(options) {
// settings and defaults.
var settings = options || {};
var speed = settings.speed || 1;
var step = settings.step || 1;
var direction = settings.direction || 'rtl';
var animStep;
// build up a string to pass to animate:
if (direction === 'rtl') {
animStep = "-=" + step + "px";
}
else if (direction === 'ltr') {
animStep = '+=' + step + "px";
}
var element = this;
// perform the animation forever:
var animate = function() {
element.animate({
backgroundPosition: animStep + " 0px"
}, speed, animate);
};
animate();
};
})(jQuery);
Usage:
$("#header").scrollingBackground({
speed: 50,
step: 50,
direction: 'ltr'
});
This is pretty basic, and assumes that you're background-repeat is 'repeat-x' on the element you call it on. This way, there's no need to reset the background position every so often.
Working example: http://jsfiddle.net/andrewwhitaker/xmtpr/
I could work out the following solution. Am not sure if it is efficient. Will wait for anyone to comment or provide a better option.
Till then...:
var scrollSpeed = 70;
var step = 1;
var current = 0;
var images =
[
{
imageWidth:2247,
imagePath:"images/image1"
},
{
imageWidth:1200,
imagePath:"images/image2"
}
]
var headerWidth = 800;
var imageRotateCount = 0;
var imagesLength = images.length;
$('#header').css("background-image", images[0].imagePath);
function scrollBg(){
var curIndex = imageRotateCount%imagesLength;
var curImage = images[curIndex];
current -= step;
var restartPosition = -(curImage.imageWidth - headerWidth);
if (current == restartPosition){
current = 0;
imageRotateCount++;
curIndex = imageRotateCount%imagesLength;
curImage = images[curIndex];
$('#header').css("background-image", curImage.imagePath);
}
$('#header').css("background-position",current+"px 0");
}
var init = setInterval("scrollBg()", scrollSpeed);

FadeIn javascript function in Safari not working but FadeOut works :(

So I've made custom function for a game I'm working on, one being fade in the other one fade out. The problem is fadeOut works, but fading back IN does not... strange. Any clues? See code below.
THIS WORKS:
fadeOut:function(o,duration)
{
o.style.opacity = 1;
o._anim = function()
{
if(o.style.opacity <=0)
{
clearInterval(o._animInt);
return false;
}
o.style.opacity -= .1;
game.log("opacity:" + o.style.opacity);
}
o._animInt = setInterval(o._anim,duration / 10)
}
THIS DOES NOT:
fadeIn:function(o,duration)
{
o.style.opacity = 0;
o._anim = function()
{
if(o.style.opacity >= 1)
{
clearInterval(o._animInt);
return false;
}
o.style.opacity += .1;
game.log("opacity:" + o.style.opacity);
}
o._animInt = setInterval(o._anim,duration / 10)
}
function fadeIn (o,duration) {
o.style.opacity = 0;
o._anim = function() {
var opacity = parseFloat(o.style.opacity);
if(opacity >= 1) { clearInterval(o._animInt); return false;}
o.style.opacity = opacity + 0.1;
game.log("opacity:" + o.style.opacity);
}
o._animInt = setInterval(o._anim,duration / 10)
}
The opacity attribute is a string. Parse it first, compare, increment, then store. This worked for me in Chrome and Firefox.

Categories

Resources