Link clicked first time - on scroll animation doesn't work - javascript

Issue:
When I click the skill-set link for the first time, the animation occurs but does not occur when you scroll down. Each circle is to start it's own animation when the user scrolls down the page. If you click the skill-set link twice though, everything works as its supposed to.
So my question at hand is, why doesn't the animation on scroll occur on the first time the skill-set link is clicked?
Here is a DEMO of what I am talking about, please excuse the terrible layout. Once you click on the skill-set link, you see the animation happen, but when you scroll down, the animation is already completed...However, if you click the skill-set link twice, and then scroll down, you see each circle animate when you scroll down. This is what should happen on the first time the link is clicked, but for some odd reason it isn't.
JS:
$('#skill-set-link').click(function () {
function animateElements(index, element) { // (e, init)
if (element) { // (init)
$('.progressbar').data('animate', false);
}
$('.progressbar').each(function () {
var elementPos = $(this).offset().top;
var topOfWindow = $(window).scrollTop();
var percent = $(this).find('.circle').attr('data-percent');
var percentage = parseInt(percent, 10) / parseInt(100, 10);
var animate = $(this).data('animate');
if (elementPos < topOfWindow + $(window).height() + 10 && !animate) {
$(this).data('animate', true);
$(this).find('.circle').circleProgress({
startAngle: -Math.PI / 2,
value: percent / 100,
thickness: 2, // Change this for thickness
fill: {
color: '#16A085'
}
}).on('circle-animation-progress', function (event, progress, stepValue) {
$(this).find('.percent').text((stepValue * 100).toFixed(0) + "%"); // NOTE: Change '.toFixed(0)' to '.toFixed(1)' to get 1 decimal place to the right...
}).stop();
}
});
}
animateElements({}, true);
$('.about_body_wrapper').scroll(animateElements);
});
=========================================================================
Any idea as to why the animation on scroll doesn't occur the first time the link is clicked?

The behavior is occurring because everything in the skill-set-link DIV is still hidden when it runs the first time, so the top position of all of the progressbar elements is zero. Since they are zero, they are meeting the criteria of the if statement and the animation is being enabled on all of them.
To fix it, I added a call to show() the progressbar elements, including the parameter to run animateElements when show() is complete.
I moved the call to set "animate" to false to the menu item click function as it didn't really serve any purpose in animateElements. I also removed the animateElements function from the click event handler to simplify reading the code.
function animateElements(index, element) { // (e, init)
$('.progressbar').each(function () {
var elementPos = $(this).offset().top;
var topOfWindow = $(window).scrollTop();
var percent = $(this).find('.circle').attr('data-percent');
var percentage = parseInt(percent, 10) / parseInt(100, 10);
var animate = $(this).data('animate');
if (elementPos < topOfWindow + $(window).height() + 10 && !animate) {
$(this).data('animate', true);
$(this).find('.circle').circleProgress({
startAngle: -Math.PI / 2,
value: percent / 100,
thickness: 2, // Change this for thickness
fill: {
color: '#16A085'
}
}).on('circle-animation-progress', function (event, progress, stepValue) {
$(this).find('.percent').text((stepValue * 100).toFixed(0) + "%"); // NOTE: Change '.toFixed(0)' to '.toFixed(1)' to get 1 decimal place to the right...
}).stop();
}
});
}
$('#skill-set-link').click(function () {
$('.progressbar').data('animate', false);
$('#skill-set').fadeIn(animateElements);
});
$(window).scroll(animateElements);

Thanks to the help from Tony Hinkle - Here is the answer.
Due to the main div being hidden - we needed to show() the main div beforehand...However, adding $('#skill-set').show(0, animateElements); as suggested by Tony, didn't quite work right - so instead $('#skill-set').fadeIn(animateElements) replaced that along with taking out the 0 which seemed to do the trick.
Many thanks to Tony though for steering me in the right direction!
Here is the final snippet used to make this work as desired:
function animateElements(index, element) { // (e, init)
$('.progressbar').each(function () {
var elementPos = $(this).offset().top;
var topOfWindow = $(window).scrollTop();
var percent = $(this).find('.circle').attr('data-percent');
var percentage = parseInt(percent, 10) / parseInt(100, 10);
var animate = $(this).data('animate');
if (elementPos < topOfWindow + $(window).height() + 10 && !animate) {
$(this).data('animate', true);
$(this).find('.circle').circleProgress({
startAngle: -Math.PI / 2,
value: percent / 100,
thickness: 2, // Change this for thickness
fill: {
color: '#16A085'
}
}).on('circle-animation-progress', function (event, progress, stepValue) {
$(this).find('.percent').text((stepValue * 100).toFixed(0) + "%"); // NOTE: Change '.toFixed(0)' to '.toFixed(1)' to get 1 decimal place to the right...
}).stop();
}
});
}
$('#skill-set-link').click(function () {
$('.progressbar').data('animate', false);
$('#skill-set').fadeIn(animateElements);
});
$(window).scroll(animateElements);
And here is the final iteration: DEMO
Don't mind the layout... :)

