Randomizing effects on jQuery - javascript

To keep it small and simple, when clicking a button, all the the divs should slide away in random directions and another set of new divs should be displayed.
Basic demo of what the jQuery code is like:
$(document).ready(function() {
$("#toggle_value").click(function(){
$("#div1").show("fast");
$("#div2").show("fast");
$("#div3").show("fast");
});
});
But its all about randomizing the effects. Any solutions?

I would do something like this:
http://jsfiddle.net/8uKt3/13/
$(document).ready(function() {
var $div = $('div'),
pos = [0, 0, 0, 500, 250, 100, 50, -500, -750, -1000, -1500], // Define your numbers
mypos1,
mypos2,
$me;
$("#toggle_value").click(function(){
$div.each(function(){
$me = $(this);
// Choose a value from each array randomly
mypos1 = pos[Math.floor(Math.random() * pos.length)];
mypos2 = pos[Math.floor(Math.random() * pos.length)];
// animate in a random direction in a random quantitya
$me.animate({
'top' : mypos1,
'left': mypos2
});
});
});
});

You can do something like this, lets say you have 3 possible cases for how the divs might slide away:
var rand = Math.random();
if (rand < .33) {
// Some animation
} else if (rand < .66) {
// Some other possible animation
} else {
// Final animation possibility
}

Algorithm:
create an array of 'n' ints
shuffle the array
in the click function:
for each value 'v' in the shuffled array:
$('#div' + v).show('fast')
My guess is that you're going to have introduce a delay in the animation using the completion all back on 'effect' for this to look good, but that should be trivial to do

Related

How to create smarter toggle animation using velocity

I am using velocity.js to deal with animations and its for the most part great. I have a basic demo on codepen that displays a simple toggle button, however the js to make it animate is seemingly very cumbersome.
Whats the best way to deal with toggling animation like that in my example?
var open = false;
$('.filter').click(function(e){
e.preventDefault();
var el = $(this);
if(!open){
el.find('.filter__line:first').velocity({translateY: [0, -5]}, 200, function(){
$(this).addClass('filter__line--thick').velocity({rotateZ: '45deg'}, 200);
});
el.find('.filter__line:last').velocity({translateY: [0, 5]}, 200, function(){
$(this).addClass('filter__line--thick').velocity({rotateZ: '-45deg'}, 200);
});
open = true;
} else {
el.find('.filter__line:first').velocity({rotateZ: '0deg'}, 200, function(){
$(this).removeClass('filter__line--thick').velocity({translateY: [-5, 0]}, 200);
});
el.find('.filter__line:last').velocity({rotateZ: '0deg'}, 200, function(){
$(this).removeClass('filter__line--thick').velocity({translateY: [5, 0]}, 200);
});
open = false;
}
});
http://codepen.io/matt3224/pen/zGgKwP?editors=011
Thanks
I used Velocity for a long time and ran into those sort of problems a lot. I would highly suggest GSAP if you're doing any sort of complex animations. GSAP timelines allow you to easily play, pause, and reverse a series of animations and the syntax is nice and clean. You can find more info on the GSAP website.
I made a quick demo using this technique on Codepen.
Here's what the script looks like:
$(document).ready(function(){
var top = $('.part-1');
var mid = $('.part-2');
var btm = $('.part-3');
var tl = new TimelineMax().pause();
tl.to(mid, 0.3, {x:100, opacity:0})
.to(top, 0.3, {rotation:18, transformOrigin:"left top"},"second")
.to(btm, 0.3, {rotation:-18, transformOrigin:"left bottom"},"second");
var active = false;
$('h1').click(function(){
if(!active){
tl.play();
active = true;
} else {
tl.reverse();
active = false;
}
}); // end of click
}); // end of ready

Keeping seperate track of id attributes in a .animate's step function?

