jquery infinite loop (to move a div position) - javascript

I have the following jquery code to move a rectangle from one place to another. It works.
jQuery(function ($) {
$(document).ready(function () {
loop_pos = function () {
var docHeight = $(document).height(),
docWidth = $(document).width(),
$div = $('#test'),
divWidth = $div.width(),
divHeight = $div.height(),
heightMax = docHeight - divHeight,
widthMax = docWidth - divWidth;
$div.css({
left: Math.floor(Math.random() * widthMax),
top: Math.floor(Math.random() * heightMax)
// here
});
}
// or here
});
});
Now, I want to make this rectangle change its position automatically in a infinite loop.
I tried to call the function loop_pos, in //here also // or here, but it doesn't work and I don't know how to do it.
Another solution maybe setTimeout() but I can't make it work.
Please a little help. Thanks.

First, refactor so that you don't compute widths and heights at every function call.
Then use setInterval to call a function every n milliseconds :
jQuery(function($) {
// No need for document.ready cause jQuery is made to execute this function when the doc is ready.
// initialize variables
var $div = $('#test'),
delay = 1000, // ms
docHeight,
docWidth,
divWidth,
divHeight,
heightMax,
widthMax;
function onResize(){
//update them
docHeight = $(document).height();
docWidth = $(document).width();
divWidth = $div.width();
divHeight = $div.height();
heightMax = docHeight - divHeight,
widthMax = docWidth - divWidth;
}
function loop_pos(){
$div.css({
left: Math.floor(Math.random()*widthMax),
top: Math.floor(Math.random()*heightMax)
// here
});
}
// Calculate for the first time
onResize();
// Add event listener
$(window).resize(onResize);
// run loop
setInterval(loop_pos, delay); // 1000 ms = 1 second
});
See fiddle :
http://jsfiddle.net/5f4quu8u/

"or here" is your answer, just refactor your code to prevent running your DOM for sizes when it's not needed:
jsFiddle demo
$(document).ready(function() {
var $div = $('#test'), x, y;
function getSizes(){
x = $(document).width() - $div.width();
y = $(document).height() - $div.height();
}
function loop_pos(){
$div.css({ // or use `.animate` instead of `.css`
left: ~~(Math.random() * x),
top: ~~(Math.random() * y)
});
}
getSizes(); // Get them immediately
$("window").on("resize", getSizes); // Update values on Win. resize
setInterval(loop_pos, 1000);
});

Well, I would first move your code outside the $(document).ready()-part and declare it as a separate function.
function moveDiv(){
var docHeight = $(document).height();
docWidth = $(document).width();
$div = $('#test');
divWidth = $div.width();
divHeight = $div.height();
heightMax = docHeight - divHeight;
widthMax = docWidth - divWidth;
$div.css({
left: Math.floor(Math.random()*widthMax),
top: Math.floor(Math.random()*heightMax)
});
}
Then you can use the SetInterval-function in javascript.
$(document).ready(function() {
var delay = 1*1000; //would move the div every 1 second
setInterval( moveDiv , delay );
});
That should do it I think. (Given that your code works which it seems to me it should!)

Related

Randomly re-place a div element when an animated div crosses coordinates

I am making a simple web game where can use arrow keys to move a div around the page with the goal of colliding it with another div. The second div will then be randomly placed somewhere else on the page. My question is, how can I change to following code to relocate the second div apon collision?
I have code that does this when the div is clicked
$('#test').click(function() {
var docHeight = $(document).height(),
docWidth = $(document).width(),
$div = $('#test'),
divWidth = $div.width(),
divHeight = $div.height(),
heightMax = docHeight - divHeight,
widthMax = docWidth - divWidth;
$div.css({
left: Math.floor( Math.random() * widthMax ),
top: Math.floor( Math.random() * heightMax )
});
});
I am looking to do this in jquery, js, or angular. Any help is appreciated.
Maybe something like https://api.jquery.com/offset/ :
$('moving_div').click(function(){ // or the action you make the div move
if ( $('#moving').offset().left == $('#target').offset().left && $('#moving').offset().top == $('#target').offset().top ) {
$('target_div').css({
left: Math.floor( Math.random() * widthMax ),
top: Math.floor( Math.random() * heightMax )
});
}
});
like this one: http://jsfiddle.net/7seqdp3b/

