Javascript help, Trying to animate two different sprites at same time - javascript

I need some javascript help. I am trying to set up two sprite animations with different frame rates in two separate div.
Here is a fiddle I started and i am very much stuck.
How do I combine the two div IDs into one statement? OR Should I be using ClassName in the statement to run on both divs?
http://jsfiddle.net/akwilinski/3t7d6qbL/1/
<div id="animate" class="animation"></div>
<div id="animate2" class="animation2"></div>
onload = function startAnimation() {
var frameHeight = 400;
var frames = 27;
var frame = 0;
var div = document.getElementById("animate");
setInterval(function () {
var frameOffset = (++frame % frames) * -frameHeight;
div.style.backgroundPosition = "0px " + frameOffset + "px";
}, 100);
}
Thank you for any assistance!

Simplest way to do this using the method you have already started using is to define 2 new variables, 1 for the second div and one for the second frame count. Then you can just add the call to your function.
Updated js:
onload = function startAnimation() {
var frameHeight = 400;
var frames = 27;
var frame = 0;
var div = document.getElementById("animate");
var div2 = document.getElementById("animate2");
setInterval(function () {
var frameOffset = (++frame % frames) * -frameHeight;
var frameOffset2 = (++frame % frames) * -frameHeight - 10;
div.style.backgroundPosition = "0px " + frameOffset + "px";
div2.style.backgroundPosition = "0px " + frameOffset + "px";
}, 100);
}
Fiddle

http://jsfiddle.net/f4v1vy7x/5/
I made a Can object to store the configuration for each can (so you can have different frameHeights, frames and frameRates.
I used window.requestAnimationFrame because it's far more efficient than setInterval. On each available frame I check whether it's time to animate based on each Can's set frame rate:
var Can = function( selector, frameHeight, frames, frameRate )
{
this.domCan = document.getElementById( selector );
this.frameHeight = frameHeight;
this.frames = frames;
this.frameRate = frameRate;
this.frame = 0;
};
onload = function startAnimation() {
var can1 = new Can( 'animate', 400, 27, 20 );
var can2 = new Can( 'animate2', 400, 27, 100 );
var cans = [ can1, can2 ];
window.requestAnimationFrame( function() {
can1.start = can2.start = new Date();
animate( cans );
} );
};
var animate = function( cans ) {
for( var i = 0; i < cans.length; i++ ) {
var now = new Date();
var can = cans[i];
if( now - can.start >= 1000 / can.frameRate ) {
can.start = now;
var frameOffset = (++can.frame % can.frames) * -can.frameHeight;
can.domCan.style.backgroundPosition = "0px " + frameOffset + "px";
}
}
window.requestAnimationFrame( function() {
animate( cans );
} );
}

You could do something like this:
var div = document.getElementById("animate");
var div2 = document.getElementById("animate2");
function anim(div) {
setInterval(function () {
var frameOffset = (++frame % frames) * -frameHeight;
div.style.backgroundPosition = "0px " + frameOffset + "px";
}, 100);
}
anim(div);
anim(div2);
You could then pass in additional parameters like frameHeight, frame, and frames to further customize each animation.

Related

setInterval Mousemove trail

In my code, I wanted to create a mouse trail with 1)random images 2)a blurring effect 3) opacity transition 4) a max amount of divs in the trail.
Similar to this: https://tympanus.net/Development/ImageTrailEffects/
Point 2 and 3 are done, however I am stuck on point 4. The trail has a crazy strobe effect right now, which I dislike. I want it to be less sensitive and more subtle. Some kind of limitation on them. I've added a counter where I can count the amounts of divs created, but I'm unsure and stuck as to what to do now. I've looked at setInterval, but when I apply it to my function it's not working
I've also had some issues with the creation of an array for the random backgrounds, but I'm sure I'll figure that out. The question is mostly about how to limit and control the creation of the trail, but if anyone has a tip/link as to how to create the random background images, I am all ears.
Here the code I have up till now
window.onload= function() {
window.addEventListener('mousemove', function(e) {
var animate= function(i) {
var image= document.createElement('div'); //create a div named bubble
image.classList.add('trail');
var size= 60;
var sizepx= size+'px';
image.style.transition='2s ease';
image.style.position= 'fixed';
image.style.top= e.pageY - size/2 + 'px';
image.style.left= e.pageX - size/2 + 'px';
image.style.width= sizepx;
image.style.height= sizepx;
image.style.background= 'hsla(' +
Math.round(Math.random()*360) + ', ' +
'100%, ' +
'50%';
// image.style.background= 'black';
image.style.border= 'white 1px solid';
image.style.pointerEvents= 'none';
image.style.zIndex= 1;
document.body.appendChild(image);
//opacity and blur animations
window.setTimeout(function() {
image.style.opacity = 0;
image.style.filter = 'blur(6px)';
}, 80);
window.setTimeout(function() {
document.body.removeChild(image);
}, 2100);
};
var numItems = document.querySelectorAll('.trail').length;
console.log(numItems);
for (var i= 1; i <= 1; i+= 1) {
animate(i);
}
});
};
A fiddle:
https://jsfiddle.net/opufnsvz/
Here you go mate ( I used Unsplash for the random image source ), loading images on the fly gives unwanted effects, so they have to be preloaded. you can change the timesPerSecondto control the frequency
const numberOfImages = 10;
const imageSources = Array.from(Array(numberOfImages).keys()).map((i) => 'https://source.unsplash.com/collection/9948714?' + i);
// how many times to fire the event per second
const timesPerSecond = .1;
function preloadImages(images) {
for (i = 0; i < images.length; i++) {
let l = document.createElement('link')
l.rel = 'preload'
l.as = 'image'
l.href = images[i]
document.head.appendChild(l);
}
}
function animate(e) {
var image= document.createElement('div'); //create a div named bubble
image.classList.add('trail');
var size= 60;
var sizepx= size+'px';
image.style.transition='2s ease';
image.style.position= 'fixed';
image.style.top= e.pageY - size/2 + 'px';
image.style.left= e.pageX - size/2 + 'px';
image.style.width= sizepx;
image.style.height= sizepx;
image.style.backgroundImage = 'url(https://source.unsplash.com/collection/9948714?'+ Math.floor(Math.random()*numberOfImages) +')';
image.style.backgroundSize = 'cover';
image.style.border= 'white 1px solid';
image.style.pointerEvents= 'none';
image.style.zIndex= 1;
document.body.appendChild(image);
//opacity and blur animations
window.setTimeout(function() {
image.style.opacity = 0;
image.style.filter = 'blur(6px)';
}, 80);
window.setTimeout(function() {
document.body.removeChild(image);
}, 2100);
};
window.onload= function() {
preloadImages(imageSources);
var wait = false;
window.addEventListener('mousemove', function(e) {
if (!wait) {
wait = true;
setTimeout(() => { wait = false }, timesPerSecond * 1000);
animate(e);
}
});
};