I have a series of blocks that fall, and when they get to a certain point a grey block (placeholder for dust) appears; it goes away if the block bounces up past a certain point, then reappears when the block falls down again, getting smaller each time impact occurs.
Currently, however, since a class for the grey block is what is being affected, any falling block affects the overall size of the "dust" block despite falling and hitting at different times. I would like to keep track of each dust block separately, so each one changes depending on when the color block it is associated with impacts on the ground.
I've tried using ids - id='smoke"+i+"', $("#smoke"+i).height(40+smokeGlobal); - instead of a single class, but it appears doing that only allows the first block to animate. (I assumed a "for" loop is necessary there, but adding that in seemed to cancel the dust block altogether.)
As always, help would be appreciated. Thanks.
http://jsfiddle.net/pjhoL899/1/
JS:
var links = ["#portfolio", "#hamumu", "#beep", "#jk"];
var linkGlobal;
smokeGlobal = 0;
//home page functions
$(document).ready(function homePage() {
//check collisions
//initial animation
for (var i=0; i<links.length; i++) {
//animate links
$(links[i]).animate({
top: '0'
}, {
duration: 2000*(Math.random()*(2)+1),
easing: 'easeOutBounce',
step: function(y) {
if (y >= -2) {
smokeGlobal -= 2;
linkGlobal = $(this);
linkGlobal.html("<div class='smoke' id='smoke"+i+"'></div>");
$(".smoke").height(40+smokeGlobal);
$(".smoke").fadeTo("fast", 0);
}
}, complete: setTimeout(function() {
linkGlobal.html("");
}, 2000)
});
}
})
Edit, updated
Substituted now for y and $(tween.elem) for $(this) at step function. step function argument tween is one of objects within jquery .animate() ; having several properties , including currently animated element (elem) ; easing ; now ; options - which also has queue property (see .queue()).
For each element within the set links , the currently animated property could be retrieved utilizing tween object , along with the elements' animated position between the start and end of the animated property.
At original post , y could actually be utilized as now argument ; and $(this) for linkGlobal . The tween object should give access to the animated element at the specific portion of the animation required ; for adjustment of the element , animation , callback.
To keep track of each dust block separately , can access that element through .fadeTo() callback , or utilize done callback to adjust effects ; done fires before complete . done also has promise which could be utilized to adjust next animated element . There may be several potential options available to adjust features utilizing .animate().
Try (this pattern)
var links = ["#portfolio", "#hamumu", "#beep", "#jk"];
var linkGlobal;
smokeGlobal = 0;
//home page functions
$(document).ready(function homePage() {
//check collisions
//initial animation
for (var i=0; i<links.length; i++) {
//animate links
$(links[i]).animate({
top: '0'
}, {
duration: 2000*(Math.random()*(2)+1),
easing: 'easeOutBounce',
step: function(now, tween) {
console.log(now, tween);
// substituted `now` for `y`
if (now >= -2) {
smokeGlobal -= 2;
// substituted `$(tween.elem)` for `$(this)`
linkGlobal = $(tween.elem);
linkGlobal.html("<div class='smoke' id='smoke"+i+"'></div>");
// adjust "dust" colors ,
// from checking `tween.elem` `backgroundColor` , `now`
var color = linkGlobal.css("background-color");
$(".smoke").eq(0)
.css("background-color"
, color === "yellow" && now < -1.05 ? "purple" : "orange");
$(".smoke").eq(1)
.css("background-color"
, color === "purple" && now < -0.00025 ? "orange" : "pink");
$(".smoke").eq(2)
.css("background-color"
, color === "pink" && now >= -0.0075 ? "purple" : "yellow");
$(".smoke").eq(3)
.css("background-color"
, color === "orange" && now < -0.003 ? "pink" : "purple");
// alert(now);
$(".smoke").height(40+smokeGlobal);
$(".smoke").fadeTo("fast", 0);
}
}, complete: setTimeout(function() {
linkGlobal.html("");
}, 2000)
});
}
});
jsfiddle http://jsfiddle.net/guest271314/pjhoL899/10/

jQuery scrollTo but slow down inbetween