How to use math.random() with for loop

I want to change the position of div with for loop ..
I made an animation .. When i click a div ( circle ) it moves to a position that is being determined with Math.random() ..
I dont want to click the div to move to another position .
I want to use for loop method and i want div to move another position in every 2 seconds or some seconds ..
Do you have any advise .. Thanks
Click to see how it is
$(document).ready(function () {
$("#circle").click(function () {
var width = Math.random();
var yeniwidth = width * 500;
margin = Math.round(yeniwidth);
$("#circle").css("margin-top", margin + "px");
var height = Math.random();
var yeniheight = height * 1000;
margin2 = Math.round(yeniheight);
$("#circle").css("margin-left", margin2 + "px");
});
});
Codepen
You don't really need a for-loop to do that. Instead of executing the code after clicking the div, you could just use the setInterval function instead:
$(document).ready(function () {
window.setInterval(function(){
var width = Math.random();
var yeniwidth = width * 500;
margin = Math.round(yeniwidth);
$("#circle").css("margin-top", margin + "px");
var height = Math.random();
var yeniheight = height * 1000;
margin2 = Math.round(yeniheight);
$("#circle").css("margin-left", margin2 + "px");
}, 5000);
});
Just change the number 5000 to adjust the time that should pass before the code is executed again (1000ms is 1 second).
On Codepen

making a function works on specific widths

