So, I have a page, where when a user holds left mouse button, Shrek images are drawn where his/her cursor is. The problem is, only one picture is created when the mouse is down, but I need an ENDLESS CURRENT OF SHREKS.
Here is the code:
var shrekId = 0;
document.onmousemove = function(event) {
mouseX = event.clientX;
mouseY = event.clientY;
}
window.addEventListener('selectstart', function(e){ e.preventDefault(); });
document.body.onmousedown = function(event) {
shrekId = 0;
interval = setInterval(draw(event), 100);
}
document.body.onmouseup = function() {
clearInterval(interval);
}
function draw(event) {
this["img" + shrekId] = document.createElement("img");
this["img" + shrekId].src = "http://pngimg.com/uploads/shrek/shrek_PNG3.png";
this["img" + shrekId].style = "height: 100px; width: 100px; position: absolute; left: " + (mouseX - 50) + "px; top: " + (mouseY - 50) + "px; x-index: 100;";
this["img" + shrekId].ondragstart = function() { return false; };
document.body.appendChild(this["img" + shrekId]);
shrekId += 1
}
setInterval() takes a function as a parameter, this is done by passing the function name (without the brackets) like so:
myFunc()
{
console.log('hello');
return 1;
}
setInterval(myFunc, 100);
When you do include the brackets (like you did in your example), it will run the function, take the return of that function, and provide that to the setInterval instead.
For example:
myFunc()
{
console.log('hello');
return 1;
}
setInterval(myFunc(), 100);
turns into
setInterval(1, 100);
because myFunc() returns 1.
So you should be able to fix your code by removing the brackets from your interval:
interval = setInterval(draw(event), 100);
// to
interval = setInterval(draw, 100);
Which also means you have to remove the parameter from the function:
function draw(event) {
// to
function draw() {
The problem is with this line: interval = setInterval(draw(event), 100);
The first parameter of setInterval should be a function, but you're calling the function here and passing in the result, try the following instead:
interval = setInterval(() => { draw(event) }, 100);
Or if you aren't supporting ES6:
interval = setInterval(function() { draw(event) }, 100);
It doesn't look like you're using event inside of the draw function though, if that's the case you can just pass the draw function itself:
interval = setInterval(draw, 100);
You are passing the result of executing the function instead of the function itself. Since the result of the function is undefined, you are executing draw and then passing undefined to setInterval which doesn't do anything.
Instead of this:
setInterval(draw(), 100);
Your statement should be this:
setInterval(draw, 100);
without the parentheses at the end of the function name.
When you pass draw() that calls the function immediately and gets it's return value. When you pass draw that passes a reference to the function so setInterval can invoke it in future(which is what you expect).
Related
I'm using setInterval with jQuery to change the position of a background-image onLoad but I want to use it as a function so I can call clearInterval to stop it when an element is clicked and to call the function again when another element is clicked but panRight() isn't working on load.
function moveImage() {
var x = 0;
x-=1;
$('.bg-img').css('background-position-x', x + 'px');
}
function panRight(){
setInterval(moveImage(),25);
}
// moveImage onLoad
panRight();
$("#stop-animation").click(function(){
clearInterval(panRight);
});
$("#start-animation").click(function(){
panRight();
});
The following code works as intended onLoad and is what I'm trying to refactor as functions.
$(function(){
var x = 0;
setInterval(function(){
x-=1;
$('.bg-img').css('background-position', x + 'px 0');
}, 25);
})
You can do it like this:
function moveImage() {
var x = 0;
x-=1;
$('.bg-img').css('background-position-x', x + 'px');
}
var panInterval; //timer id
function panRight(){
panInterval = setInterval(moveImage,25);
}
// moveImage onLoad
panRight();
$("#stop-animation").click(function(){
clearInterval(panInterval);
});
$("#start-animation").click(function(){
panRight();
});
Here var panInterval is timer id which get returned whenever we call setInterval and which can be use to clear the interval
We have some problem with our image animation with speed control.
It make use of a timeout to change the image, but we want to change the timeout value with a slider, but for some sort of reason, it doesn't work. Can someone help us out ?
We have a Jfiddle here: http://jsfiddle.net/Kbroeren/fmd4xbew/
Thanks! Kevin
var jArray = ["http://www.parijsalacarte.nl/images/mickey-mouse.jpg", "http://www.startpagina.nl/athene/dochters/cliparts-disney/images/donad%20duck-106.jpg", "http://images2.proud2bme.nl/hsfile_203909.jpg"];
var image_count = 0;
function rollover(image_id, millisecs) {
var image = document.getElementById(image_id);
image.src = jArray[image_count];
image_count++;
if (image_count >= jArray.length) {
image_count = 0;
}
var timeout = setTimeout("rollover('" + image_id + "'," + millisecs + ");", millisecs);
}
rollover("img1", 200);
$(function () {
var value;
var $document = $(document),
$inputRange = $('input[type="range"]');
// Example functionality to demonstrate a value feedback
function valueOutput(element) {
var value = element.value,
output = element.parentNode.getElementsByTagName('output')[0];
output.innerHTML = value;
}
for (var i = $inputRange.length - 1; i >= 0; i--) {
valueOutput($inputRange[i]);
};
$document.on('change', 'input[type="range"]', function (e) {
valueOutput(e.target);
rollover("img1", 200);
});
// end
$inputRange.rangeslider({
polyfill: false
});
});
You keep creating more and more infinite function calls without stopping them.
After you call your function the first time, it keeps calling itself.
then you call it again with different interval (millisecs) and it will also start call itself....
You can try two different approach.
1.Use setInterval instead of setTimeout. Use clearInterval to clear the interval before setting it with a new value.
/// Call animation() every 200 ms
var timer = setInterval("Animation()",200);
function ChageSpeed(miliseces){
///Stop calling Animation()
clearInterval(timer);
/// Start calling Animation() every "miliseces" ms
timer = setInterval("Animation()",miliseces);
}
function Animation(){
/// Animation code goes here
}
2.Or, Instead, Set your interval as a global variable (not cool) and just change it value when the user want to change the animation speed.
var millisecs = 200;
function rollover(image_id) {
var image = document.getElementById(image_id);
image.src = jArray[image_count];
image_count++;
if (image_count >= jArray.length) {
image_count = 0;
}
var timeout = setTimeout("rollover('" + image_id + "'," + millisecs + ");", millisecs);
}
$document.on('change', 'input[type="range"]', function (e) {
valueOutput(e.target);
millisecs = YourNewValue;
});
function moveDoi(n) {
var delay = -1;
var left = document.getElementById("One");
var currentLeft = parseInt(getComputedStyle(left).left, 10);
setTimeout(move, delay);
function move(){
if (currentLeft <= n ) {
currentLeft+=3;
left.style.left = currentLeft + "px";
setTimeout(move, delay);
}
}
};
In this code I have n as a parameter of the function, that is used in the if conditional statement.
For this function i need to have one more parameter x that will change the "One" so i need to obtain something like this: document.getElementById(""+x+"") . However, this is not working?
How can I add one more parameter to the function that needs to be in quotes (" ") in function?
First, you need to pass x into the function. Then, you simply need to reference it when calling document.getElementById. There are is no need to append/prepend quotes, since x is already a string.
function moveDoi(n, x) {
var delay = -1;
var left = document.getElementById(x);
var currentLeft = parseInt(getComputedStyle(left).left, 10);
setTimeout(move, delay);
function move(){
if (currentLeft <= n ) {
currentLeft+=3;
left.style.left = currentLeft + "px";
setTimeout(move, delay);
}
}
};
I'm trying to gradually increase the elements of 2 id's in javascript using a Timeout. I can get one working but when trying to call another element into the same function it only does one iteration then crashes after the first recursive call.
I'm passing two id's for the elements. and I want the left element to gradually increase while the right element gradually increases in width.
Heres what ive got
function grow(elementL, elementR)
{
var htL = parseInt(document.getElementById(elementL).style.width,10);
var htR = parseInt(document.getElementById(elementR).style.width,10);
var movementL = htL + 5;
var movementR = htR - 5;
document.getElementById(elementL).style.width = movementL + 'px';
document.getElementById(elementR).style.width = movementR + 'px';
if (movementL > 1000) {
clearTimeout(loopTimer);
return false;
}
var loopTimer = setTimeout('grow(\''+elementL+','+elementR+'\')',50);
}
You could simplify this (removing the script-generation) by using setInterval -- this repeats the function call until you cancel it.
function grow(elementL, elementR)
{
var loopTimer = setInterval(function() {
if (!growStep(elementL, elementR)) {
clearInterval(loopTimer);
}
}, 50);
}
function growStep(elementL, elementR) {
var htL = parseInt(document.getElementById(elementL).style.width,10);
var htR = parseInt(document.getElementById(elementR).style.width,10);
var movementL = htL + 5;
var movementR = htR - 5;
document.getElementById(elementL).style.width = movementL + 'px';
document.getElementById(elementR).style.width = movementR + 'px';
if (movementL > 1000) {
return false;
}
return true;
}
(Fiddle)
Edit
Yeah, I guess the only problem with the OP code is that it passes a string to setTimeout, rather than the function itself:
var loopTimer = setTimeout(function() {
grow(elementL, elementR);
},50);
setTimeout('grow(\''+elementL+','+elementR+'\')',50)
would need to be
setTimeout('grow(\''+elementL+'\',\''+elementR+'\')',50)
// ^^ ^^
to work. But don't do that. Pass a function expression to setTimeout:
setTimeout(function() {
grow(elementL, elementR);
}, 50)
I have an animation script implemented with jQuery. The issue is that it does not complete the animation before returning to the parent function. To clarify: the js changes a background color, the js function calls the animate function, the animation function begins, before it finishes it has already returned to the parent and continues on with the next line of js.
function step5(){
/*code*/
currentNode.obj.style.backgroundColor="white";
movePacket(currentNode, objects[currentNode.switchName]);
objects[currentNode.switchName].obj.style.backgroundColor="#ADEBFF";
/*code*/
}
function movePacket(obj1, obj2){
var x = obj2.x - obj1.x;
var y = obj2.y - obj1.y;
$("#packet").animate({"left": "+="+x+"px", "top": "+="+y+"px"}, 3000);
}
I need for the code to wait for the animation to complete and then proceed. Any suggestions?
You should pass it in as a callback function to the animate method:
function step5() {
currentNode.obj.style.backgroundColor = "white";
movePacket(currentNode, objects[currentNode.switchName], function() {
objects[currentNode.switchName].obj.style.backgroundColor = "#ADEBFF";
});
}
function movePacket(obj1, obj2, callback) {
var x = obj2.x - obj1.x;
var y = obj2.y - obj1.y;
$("#packet").animate({
left: "+=" + x + "px",
top: "+=" + y + "px"
}, 3000, callback);
}