Related

SmoothScroll to an ID Div on another page using jquery

I have a page "link.html" which has an anchor pointing to index.html page <a href = "index.html?#myInnerLink"
I want smoothscroll to the div on another page(index.html) which has an Id of "myInnerLink" in jquery .. it is working fine but the problem is that it is scrolling from bottom to top instead of top to bottom to that particular div
"myInnerLink" div is internal in "myDiv" div... Thanks
link.html
<a id="mylink" href="index.html?#myInnerLink">Go To MY InnerLink</a>
index.html
<div id="myDiv" class="mydiv">
SomeText here...
<div id="myInnerLink">
ScrollTo This Div...
</div>
</div>
jquery
$(document).ready(function() {
if (window.location.hash) {
var hash = window.location.hash;
$('#myDiv').animate({
scrollTop : $(hash).offset().top
}, 500);
};
});
I'm currently using this script below, which is modified and originally came from https://jsfiddle.net/s61x7c4e/
function doScrolling(element, duration) {
let bodyRect = document.body.getBoundingClientRect(),
elementRect = element.getBoundingClientRect(),
offset = ((elementRect.top - bodyRect.top) - 40);
let startingY = window.pageYOffset,
elementY = offset,
targetY,
diff,
easeInOutCubic,
start;
duration = duration || 500;
// if element is close to page's bottom then window will scroll only to some position above the element...
targetY = document.body.scrollHeight - elementY < window.innerHeight ? document.body.scrollHeight - window.innerHeight : elementY;
diff = targetY - startingY;
easeInOutCubic = function (t) {
return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1
};
if (!diff) return;
// bootstrap our animation,
// it will get called right before next frame shall be rendered...
window.requestAnimationFrame(function step(timestamp) {
if (!start) start = timestamp;
let time = timestamp - start, // elapsed milliseconds since start of scrolling...
percent = Math.min(time / duration, 1); // get percent of completion in range [0, 1]
// apply the easing, it can cause bad-looking
// slow frames in browser performance tool, so be careful...
percent = easeInOutCubic(percent);
window.scrollTo(0, startingY + diff * percent);
// proceed with animation as long as we wanted it to.
if (time < duration) {
window.requestAnimationFrame(step)
}
})
}
document.getElementById('scrollMid').addEventListener('click', function(){
var element = document.getElementById('middle');
doScrolling(element, 1000);
});

JS animation loop when returning to hide element

I have an element which I animate to move across the screen. From left:-100px to left:screen-width. I loop this 4 times.
When returning the element back to its original position left:-100px, I don’t want it to be seen moving across the screen (from right to left) really fast.
I tried to do it by hiding the element with .hide() and then showing it after a while (so that it has time to move back to its initial position). But this doesn’t work:
$('.snake-image').hide();
$('.snake-image').css('top', height / 2).css('left', currentPos);
setTimeout(function(){$('.snake-image').show();},1000);
Code:
$('body').append('<a href="#"><img src="https://dl.dropboxusercontent.com/u/48552248/projects/covve/website/2015/public/images/snake.png" class="snake-image" style="position:absolute;top:0;" />');
function goRight(currentPos) {
$('.snake-image').animate({
left: currentPos
}, 100);
}
function moveSnake() {
while (currentPos <= width) {
goRight(currentPos);
currentPos += 20;
console.log(width + " x " + currentPos);
}
}
var currentPos,
height = $(window).height(),
width = $(window).width(),
i = 4;
var intervalID = setInterval(function(){
if (i > 0){
currentPos = -100;
$('.snake-image').hide();
$('.snake-image').css('top', height / 2).css('left', currentPos);
setTimeout(function(){$('.snake-image').show();},1000);
moveSnake();
i--;
console.log('Interval 1');
} else {
clearInterval(intervalID);
}
}, 100);
Demo: http://jsfiddle.net/m0epjLym/
you could use the animate callback
triggered at the end of the animation, you can move your item back in the origina position and then call again the animation
Fiddle:http://jsfiddle.net/xgknu376/
You can do this:
$('.snake-image').animate({'opacity': 0}, 0);
$('.snake-image').animate({'top': height / 2}, 0).animate({'left': currentPos}, 0).delay(1000).animate({'opacity': 1}, 0);
The delay function will only work on items that are in the animation queue.
Fiddle: http://jsfiddle.net/y995cts3/3/

jQuery width (%) doesn't stop calculate on windowResize?