extract a number from a property value

I am trying to create an animation, when a button is pressed, the div have to move to left 300 px by changing the left-margin,and stop.
I get the left margin value, but when I try to extract 300 px from it, it says that the var moveto is not a number, and current_left_margin`s value is 0px, how can I get this value to be a number, without the px?
here is my full code:
function get_vars() {
elem = document.getElementById('front-slide');
}
window.onload = get_vars;
function vb_anim() {
var interval = setInterval(anim, 10);
var elemstyle = window.getComputedStyle(elem);
var elemvidth = elemstyle.width;
var current_left_margin = elemstyle.getPropertyValue('margin-left');
var moveto = current_left_margin - 300;
console.log('current_left_margin= ' + current_left_margin );
console.log('moveto= ' + moveto );
var pos = 0;
function anim() {
if (pos == moveto) {
clearInterval(interval);
} else {
pos--;
elem.style.marginLeft = pos + 'px';
}
}
}
This should do:
var current_left_margin = parseInt(elemstyle.getPropertyValue('margin-left'));
If not, then:
var current_left_margin = parseInt(elemstyle.getPropertyValue('margin-left').replace('px', ''));

Javascript how to end a function

There are 4 horses on my track. https://i.imgur.com/xKFTZ8a.png
I press start and the horses are supposed to complete a lap. I have managed to make them go around the first corner and make them stop at the second corner like so https://i.imgur.com/4uwrBiN.png
Heres my code for the white horse, my problem is that the functions are calling each other constantly and due to this I am unable to go around the second corner due to
positionTop >= window.innerHeight * 0.84 - 50
from horse1 function running and preventing the horse from going left.
var interval = 0;
function startRace() {
var raceTimer = setInterval(100);
var raceActive = true;
loop();
}
function loop() {
interval = setInterval(horse1, 10);
interval = setInterval(horse2, 10);
interval = setInterval(horse3, 10);
interval = setInterval(horse4, 10);
}
function horse1() {
var horse1 = document.getElementById('horse1');
var positionLeft = horse1.offsetLeft;
var positionTop = horse1.offsetTop
horse1.className = 'horse runRight'
if (positionLeft >= window.innerWidth * 0.84 - 50) {
horse1down();
} else {
horse1.style.left = positionLeft + 1 + 'px';
}
}
function horse1down() {
var horse1 = document.getElementById('horse1');
var positionTop = horse1.offsetTop;
horse1.className = 'horse runDown'
if (positionTop >= window.innerHeight * 0.85 - 50) {
horse1left()
} else {
horse1.style.top = positionTop + 1 + 'px';
}
}
function horse1left() {
var horse1 = document.getElementById('horse1');
var positionLeft = horse1.offsetLeft
horse1.style.left = positionLeft - 1 + 'px';
horse1.className = 'horse runLeft'
}
function myLoadFunction() {
var startButton = document.getElementById('start');
startButton.addEventListener('click', startRace);
}
document.addEventListener('DOMContentLoaded', myLoadFunction);
What I have tried:
I have tried clear intervals but I might be doing them wrong.
function horse1down() {
var horse1 = document.getElementById('horse1');
var positionTop = horse1.offsetTop;
horse1.className = 'horse runDown'
if (positionTop >= window.innerHeight * 0.85 - 50) {
horse1left()
clearInterval(interval);
interval = setInterval(horse1, 10);
} else {
horse1.style.top = positionTop + 1 + 'px';
}
}
You are overwriting variable interval.Create an array with 4 different intervals and you will be able to clear them separately.
In general its better to use setTimeout insead of setInterval. You can easily rewrite setInterval function to safer setTimeout. setInterval doesn't care whether the callback is still running or not.
In some cases, the function might need longer than the interval time to finish execution. What would happen is that you'll end up with a bunch of queued requests that may not necessarily return in order.

Event on margin change

I have an element with animated top margin. I need to detect if it isn't too close from the border, and if it is, scroll parent div to lower position, to prevent animated element from hiding. Here is an example:
http://jsfiddle.net/zYYBR/5/
This green box shouldn't be below the red line after clicking the "down" button.
Do you mean this?
var new_margin;
var step = 75;
var limit = $("#max")[0].offsetTop;
$('#down').click(function() {
var goStep = step;
var elHeight = $("#animated")[0].offsetTop + $("#animated")[0].offsetHeight;
if((elHeight + step) > limit)
{
goStep = limit - elHeight;
}
new_margin = goStep + parseInt($('#animated').css('margin-top'));
$("#animated").animate({marginTop: new_margin}, 1000);
});
http://jsfiddle.net/zYYBR/8/
EDIT: Or maybe something like that (of course you can improve the calculation, because currently it's very buggy with scroll):
var new_margin;
var step = 75;
$('#down').click(function () {
scroll(1000);
});
var scrollTimer = null;
$("#container").bind("scroll", function () {
clearTimeout(scrollTimer);
scrollTimer = setTimeout(function () { scroll(1); }, 10);
});
function scroll(speed) {
var scrollStep, animationStep = step;
var currentBoxBottom = $("#animated")[0].offsetTop + $("#animated")[0].offsetHeight;
var nextCurrentBoxBottom = currentBoxBottom + step;
var limit = $("#max")[0].offsetTop + $("#container")[0].scrollTop;
if (nextCurrentBoxBottom > limit) {
if (limit >= $("#container")[0].scrollTop) {
scrollStep = $("#container")[0].scrollTop + nextCurrentBoxBottom - limit;
}
else {
scrollStep = $("#container")[0].scrollTop - nextCurrentBoxBottom - limit;
animationStep = nextCurrentBoxBottom - limit;
}
$("#container")[0].scrollTop = scrollStep;
}
new_margin = animationStep + parseInt($('#animated').css('margin-top'));
$("#animated").animate({ marginTop: new_margin }, speed);
}
http://jsfiddle.net/zYYBR/13/
Do you mean something like this?
I have the same visual result as Alex Dn did, but I added a little extra direction to what I think you're talking about. If it's what you're looking for I'll make updates:
var new_margin;
var step = 75;
var limit = $("#max")[0].offsetTop;
$('#down2').click(function() {
var anim = $("#animated");
var hrOff = $("#max").offset();
var thOff = anim.offset();
new_margin = Math.min(hrOff.top - thOff.top - anim.height(), 75);
console.log(new_margin, hrOff.top, thOff.top);
var st = 0;
if (new_margin < 75) {
st = 75 - new_margin;
//have container scroll by this much?
}
anim.animate({
marginTop: "+=" + new_margin
}, 1000);
});​
​
http://jsfiddle.net/zYYBR/10/

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);

Categories

Resources