I'm using a simple chunk of code (based of 'ScrollTo Posts with jQuery' which allows you to click a next/previous link and it'll jump through to the top of each post.
I have my HTML structure so it goes post > image > post > image etc.
I'm wondering if it's possible that if you click the next/previous button, it scrolls to the next post as normal, but it hangs/hovers over the images/div inbetween? So it eventually completes it's scroll, but slows down over the divs inbetween.
Here's my jQuery code:
$(function () {
function a(f) {
var b, e, c = [],
d = $(window).scrollTop(),
g = $('.section-slide');
g.each(function () {
c.push(parseInt($(this).offset()['top'], 10))
});
for (e = 0; e < c.length; e++) {
if (f == 'next' && c[e] > d) {
b = g.get(e);
break
}
if (f == 'prev' && e > 0 && c[e] >= d) {
b = g.get(e - 1);
break
}
}
if (b) {
$.scrollTo(b, {
duration: 1400
})
}
return false
}
$('#next,#prev').click(function () {
return a($(this).attr('id'))
});
$('.scrolltoanchor').click(function () {
$.scrollTo($($(this).attr('href')), {
duration: 1400
});
return false
})
});
Assuming your structure will remain static: post -> image -> post -> image etc. you can accomplish this by finding the previous / next image to the post you will be scrolling to, and scrolling to it first, then use the onAfter callback/setting from the $.scrollTo plugin to fire a secondary scroll after a predefined setTimeout like this:
$(function () {
function scroll(direction) {
var scroll, scrollImage, i,
positions = [],
here = $(window).scrollTop(),
collection = $('.post');
collection.each(function () {
positions.push(parseInt($(this).offset()['top'], 10));
});
for (i = 0; i < positions.length; i++) {
if (direction == 'next' && positions[i] > here) {
scroll = collection.get(i);
// Find Image Before Post
scrollImage = $(scroll).prev('.image').get(0);
break;
}
if (direction == 'prev' && i > 0 && positions[i] >= here) {
scroll = collection.get(i - 1);
// Find Image After Post
scrollImage = $(scroll).next('.image').get(0);
break;
}
}
if (scroll) {
// Check if Scroll Image Exists
if (scrollImage){
// Scroll with Image Delay
$.scrollTo(scrollImage, {
duration: 750,
onAfter: function(){
setTimeout(function(){
$.scrollTo(scroll, {
duration: 750
});
}, 1000); // Change the Delay to Increase / Decrease the Hover
}
});
} else {
$.scrollTo(scroll, {
duration: 750
});
}
}
return false;
}
$("#next,#prev").click(function () {
return scroll($(this).attr('id'));
});
$(".scrolltoanchor").click(function () {
$.scrollTo($($(this).attr("href")), {
duration: 750
});
return false;
});
});
You can find an updated fiddle here: http://jsfiddle.net/hfg2v/2/
I hope this helps.
This is happening because you're using a parallax scrolling library (Stellar.js), which makes different elements scroll at different speeds.
A possible fix would be to scroll at a higher speed when no element is in the current viewport until the edge of the next element is just off the screen, then immediately scroll at the original scrolling speed until there are no elements in the viewport again, and keep repeating this until you reach the desired scroll offset.
Edit:
Sorry, something came up while I was writing my answer and I didn't have time to finish the code.
However, after working on it for some time I'm starting to think that my proposed solution wouldn't work. I was thinking something along those lines:
$(window).scrollTo(640, {onAfter: function () {
var scrollRatio = 3;
var distance = 855 - 640;
$(window).scrollTo(855, {
easing: 'linear',
duration: distance * scrollRatio / speed,
onAfter: function () {
var scrollRatio = 1;
var distance = 1200 - 855;
$(window).scrollTo(1200, {
easing: 'linear',
duration: distance * scrollRatio / speed,
onAfter: function () {
var scrollRatio = 3;
var distance = 1280 - 1200;
$(window).scrollTo(1280, {
easing: 'linear',
duration: distance * scrollRatio / speed
});
}
});
}
});
}});
If you paste the previous code in the website provided in the question (http://dev.du.st/field-station/), you'll be taken to the first element, and it will attempt to scroll you to the next one using the method I described. I hardcoded the offset values because I was still experimenting with it. However, I don't think this approach would work since it still feels off. This is because changing instantly speed in the middle of the animation will always be noticeable.
Right now, I think the best way you can mitigate the slow-scrolling feel that parallax scrolling is causing is by using a different easing function. After all, making the background pictures slower, is exactly what you're using parallax scrolling for.
The following code, when ran in your website, would make all animations use 'easeOutCirc' for their easing function by default, after some experimenting, I found it to be the one that makes the scrolling feel least odd:
// Add the jQuery-easing plugin, needed for the more sophisticated easing functions.
$.getScript('//cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js');
// Set easeOutCirc as the default easing.
jQuery.easing.def = 'easeOutCirc';
You can find more easing functions at this website
Once you're done experimenting, if you do decide on using an easing (you can use different ones for scrolling up and down), then you should probably keep the default easing as is, and just change the easing in the scroll animation by adding {easing: EASING_NAME} to your options hash in the scrollTo function. So your code will look something like this:
$.scrollTo($($(this).attr("href")), {
duration: 750,
easing: 'easeOutCirc'
});

overflow: hidden; image scrollBy

I had an idea for like a bus window as a fixed frame, about 800px wide, with a parallax city with the content on billboards spaced out so when you scroll between them it allows the parallax to look like bus is moving. The content will be much bigger than the window like a sprite and I'll put forward and back buttons that will scrollBy (x amount, 0). I have a working parallax script and a rough cityscape of 3 layers that all work fine.
I have hit a wall. I am trying to clear a scrollBy animation after it scrolls 1000px. Then you click it again and it goes another 1000px. This is my function.
function scrollForward() {
window.scrollBy(5,0);
scrollLoop = setInterval('scrollForward()',10);
}
So far I can only clear it when it gets to 1000. I tried doing 1000 || 2000 ect but after the first one it goes really fast and won't clear.
Excelsior https://stackoverflow.com/users/66580/majid-fouladpour wrote a great piece of code for someone else with a different question. It wasn't quite right for what the other guy wanted but it is perfect for me.
function scrollForward() {
var scrolledSoFar = 0;
var scrollStep = 75;
var scrollEnd = 1000;
var timerID = setInterval(function() {
window.scrollBy(scrollStep, 0);
scrolledSoFar += scrollStep;
if( scrolledSoFar >= scrollEnd ) clearInterval(timerID);
}, 10);
}
function scrollBack() {
var scrolledSoFar = 0;
var scrollStep = -75;
var scrollEnd = -1000;
var timerID = setInterval(function() {
window.scrollBy(scrollStep, 0);
scrolledSoFar += scrollStep;
if( scrolledSoFar <= scrollEnd ) clearInterval(timerID);
}, 10);
}
Now for step two figuring out how to put this content animation behind a frame.
Not quite sure what your asking here. Perhaps you could provide more relevant code?
I do see a potential issue with your code. You call setInterval('scrollForward()', 10) which will cause scrollForward to be called every 10ms. However, each of those calls to scrollForward will create more intervals to scrollForward creating a sort of explosion of recursion. You probably want to use setTimeout or create your interval outside of this function.
Also, as an aside you can change your code to simply: setInterval(scrollForward, 10). Removing the quotes and the parens makes it a littler easier to read and manager. You can even put complex, lambda functions like:
setInterval(function() {
scrollForward();
// do something else
}, 10);
edit:
So if you know that scrollForward moves the item 10px, and you want it to stop after it moves the item 1000px, then you simply need to stop it has moved that much. I still don't know how your code is actually structured, but it might look something like the following:
(function() {
var moved_by = 0;
var interval = null;
var scrollForward = function() {
// move by 10px
moved_by += 10;
if (moved_by === 1000 && interval !== null) {
clearInterval(interval);
}
};
var interval = setInterval(scrollForward, 10);
})();
If you want to clear it after 1000 or 2000, you simply adjust the if statement accordingly. I hope that helps.

Stop animation and reset position of an element in Raphaƫl.js

I have this simple animation that moves from side to side, Im trying to create a reset button so that the animation stops and gets back to default, but I cant seem to get i right.
The library I am using is Raphael, but I'm almost sure that with a simple javascript I can reset the values inside the function.
Body onload init function
function init() {
paper = Raphael("loadSVG");
var bg = paper.rect( 0, 0, "240px", "90px", 0 );
bg.attr( {fill: "#f3f3ff"} );
rect1 = paper.rect(150, 20, 50, 50);
rect1.attr( {fill: "#ffaaaa", "stroke-width": 3} );
}
The animation function
function moveRect1() {
if( xEnd == 150 )
xEnd = 50;
else
xEnd = 150;
rect1.animate( {x: xEnd}, 1000, "Sine", function (){
moveRect1();
});
}
and the stop button that don't work :)
function stopsvgRect1() {
rect1.stop();
}
You need to bind the stop button to the function you've created.
For example like this:
document.querySelector('#stop').onclick = function() {
stopsvgRect1();
};
Open this fiddle to see it in action.
edit:
As the position should also be resetted, you can choose Raphael.transform() for this action.
Open my updated fiddle to see how it works.

Categories