I am doing a small javascript animation. this is my code :
window.onload = function () {
var heading = document.getElementsByTagName('h1')[0];
heading.onclick = function () {
var divHeight = 250;
var speed = 10;
var myInterval = 0;
alert(divHeight);
slide();
function slide() {
if (divHeight == 250) {
myInterval = setInterval(slideUp, 30);
} else {
myInterval = setInterval(slideDwn, 30);
alert('i am called as slide down')
}
}
function slideUp() {
var anima = document.getElementById('anima');
if (divHeight <= 0) {
divHeight = 0;
anima.style.height = '0px';
clearInterval(myInterval);
} else {
divHeight -= speed;
if (divHeight < 0) divHeight = 0;
anima.style.height = divHeight + 'px';
}
}
function slideDwn() {
var anima = document.getElementById('anima');
if (divHeight >= 250) {
divHeight = 250;
clearInterval(myInterval);
} else {
divHeight += speed;
anima.style.height = divHeight + 'px';
}
}
}
}
i am using above code for simple animation. i need to get the result 250 on the first click, as well second click i has to get 0 value. but it showing the 250 with unchanged. but i am assigning the value to set '0', once the div height reached to '0'.
what is the issue with my code? any one help me?
Everytime you click on the div the divHeight variable is reset to 250, thus your code never calls slideDwn. Moving the divHeight declaration outside the event handler should do the trick.
Also, your div wont have the correct size when any of the 2 animations end. You're setting the divHeight variable to 250 or 0 correctly, but never actually setting anima.style.height after that.
I've rewritten your code into something simpler and lighter. The main difference here is that we're using a single slide() function here, and that the height of the div in question is stored in a variable beforehand to ensure that the element slides into the correct position.
Note that this is a very simplistic implementation and assumes that the div carries no padding. (The code uses ele.clientHeight and ele.style.height interchangeably, which admittedly, is a pretty bad choice, but is done here to keep the code simple)
var heading = document.getElementsByTagName('h1')[0],
anima = document.getElementById('anima'),
divHeight = anima.clientHeight,
speed = 10,
myInterval = 0,
animating = false;
function slide(speed, goal) {
if(Math.abs(anima.clientHeight - goal) <= speed){
anima.style.height = goal + 'px';
animating = false;
clearInterval(myInterval);
} else if(anima.clientHeight - goal > 0){
anima.style.height = (anima.clientHeight - speed) + 'px';
} else {
anima.style.height = (anima.clientHeight + speed) + 'px';
}
}
heading.onclick = function() {
if(!animating) {
animating = true;
var goal = (anima.clientHeight >= divHeight) ? 0 : divHeight;
myInterval = setInterval(slide, 13, speed, goal);
}
}
See http://www.jsfiddle.net/yijiang/dWJgG/2/ for a simple demo.
I've corrected your code a bit (See working demo)
window.onload = function () {
var heading = document.getElementsByTagName('h1')[0];
var anima = document.getElementById('anima');
var divHeight = 250;
heading.onclick = function () {
var speed = 10;
var myInterval = 0;
function slideUp() {
divHeight -= speed;
if (divHeight <= 0) {
divHeight = 0;
clearInterval(myInterval);
}
anima.style.height = divHeight + 'px';
}
function slideDwn() {
divHeight += speed;
if (divHeight >= 250) {
divHeight = 250;
clearInterval(myInterval);
}
anima.style.height = divHeight + 'px';
}
function slide() {
console.log(divHeight )
if (divHeight == 250) {
myInterval = setInterval(slideUp, 30);
} else {
myInterval = setInterval(slideDwn, 30);
}
}
slide();
}
}
Related
Need to apply the animateScript() function to different images/divs on mouseover. i think i just need to change my document.querySelector but im not sure how to do so so that it applies to one of the 4 different images.
let tID; //we will use this variable to clear the setInterval()
//let x = event.clientX, y = event.clientY, elementMouseIsOver = document.elementFromPoint(x, y);
function stopAnimate() {
clearInterval(tID);
} //end of stopAnimate()
function animateScript() {
let position = 80; //start position for the image slicer
let height = 0;
const interval = 190; //180 ms of interval for the setInterval()
const diff = 80; //diff as a variable for position offset
const next_row = 110;
let elements = document.querySelectorAll(':hover');
tID = setInterval(() => {
document.querySelector(".avatar").style.backgroundPosition = `-${position}px -${height}px`;
//we use the ES6 template literal to insert the variable "position"
if (height < 220)
{
if (position < 720) {
position = position + diff;
console.log(position);
}
else if (position == 720){
//console.log("height");
position = 80;
height = next_row + height;
console.log("height: ", height);
}
}
else {
if (position < 400) {
position = position + diff;
console.log(position);
}
else if (position == 480){
position = 80;
height = 0;
console.log("height: ", height);
}
}
//reset the position to 256px, once position exceeds 1536px
}, interval); //end of setInterval
} //end of animateScript()
You're hard-coding the .avatar selector, which will always get the first element with that class, so you're correct that that will need to change.
One easy solution would be to pass the hovered element into your function.
const handleMouseEnter = (e) => {
const el = e.target;
animateScript(el);
}
element.addEventListner("mouseenter", handleMouseEnter);
function animateScript(element) {
[...]
tID = setInterval(() => {
element.style.backgroundPosition = `whatever style`;
[...]
}, interval);
}
I followed Paul Lewis's guide to debounce and requestAnimationFrame. I'm translating an image across the screen on scroll when it comes into view.
var bicycles = $('.tandem-bike', context),
lastScrollY = 0,
ticking = false;
function update() {
var windowHeight = window.innerHeight,
windowWidth = $(window).width(),
bikeTop = [];
bicycles.each( function (i, el) {
bikeTop[i] = $(this).offset();
});
bicycles.each(function(i, el) {
var position = bikeTop[i];
var fromTop = position.top - windowHeight;
var imgHeight = $(this).height();
// When this image scrolls into view.
if (lastScrollY > fromTop && lastScrollY < position.top + imgHeight && i == 1 ) { // 375 ~= height of image
var translate = Math.floor((lastScrollY - fromTop) / ((windowHeight + imgHeight + 300) / windowWidth));
console.log('add tp tranlate ', translate);
$(this).css('transform', 'translateX(' + (translate - 275) + 'px)');
}
});
ticking = false;
}
function onScroll() {
lastScrollY = window.scrollY;
requestTick();
}
function requestTick() {
if(!ticking) {
requestAnimationFrame(update);
ticking = true;
}
}
window.addEventListener('scroll', onScroll, false);
This works great and the bicycle-built-for-two slides effortlessly across the screen. However, I want the image to "bounce" when the user stops scrolling. I figure an easy way would be to add a class when the animation ends, and pull it off when the animation starts. The obvious place to do that is within the if block in requestTick().
if(!ticking) {
$('.tandem-bike').removeClass('bounce');
requestAnimationFrame(update);
$('.tandem-bike').addClass('bounce');
ticking = true;
}
or
if(!ticking) {
requestAnimationFrame(update);
$('.tandem-bike').addClass('bounce');
ticking = true;
} else {
$('.tandem-bike').removeClass('bounce');
}
}
Neither works, and I don't love then because I'm whole-sale adding classes to all the animated images on the page. (I would live with that if it worked)
I was trying to create a auto slide for the slider using setInterval. It works like a charm when there's only one slider.
When there are 2 slider, the first slider wont work, and the second slider will slide faster, because there will be 2 setInterval and both are sliding the second slider. Anyway to make sure each setInterval slide their own slider?
var autoSlideTimer = 5;
var autoslide = setInterval(function () {
if (autoSlideTimer == 0) {
var slideMargin = offsetMarginLeft - width;
if (-slideMargin == (width * totalImages)) {
offsetMarginLeft = width;
displayImage = 0;
}
slider.style.marginLeft = (offsetMarginLeft - width) + 'px';
displayImage += 1;
pagination = element.getElementsByTagName('ul')[0];
pagination.innerHTML = paginate;
pagination.getElementsByTagName('li')[displayImage - 1].setAttribute("class", "displayed");
slider = element.getElementsByTagName('div')[0];
offsetMarginLeft = parseInt(slider.style.marginLeft.replace('px', ''));
autoSlideTimer = 5;
} else {
autoSlideTimer--;
}
}, 1000);
thanks
I work it out with another way, although is working but doesnt seems to be the perfect way
var event = new Event('build');
// Listen for the event.
element.addEventListener('build', function (e) {
function timeoutLoop()
{
setTimeout(function(){
if(autoSlideTimer == 0)
{
var slideMargin = offsetMarginLeft - width;
if(-slideMargin == (width * totalImages))
{
offsetMarginLeft = width;
displayImage = 0;
}
slider.style.marginLeft = (offsetMarginLeft - width) + 'px';
displayImage += 1;
pagination = element.getElementsByTagName('ul')[0];
pagination.innerHTML = paginate;
pagination.getElementsByTagName('li')[displayImage - 1].setAttribute("class", "displayed");
offsetMarginLeft = parseInt(slider.style.marginLeft.replace('px', ''));
autoSlideTimer = 5;
}else
{
autoSlideTimer--;
}
timeoutLoop();
},1000);
}
timeoutLoop();
}, false);
// Dispatch the event.
element.dispatchEvent(event);
At first, I used setInterval inside, yet the slider will be overwritten. But setTimeout is ok.
I built a kind of chat in JS and then I wanted that when I got new message the chat automatically scrolled down (with animation...). Everything worked beautifully, but after the animation stopped the user couldn't scroll by himself; the chat automatically scrolled to the end.
So this is the code :
<!-- language:lang-js -->
var height = 1;
window.setInterval(function() {
var elem = document.getElementById('chat');
elem.scrollTop = height;
if (elem.scrollheight < height) {
clearInterval(this);
}
height += 2;
}, 50);
the clearInterval function expects a number. Using that should make it work correctly. You also have many syntax errors.
var intervalReference = window.setInterval(function() {
var elem = document.getElementById('chat');
elem.scrollTop = height;
if (elem.scrollHeight < height) {
clearInterval(intervalReference);
}
height += 2;
}, 50);
you should make a var holding the interval like this :
var height = 1;
var interval = window.setInterval( animate, 50 );
function animate() {
var elem = document.getElementById('chat');
elem.scrollTop = height;
if (elem.scrollHeight < height) {
clearInterval( interval );
}
height += 2;
}
this should work fine
I'm trying to create an loading icon by moving the css 'background-position' of an image in a loop:
$('#LoginButton').click(function () {
var i = 1, h = 0, top;
for (i = 0; i <= 12; i++) {
h = i * 40;
top = h + 'px';
$('#ajaxLoading').css('background-position', '0 -' + top).delay(800);
}
});
The problem here is that it runs to fast so I don't se the 'animation' of the moving background.
So I added jquerys delay(), but:
delay(800) is not working because delay() only works in jquery animation effects and .css() is not one of those.
How to delay this loop?
I'd suggest using jQuery timer plugin: http://jquery.offput.ca/js/jquery.timers.js
$('#LoginButton').click(function () {
var times = 13;
var delay = 300;
var h = 0, top;
$(document).everyTime(delay, function(i) {
top = h + 'px';
$('#ajaxLoading').css('background-position', '0 -' + top);
h += 40;
}, times);
});
In case you don't want any plugins, use setInterva/clearInterval:
$('#LoginButton').click(function () {
var delay = 300;
var times = 13;
var i = 0, h = 0, top;
doMove = function() {
top = h + 'px';
$('#ajaxLoading').css('background-position', '0 -' + top);
h += 40;
++i;
if( i >= times ) {
clearInterval( interval ) ;
}
}
var interval = setInterval ( "doMove()", delay );
});
Have you looked at using animate() instead of css()? I'm not 100% sure I understand what you're trying to accomplish, so this is kinda a shot in the dark.
http://api.jquery.com/animate/
Chrome, Safari and IE3+ should support background-position-y, so if you're targeting these specific browser, using jquery you could just make a timed animation() on backgroundPositionY property - http://snook.ca/archives/html_and_css/background-position-x-y
(On Firefox the effect won't work)
You can use setTimeout() and clearTimeout() functions in order to accomplish that.
IE:
var GLOBAL_i = 0;
function doAnimation() {
var h = GLOBAL_i * 40;
var top = h + 'px';
$('#ajaxLoading').css('background-position', '0 -' + top);
if (GLOBAL_i < 12) {
GLOBAL_i++;
t=setTimeout(doAnimation, 800);
}
}
$('#LoginButton').click(function () {
doAnimation()
});