This is my code:
http://jsfiddle.net/7cXZj/
var callback = function () {
$('.progress-bar').width($('.progress-bar').parent().width() - 190);
$(".mainpart-background").animate({ width: "80%" }, 800 , function(){
var sidepartposition = $(".progress-bar").width() * 0.1 + $(".sidepart-content").width() * 0.5 ;
$(".sidepart").animate({ "margin-right": - sidepartposition }, 100);
});
};
$(document).ready(callback);
$(window).resize(callback);
var sidepartpositionResize = $(".progress-bar").width() * 0.1 + $(".sidepart-content").width() * 0.5 ;
$(window).resize(function(){
$(".sidepart").css( "margin-right", "sidepartpositionResize" );
});
This is the problem:
The span showing "20%" disappears when you resize the window. Why? Inspecting it with Firebug you will see jQuery won't stop calculate the 80%, it goes 80.00213 to 79.1241 to 79.12523 ... and so on. Suddenly after 1-4 seconds it's done with this strange process. Then the span contents the 20% appears.
Please note: This code should work on responsive websites.
I'm a JS beginner. Thank you so much for help!
Try this code: http://jsfiddle.net/7cXZj/5/
This code lets you bind to the end of the resize event and not executing the function many times during the resize of the window.
var animate = function(){
console.log('animando');
$(".mainpart-background").css('width', 0);
$(".mainpart-background").animate({
width: "80%"
}, 800, function () {
var sidepartposition = $(".progress-bar").width() * 0.1 + $(".sidepart-content").width() * 0.5;
$(".sidepart").animate({
"margin-right": -sidepartposition
}, 10);
}
);
}
window.resizeEvt;
$(document).ready(function(){
animate();
$(window).resize(function()
{
clearTimeout(window.resizeEvt);
window.resizeEvt = setTimeout(function()
{
animate();
}, 250);
});
});
Hope it helps.

Linear animation with jQuery and fixed step-number

I'm trying to animate the backgroundPositionY of an <div> element. What I try to do is to animate it linearly. Every step should be in between a fixed range.
For example:
step1: backgroundPositionY: 0 (192*0)
step2: backgroundPositionY: 192 (192*1)
step3: backgroundPositionY: 384 (192*2)
... and so on
My current code looks like the following:
$curtains = $("#unshredder-curtains");
$curtains.data('backgroundPositionY', -3456);
$curtains.animate({
backgroundPositionY: 3648
}, {
duration: 2000,
easing: "linear",
step: function(now, fx) {
var newTop = Math.floor(now / 192) * 192;
$(fx.elem).css('backgroundPositionY', newTop+'px');
}
});
But that does nothing. It just animates the background as it usually does. The steps are just ignored.
Does anyone know how to do that special animation?
Thanks :)
I'd probably do something like:
var step = 192;
setInterval(function(){
$('#unshredder-curtains').css('backgroundPositionY', function(i, val){
var bgPosY = (parseInt(val) + step) + 'px';
$(this).html('New position: ' + bgPosY);
return bgPosY;
});
}, 100);
You can see it in action here: http://jsfiddle.net/pr7cc/

jQuery vertical bubble marquee HTML elements

I'm searching for a good vertical bubble marquee plugin.
Not simple vertical marquee, I'm looking for a good "flash like" effects plugin, something smooth with element marquee from bottom to top of a div content.
Could be really nice but I think it's only in my dreams this plugin
Well, it's not terribly efficient, but this is a good start I think:
jQuery.fn.verticalMarquee = function(vertSpeed, horiSpeed) {
this.css('float', 'left');
vertSpeed = vertSpeed || 1;
horiSpeed = 1/horiSpeed || 1;
var windowH = this.parent().height(),
thisH = this.height(),
parentW = (this.parent().width() - this.width()) / 2,
rand = Math.random() * 1000,
current = this;
this.css('margin-top', windowH + thisH);
this.parent().css('overflow', 'hidden');
setInterval(function() {
current.css({
marginTop: function(n, v) {
return parseFloat(v) - vertSpeed;
},
marginLeft: function(n, v) {
return (Math.sin(new Date().getTime() / (horiSpeed * 1000) + rand) + 1) * parentW;
}
});
}, 15);
setInterval(function() {
if (parseFloat(current.css('margin-top')) < -thisH) {
current.css('margin-top', windowH + thisH);
}
}, 250);
};
$('.message').verticalMarquee(0.5, 1);
It uses Math.sin to move the element horizontally. The function verticalMarquee accepts two arguments, one for vertical speed and the other for horizontal speed. The function can only be called on jQuery objects that contains only one element - during testing anything more than one element been animated at once caused terrible amount of lagging.
See a simple demo here: http://jsfiddle.net/CcccQ/2/
Do you mean something like The Silky Smooth Marquee plugin?

Categories

Resources