I am trying to make this function works only when the screen size is above 1024px.
//Parallax background image
var velocity = 0.5;
function update(){
var pos = $(window).scrollTop();
$('.parallax').each(function() {
var $element = $(this);
var height = $element.height();
$(this).css('background-position', '40%' + Math.round((height - pos) * velocity) + 'px');
});
};$(window).bind('scroll', update); update();
Here is what I have tried to do:
//Parallax background image
var velocity = 0.5;
$(window).on("ready resize", function() {
if ($(window).width() < 770) {
function update(){
var pos = $(window).scrollTop();
$('.parallax').each(function() {
var $element = $(this);
var height = $element.height();
$(this).css('background-position', '40%' + Math.round((height - pos) * velocity) + 'px');
});
};});$(window).bind('scroll', update); update();
I really don't know what I am doing wrong...
You haven't stated what the problem you're coming across is. If it's "my code doesn't work", then perhaps you should check your syntax first. Your braces are messed up.
//Initialize velocity and empty update function
var velocity = 0.5;
var update = function () {};
//When window is ready (content loaded) OR resized, execute the following function
$(window).on("ready resize", function () {
if ($(window).width() >= 1024) { //Check if window width is 1024px wide or larger
update = function () { //Set update to run this function when executed.
var pos = $(window).scrollTop(); //Get scrollbar position https://api.jquery.com/scrollTop/
//For each element with 'parallax' class, execute the following function
$('.parallax').each(function () {
var $element = $(this); //Get the current parallax-classed element
var height = $element.height(); //Save the current height of this element
//Set the CSS of this parallax-classed element set the background position
$(this).css('background-position', '40% + ' + Math.round((height - pos) * velocity) + 'px');
});
};
} else { //Execute if screen width is < 1024px
update = function () {}; //Set update to do nothing
}
});
//When window is scrolled through, run the update function
$(window).bind('scroll', update);
//update();
Last line is unnecessary, as resize will handle function value, and scroll will handle the execution.
You were missing a + or - within the background-position setting.
So for example, if the result of your Math.round() was "30", then Javascript would interpret that line as $(this).css('background-position', '40%30px'); which obviously would cause issues. I'm sure you wanted it to say something like $(this).css('background-position', '40% + 30px');.

Adding ease to a jquery animation

Hi i found this animation, which i would like to use to give my navigation links a tiny, gentle random movement, but it just doesn't look very smooth. http://jsfiddle.net/2TUFF/
(Random Movement in a Fixed Container)
$(document).ready(function() {
animateDiv();
});
function makeNewPosition($container) {
// Get viewport dimensions (remove the dimension of the div)
$container = ($container || $(window))
var h = $container.height() - 50;
var w = $container.width() - 50;
var nh = Math.floor(Math.random() * h);
var nw = Math.floor(Math.random() * w);
return [nh, nw];
}
function animateDiv() {
var $target = $('.a');
var newq = makeNewPosition($target.parent());
var oldq = $target.offset();
var speed = calcSpeed([oldq.top, oldq.left], newq);
$('.a').animate({
top: newq[0],
left: newq[1]
}, speed, function() {
animateDiv();
});
};
function calcSpeed(prev, next) {
var x = Math.abs(prev[1] - next[1]);
var y = Math.abs(prev[0] - next[0]);
var greatest = x > y ? x : y;
var speedModifier = 0.1;
var speed = Math.ceil(greatest / speedModifier);
return speed;
}​
I've tried playing around with container size and speed but that doesn't help a lot, I also tried adding easing to the jquery myself but I have no knowledge of that mastery and failed.
Thanks!
I believe you need http://ijin.net/crSpline/demo.html for smooth "light breeze" animations.
Related answer: how to smooth jquery animations
Here is a full example in fiddle using jQuery.crSpline:
http://jsfiddle.net/2TUFF/295/

function is setting all instead of each

I have a simple function that sets the width of a bar based on an argument.
And I call the function on .each with jQuery.
The console logs the statement correctly, showing me it seems to work. However, the style seems to be overridden by the last value found.
Here is the function:
function barGraph(innerWidth, barWidth) {
innerWidth = parseInt(innerWidth) * .01 || .50;
barWidth = parseInt(barWidth) || 267;
// find percentage of total width
var innerWidth = Math.floor(innerWidth * barWidth);
var $innerBar = $('.slider-box div');
$innerBar.css('width', innerWidth + 'px');
console.log("Width should be: " + innerWidth + 'px');
}
then i call the function on each with jQuery:
$(document).ready(function() {
var $innerBar = $('.slider-box div');
$innerBar.each(function(index) {
var newWidth = $(this).attr("data-bar-width");
barGraph(newWidth, 267);
});
});
the console log shows 10 times, with all appropriate widths. However, the style for all is the same as the last width.
Can someone help explain how I get the function to set the width of the currently selected div?
Thanks so much in advance,
Adam.
Let's break it down
$(document).ready(function() {
var $innerBar = $('.slider-box div');
// going to call the barGraph function on each matching element
// so far, so good
$innerBar.each(function(index) {
var newWidth = $(this).attr("data-bar-width");
barGraph(newWidth, 267);
});
});
Then in barGraph
function barGraph(innerWidth, barWidth) {
innerWidth = parseInt(innerWidth) * .01 || .50;
barWidth = parseInt(barWidth) || 267;
// find percentage of total width
var innerWidth = Math.floor(innerWidth * barWidth);
// getting all the matching elements (again)
var $innerBar = $('.slider-box div');
// setting the width of each matched element to
// the innerwidth calculated in this barGraph call.
$innerBar.css('width', innerWidth + 'px');
console.log("Width should be: " + innerWidth + 'px');
}
So, the barGraph function is run as many times as there are matched elements in $('.slider-box div'), but each run sets the width of all matched elements. In effect, the last run will set the width of all matched elements to whatever the innerWidth is calculated to be on the last run. Is that what you want to happen?
What is more likely is perhaps something like this
$(function() {
var $innerBar = $('.slider-box div');
// going to call the barGraph function on each matching element
// so far, so good
$innerBar.each(function(index) {
var bar = $(this),
newWidth = bar.attr("data-bar-width");
barGraph(bar, newWidth, 267);
});
function barGraph(bar, innerWidth, barWidth) {
innerWidth = parseInt(innerWidth, 10) * .01 || .50;
barWidth = parseInt(barWidth, 10) || 267;
innerWidth = Math.floor(innerWidth * barWidth);
bar.css('width', innerWidth + 'px');
console.log("Width should be: " + innerWidth + 'px');
}
});
If the barGraph function is not used outside of the each call, then I might be inclined to move the function body inside of the anonymous function passed to each or modify barGraph function to be the function passed to each i.e.
$(function() {
$('.slider-box div').each(barGraph);
function barGraph(index, element) {
var bar = $(this),
newWidth = bar.attr("data-bar-width");
newWidth = parseInt(newWidth , 10) * .01 || .50;
newWidth = Math.floor(innerWidth * 267);
bar.css('width', newWidth + 'px');
console.log("Width should be: " + newWidth + 'px');
}
});
the problem is in here, have a look at your barGraph function:
var $innerBar = $('.slider-box div'); //here you choose all divs inside .slider-box
$innerBar.css('width', innerWidth + 'px'); //and set the width for all of them
change the barGraph function:
function barGraph(innerWidth, barWidth) {
innerWidth = parseInt(innerWidth) * .01 || .50;
barWidth = parseInt(barWidth) || 267;
// find percentage of total width
var innerWidth = Math.floor(innerWidth * barWidth);
var $innerBar = $('.slider-box div');
$innerBar.each(function(index){
$(this).css('width', innerWidth + 'px');
});
console.log("Width should be: " + innerWidth + 'px');
}
this may happen bacause on last barGraph() call you set all $('.slider-box div');
with last value you read into the each()
what if you try something like this
function barGraph(el, innerWidth, barWidth) {
...
el.css('width', innerWidth + 'px');
console.log("Width should be: " + innerWidth + 'px');
}
$(document).ready(function() {
var $innerBar = $('.slider-box div');
$innerBar.each(function(index, el) {
var newWidth = $(el).attr("data-bar-width");
barGraph($(el), newWidth, 267);
});
});
in this approach I passed a jQuery reference to each element, to the barGraph() function. It's also less expensive than before, since you always create a jQuery reference to a div collection.
In your barGraph function you select all instances of .slider-box div and set the width. You only want to set the one you are currently working with.
function barGraph($bar, innerWidth, barWidth) {
innerWidth = parseInt(innerWidth) * .01 || .50;
barWidth = parseInt(barWidth) || 267;
// find percentage of total width
var innerWidth = Math.floor(innerWidth * barWidth);
$bar.css('width', innerWidth + 'px');
console.log("Width should be: " + innerWidth + 'px');
}
by passing the bar into barGraph during the loop.
$(document).ready(function() {
var $innerBar = $('.slider-box div');
$innerBar.each(function(index) {
var $bar = $(this)
, newWidth = $bar.attr("data-bar-width");
barGraph($bar, newWidth, 267);
});
});
You may also want to move the selection of the width into the barGraph function to keep things clean.
Like most of jQuery's functions, css() works on collections as well as on single elements. Since $('.slider-box div') returns a collection, the CSS rule will be applied to all of the divs on every iteration of the each loop. So for 10 divs, barGraph will be called 10 × 10 = 100 times. And because the divs stay in the same order, the newWidth of the last div will be applied to all of the divs.
To apply the newWidth only to the current element in the each loop, you could keep all your logic inside that function:
var $innerBar = $('.slider-box div');
$('.slider-box div').each(function(index, element) {
var $this = $(this);
var innerWidth = ($this.attr("data-bar-width") / 10) || 0.5;
var barWidth = 267;
innerWidth = Math.floor(innerWidth * barWidth);
$this.css('width', innerWidth); // Note: no need to append 'px'; jQuery
});
This works pretty well as long as the logic is simple (a couple of lines at most) and you don't need to use it elsewhere. But when your code gets a bit more complex, you might want to brake it out into a separate function. Since you had already done this, let's look at some other solutions.
Two common solutions:
Eiter: pass the current element as a parameter of the function;
or: make it into a jQuery plugin.
The first is pretty simple:
function barGraph(element, innerWidth, barWidth) {
var $this = $(element);
// et cetera
}
// Call like this:
$('.slider-box div').each(function(index) {
var newWidth = $(this).attr("data-bar-width");
barGraph(this, newWidth, 267);
});
Like I said: simple. But it's not very neat, is it? The second solution is a bit more elegant:
$.fn.barGraph = function(barWidth) {
var $this = this; // `this` is already a jQuery object
var innerWidth = ($this.attr("data-bar-width") / 10) || 0.5;
barWidth = barWidth || 267;
innerWidth = Math.floor(innerWidth * barWidth);
$this.css('width', innerWidth);
};
// Use like this:
$('.slider-box div').each(function(index) {
$(this).barGraph(267);
});
And that's how easy it is to write your own jQuery plugin! Of course, it can use a little work, like a more descriptive name and support for chainability.

Categories