Here's my code
(function ($) {
$.fn.snow2 = function (options) {
var $flake = $('<a style="text-decoration: none;" href="/flake"><div id="flake" /></a>').css({
'position': 'absolute',
'top': '-50px',
'z-index': '100'
}).html('❄'),
documentHeight = $(document).height(),
documentWidth = $(document).width(),
defaults = {
minSize: 30,
maxSize: 50,
newOn: Math.floor(Math.random() * 14000) + 7000,
flakeColor: "#CE1126"
},
options = $.extend({}, defaults, options);
var interval = setInterval(function () {
var startPositionLeft = Math.random() * documentWidth - 100,
startOpacity = 0.5 + Math.random(),
sizeFlake = options.minSize + Math.random() * options.maxSize,
endPositionTop = documentHeight - 40,
endPositionLeft = startPositionLeft - 100 + Math.random() * 200,
durationFall = documentHeight * 10 + Math.random() * 5000;
$flake
.clone()
.appendTo('body')
.css({
left: startPositionLeft,
opacity: startOpacity,
'font-size': sizeFlake,
color: options.flakeColor
})
.animate({
top: endPositionTop,
left: endPositionLeft,
opacity: 0.2
},
durationFall,
'linear',
function () {
$(this).remove()
}
);
}, options.newOn);
};
})(jQuery);
I am trying to get it to spit out a snow flake at a random interval like 7000 and 14000 milliseconds, the problem is when I call the function it gets a random number between 7000 and 14000 and uses that same value over and over again. So say it returns 12806, it will spit out a snow flake every 12806 milliseconds. I want a new number each time. How would I go about accomplishing this? I cannibalized this code from something kinda different and am not very experienced with JavaScript or jQuery. Any help is appreciated.
The problem is setInterval, which does exactly what you are complaining about. I think you'd rather use setTimeout. From the Mozilla Developer Network:
setTimeout() calls a function or executes a code snippet after specified delay.
setInterval() calls a function or executes a code snippet repeatedly, with a fixed time delay between each call to that function.
Yes I would use setTimeout and call the function itself with a new timeout value. Also I would set newOn to a function instead of a variable since it will only be calculated once as a variable.
See if this fiddle behaves like you want: http://jsfiddle.net/e9KE9/1/
In the fiddle I set the first Timeout to 0 so that the first would appear immediately.
P.s.s this feels more like snow: http://jsfiddle.net/e9KE9/2/ Pretty cool idea!
$.fn.snow2 = function (options) {
var $flake = $('<a style="text-decoration: none;" href="/flake"><div id="flake" /></a>').css({
'position': 'absolute',
'top': '-50px',
'z-index': '100'
}).html('❄'),
documentHeight = $(document).height(),
documentWidth = $(document).width(),
defaults = {
minSize: 30,
maxSize: 50,
newOn: function(){return Math.floor(Math.random() * 14000) + 7000},
flakeColor: "#CE1126"
},
options = $.extend({}, defaults, options);
function newFlake() {
var startPositionLeft = Math.random() * documentWidth - 100,
startOpacity = 0.5 + Math.random(),
sizeFlake = options.minSize + Math.random() * options.maxSize,
endPositionTop = documentHeight - 40,
endPositionLeft = startPositionLeft - 100 + Math.random() * 200,
durationFall = documentHeight * 10 + Math.random() * 5000;
$flake
.clone()
.appendTo('body')
.css({
left: startPositionLeft,
opacity: startOpacity,
'font-size': sizeFlake,
color: options.flakeColor
})
.animate({
top: endPositionTop,
left: endPositionLeft,
opacity: 0.2
},
durationFall,
'linear',
function () {
$(this).remove()
}
);
setTimeout(newFlake, options.newOn());
};
setTimeout(newFlake, options.newOn());
}(jQuery);
Related
I have this piece of code:
var delta = _window.width() / 30, // resize hexagons by delta px
window_height = _window.height(); // .box-1/window height
$('.hexagon').each(function () { // get animated boxes
var $this = $(this),
width_1 = $this.width(),
height_1 = $this.height(),
multi = 0, // adjust resize to scroll speed (depends on delta)
ratio = 1.167; // to calculate height
// animation properties
var enlarge_obj = {
width: function() {return width_1 += (delta * multi)},
height: function() {return width_1 * ratio}
},
shrink_obj = {
width: function() {return width_1 -= (delta * multi)},
height: function() {return width_1 * ratio}
};
....
function scrollHandler() {
...
$this.animate(enlarge_obj, 0, 'linear');
...
$this.animate(shrink_obj, 0, 'linear');
}
}
I want to pass enlarge_obj and shrink_obj to jQuery animate function.
But it doesn't work.
If I write code like this:
$this.animate({width: width_1 += (delta * multi), height: width_1 * ratio},0,'linear');
it works fine.
What am I doing wrong? Thx.
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.
I have created a random fishes animation but at some point (about 10sec) from the beginning, my fishes Cling to the right, i want them to keep moving in random all over the area, any idea?
here is the fiddle link: http://jsfiddle.net/832Fx/1/
jquery code:
$.fn.rotate = function (degrees) {
var self = $(this);
self.transition({
rotateY: degrees + 'deg'
}, 5000);
};
var animeVars = {
maxPixelsPerSecond: 50,
minPixelsPerSecond: 10,
topMargin: 0,
bottomMargin: 400,
leftMargin: 0,
rightMargin: 400
};
function topFlip(obj) {
var speed = $(obj).data('speed') ? (1 / parseFloat($(obj).data('speed'))) * 1000000 : 300;
$(obj).find('.top_fin, .top_fins').transition({
rotate: '+=25deg',
x: '+=10'
}, speed, function () {
$(obj).find('.top_fin, .top_fins').transition({
rotate: '-=25deg',
x: '-=10'
}, speed, function () {
topFlip(obj);
});
});
}
function tailFlip(obj) {
var speed = $(obj).data('speed') ? (1 / parseFloat($(obj).data('speed'))) * 1000000 : 300;
$(obj).find('.tail_fin, .tail_fins').transition({
rotateX: '-=25deg'
}, speed, function () {
$(obj).find('.tail_fin, .tail_fins').transition({
rotateX: '+=25deg'
}, speed, function () {
tailFlip(obj);
});
});
}
function animateFish(obj) {
var heading = $(obj).data('heading');
if (!heading) heading = 'left';
var rotation = 0;
var currentCoords = {
top: parseInt($(obj).css('top').replace(/[^-\d\.]/g, ''), 10),
left: parseInt($(obj).css('left').replace(/[^-\d\.]/g, ''), 10)
};
var newCoords = {
top: Math.random() * (animeVars.topMargin - animeVars.bottomMargin + 1) + animeVars.bottomMargin,
left: Math.random() * (animeVars.leftMargin - animeVars.rightMargin + 1) + animeVars.rightMargin
};
if (currentCoords.left < newCoords.left && heading != 'right') {
$(obj).rotate(180);
$(obj).data('heading', 'right');
console.log('swimming right');
} else if (currentCoords.left > newCoords.left && heading != 'left') {
$(obj).rotate(0);
$(obj).data('heading', 'left');
console.log('swimming left');
}
var totalMovement = Math.sqrt(Math.pow(currentCoords.left - newCoords.left, 2) + Math.pow(currentCoords.top - newCoords.top, 2));
console.log('Total pixels to move: ' + totalMovement);
var pps = Math.floor(Math.random() * (animeVars.maxPixelsPerSecond - animeVars.maxPixelsPerSecond)) + animeVars.maxPixelsPerSecond;
var speed = totalMovement / pps * 1000;
$(obj).data('speed', speed);
$(obj).animate({
top: newCoords.top,
left: newCoords.left
}, speed, function () {
animateFish(obj);
});
}
$(document).ready(function () {
$('.loop ').each(function () {
animateFish(this);
topFlip(this);
tailFlip(this);
});
});
Here is how I would fix this: http://jsfiddle.net/BaliBalo/832Fx/2/
I just added
var $wnd = $(window);
$wnd.resize(function() {
animeVars.rightMargin = $wnd.width();
animeVars.bottomMargin = $wnd.height();
}).resize();
at the end of your code, and changed the algorithm a bit to take in account fishes size:
var w = $(obj).width();
var h = $(obj).height();
var newCoords = {
top: Math.random() * (animeVars.topMargin - animeVars.bottomMargin + h + 1) + animeVars.bottomMargin - h,
left: Math.random() * (animeVars.leftMargin - animeVars.rightMargin + w + 1) + animeVars.rightMargin - w
};
However, please note that many optimizations could be done, like caching jQuery objects in variables rather than calling the $ function every time.
I have 5 divs layered and a object in the foreground I want to move across them. This is using the paralax effect. I have been sucessfully able to move the object using basic .animate in jQuery.
The problem I'm having is getting the background divs to animate properly - or at all. What happens is when I click on my trigger div - the div.cloud1 and div.cloud2 move BEFORE my object does. They also change positions despite my playing with the timing values.
All objects in the divs are absolutely positioned - the divs are relative for being able to use z-index.
Specifically I'm trying to move div.cloud1, div.cloud2, div.ground, div.Mountain all at different speeds so it gives the illusion of 3d.
The object I'm sending across is a different div.
I'm not sure what the problem is.
Here is my JSfiddle: http://jsfiddle.net/U6Mu6/
jQuery(document).ready(function () {
jQuery('#cloud-01').css({
backgroundPosition: '50 -180px'
});
jQuery('#cloud-02').css({
backgroundPosition: '0 -100px'
});
jQuery('#mountains-03').css({
backgroundPosition: '0 50px'
});
jQuery('#trees-04').css({
backgroundPosition: '0 50px'
});
jQuery('#ground').css({
backgroundPosition: 'left bottom'
});
jQuery('#branding').css({
backgroundPosition: 'center 0'
});
jQuery('#content').css({
backgroundPosition: 'center 0'
});
jQuery('#sec-content').css({
backgroundPosition: 'center 0'
});
jQuery('#footer').css({
backgroundPosition: 'center 0'
});
jQuery('#wrapper').css({
overflow: "hidden"
});
jQuery('#klicker').click(function () {
jQuery('#cloud-01').animate({
backgroundPosition: '(-100px -10px)'
}, 200000);
jQuery('#cloud-02').animate({
backgroundPosition: '(-400px 0px)'
}, 20000);
jQuery('#mountains-03').animate({
backgroundPosition: '(-2500px 50px)'
}, 20000);
jQuery('#ground').animate({
backgroundPosition: '(-5000px bottom)'
}, 20000);
startHim();
jQuery("#full-robot").animate({
left: "50%",
marginLeft: "-150px"
}, 2000);
setTimeout("leaveScreen()", 15000);
});
});
var num = 1;
function startHim() {
num++;
jQuery("#sec-content").animate({
top: "-=5px"
}, 150).animate({
top: "+=5px"
}, 150);
jQuery("#content,#branding").animate({
top: "-=" + num + "px"
}, 150).animate({
top: "+=" + num + "px"
}, 150);
if (num < 4) {
setTimeout("startHim()", 300);
} else {
setTimeout("bounceHim()", 300);
}
}
function bounceHim() {
jQuery("#sec-content,#branding").animate({
top: "-=4px"
}, 150).animate({
top: "+=4px"
}, 150);
jQuery("#content").animate({
top: "-=8px"
}, 150).animate({
top: "+=8px"
}, 150);
setTimeout("bounceHim()", 300);
}
function leaveScreen() {
jQuery("#full-robot").animate({
left: "100%",
marginLeft: "0px"
}, 2000);
}
Just FYI - some of the objects in the fiddle are not included on purpose. I just want to get things working first.
I did see a error in JSFIDDLE dealing with implied eval on my setTime expression. But I'm not sure how to fix it. I suppose I could pass the div as function and use .hide instead.
All help is welcome thanks!
EDIT:::
I forgot this:
/**
* v. 1.02
*/
(function($) {
$.extend($.fx.step,{
'background-position': function(fx) {
if (fx.state === 0 && typeof fx.end == 'string') {
var start = $.curCSS(fx.elem,'background-position');
start = toArray(start);
fx.start = [start[0],start[2]];
var end = toArray(fx.end);
fx.end = [end[0],end[2]];
fx.unit = [end[1],end[3]];
}
var nowPosX = [];
nowPosX[0] = ((fx.end[0] - fx.start[0]) * fx.pos) + fx.start[0] + fx.unit[0];
nowPosX[1] = ((fx.end[1] - fx.start[1]) * fx.pos) + fx.start[1] + fx.unit[1];
fx.elem.style.backgroundPosition = nowPosX[0]+' '+nowPosX[1];
function toArray(strg){
strg = strg.replace(/left|top/g,'0px');
strg = strg.replace(/right|bottom/g,'100%');
strg = strg.replace(/([0-9\.]+)(\s|\)|$)/g,"$1px$2");
var res = strg.match(/(-?[0-9\.]+)(px|\%|em|pt)\s(-?[0-9\.]+)(px|\%|em|pt)/);
return [parseFloat(res[1],10),res[2],parseFloat(res[3],10),res[4]];
}
}
});
})(jQuery);// JavaScript Document
I don't know if this is too obvious, but your trying to set the "background-position"attribute of the clouds by using backgroundPosition
You might just change them to
$("#cloud-01").css({'background-position': '50px -180px'})
Notice the background-position instead of backgroundPosition
If you want to stagger the time each cloud takes to move, you need to offset your animation durations, like
$('#cloud-01').animate({
'background-position' : '(-100px -10px)'
}, (1000) ); // 1 second duration
$('#cloud-02').animate({
'background-position' : '(-400px 0px)'
}, (2000) ); // 2 seconds
$('#mountains-03').animate({
'background-position' : '(-2500px 50px)'
}, (2000) ); // 3 seconds
Has anyone set up a nivo slider to pan each image (aka Ken Burns effect)? I'm trying to implement it and it's kinda tricky!
Actually, I got my implementation working!
I have a panning function loop.. something like this:
function ken_burns_loop(el) {
$(el)
.animate({
'background-position-x': '40%',
'background-position-y': '60%'
}, 8000, 'linear')
.animate({
'background-position-x': '30%',
'background-position-y': '40%'
}, 8000, 'linear')
.animate({
'background-position-x': '70%',
'background-position-y': '70%'
}, 8000, 'linear', function() { ken_burns_loop(el); });
}
And I'm initializing nivo slider like this:
$('#welcome-slider').nivoSlider({
effect: 'fade',
slices: 1,
directionNav: false,
afterChange: function() {
$('#welcome-slider, .nivo-slice').stop(true);
ken_burns_loop('#welcome-slider, .nivo-slice');
}
});
ken_burns_loop('#welcome-slider, .nivo-slice');
I'm still working out some problems with positioning.
Source & Demo
Add this to your JS:
if(currentEffect === 'kenburns'){
createZoom(slider, settings, vars);
zoom = $('.nivo-zoom:last', slider);
var delta = (8 + Math.random() * 2) / 100;
var neww = zoom.width() * (1 + delta);
var newh = zoom.height() * (1 + delta);
var x = delta * zoom.width(); //Math.random()*(neww-zoom.width());
var y = delta * zoom.height(); //Math.random()*(newh-zoom.height());
var zoomdir = Math.round(Math.random() * 4);
zoom.animate({ opacity:'1.0'}, {easing:'linear',duration:settings.pauseTime*2/3});
if(zoomdir == 1) {
zoom.find('img').animate({ height:newh+'px',width:neww+'px',left: '-'+x+'px',top: '-'+y+'px'},{easing:'linear',duration:settings.pauseTime*4/3, complete: function(){ slider.trigger('nivo:animFinished'); }});
} else if(zoomdir == 2) {
zoom.find('img').animate({ height:newh+'px',width:neww+'px',right: '-'+x+'px',top: '-'+y+'px'}, {easing:'linear',duration:settings.pauseTime*4/3, complete: function(){ slider.trigger('nivo:animFinished'); }});
} else if(zoomdir == 3) {
zoom.find('img').animate({ height:newh+'px',width:neww+'px',right: '-'+x+'px',bottom: '-'+y+'px'}, {easing:'linear',duration:settings.pauseTime*4/3, complete: function(){ slider.trigger('nivo:animFinished'); }});
} else {
zoom.find('img').animate({ height:newh+'px',width:neww+'px',left: '-'+x+'px',bottom: '-'+y+'px'}, {easing:'linear',duration:settings.pauseTime*4/3, complete: function(){ slider.trigger('nivo:animFinished'); }});
}
if($('.nivo-zoom', slider).length > 2) $('.nivo-zoom:first', slider).remove();
}