moveBall function not working when adding input parameters - javascript

I'm trying to create a moveBall function were you put the ID of the ball created in HTML, and it moves from left to right.
This is what I've done first, and it works:
var ball = document.getElementById("ball");
var velocityX = 100;
var positionX = 0;
var reverseX = false;
//write a function that can change the position of the html element "ball"
function moveBall() {
// two fixed x-axis coordinates (you will use these variable in step 3)
var Xmin = 0;
var Xmax = 500;
//reverse condition
if (!reverseX){
positionX = positionX + velocityX;
} else positionX = positionX - velocityX;
ball.style.left = positionX + 'px';
if (positionX === Xmax){
reverseX = true;
} else if (positionX === Xmin){
reverseX = false;
}
}
// This call the moveBall function every 100ms
setInterval(moveBall, 100);
However, when I try to make a function moveBall(ballId) so I can re use it with other balls, it doesn't work. This is my code:
var ballId;
var velocityX = 100;
var positionX = 0;
var reverseX = false;
//write a function that can change the position of the html element "ball"
function moveBall(ballId) {
ball = document.getElementById(ballId)
// two fixed x-axis coordinates (you will use these variable in step 3)
var Xmin = 0;
var Xmax = 500;
//reverse condition
if (!reverseX){
positionX = positionX + velocityX;
} else positionX = positionX - velocityX;
ball.style.left = positionX + 'px';
if (positionX === Xmax){
reverseX = true;
} else if (positionX === Xmin){
reverseX = false;
}
}
// This call the moveBall function every 100ms
setInterval(moveBall("ball"), 100);
Please I would be thrilled to know if you have any clue. The ball doesn't move with the second code, it just remains static in the html file.

Your problem is in the line which says setInterval(moveBall("ball"), 100);
setInterval expects a function as first argument, however, here provided is a function call instead. I'm a bit rusty on theory here, but basically this will execute function call first, which will return undefined and then your line looks same as if you have written setInterval(undefined, 100);, so every 100ms you do nothing...
What you wanna do instead is write function handler to pass into setInterval instead of function call.
You can do either arrow function setInterval(() => moveBall("ball"), 100);
or if you can't use arrow functions you could do setInterval(function () {moveBall("ball")}, 100);
This in other words says execute (nameless) function every 100ms, this nameless function will execute call of your moveBall function with desired paramater.
Your original code without param works since if you look closely, you are passing directly function there, without call.

Thanks to Miroslav Saracevic for the incredibly quick answer,
// This call the moveBall function every 100ms
setInterval(() => moveBall("ball"), 100)
This solved the problem.

Related

Make the following JavaScript modifications using clearInterval() and setInterval() where appropriate:

Make the following JavaScript modifications using clearInterval() and setInterval() where appropriate:
In startAnimation(), add an if statement that stops the timer with the ID timerId if timerId is not null.
After the if statement in startAnimation() that stops the timer, start a timer that calls moveImage(clickX, clickY) every 10 milliseconds. Save the timer ID in the timerId variable.
Add an if statement in moveImage() that stops the timer with the ID timerId if (imgX, imgY) is equal to (centerX, centerY). Also set timerId to null.
After the modifications are complete, the user should be able to click anywhere in the browser, and the heart will slowly move to the clicked location. If the user clicks on a new location before the heart arrives at the last location, the heart will adjust course and move to the new location.
Here is my code.
I keep get these errors in the photo even though I followed the instrutions
let timerId = null;
window.addEventListener("DOMContentLoaded", function() {
document.addEventListener("click", startAnimation);
});
function startAnimation(e) {
// Get mouse coordinates
let clickX = e.clientX;
let clickY = e.clientY;
// TODO: Modify the code below
if (timerId != null) {
clearInterval(timerId);
}
moveImage(clickX, clickY);
timerId = setInterval(moveImage, 10);
};
function moveImage(x, y) {
const img = document.querySelector("img");
// Determine location of image
let imgX = parseInt(img.style.left);
let imgY = parseInt(img.style.top);
// Determine (x,y) coordinates that center the image
// around the clicked (x, y) coords
const centerX = Math.round(x - (img.width / 2));
const centerY = Math.round(y - (img.height / 2));
// TODO: Add code here
if ((imgX, imgX == centerX) && (imgY == centerY)) {
clearInterval(timerId);
timerId = null;
}
// Move 1 pixel in both directions toward the click
if (imgX < centerX) {
imgX++;
}
else if (imgX > centerX) {
imgX--;
}
if (imgY < centerY) {
imgY++;
}
else if (imgY > centerY) {
imgY--;
}
img.style.left = imgX + "px";
img.style.top = imgY + "px";
};
I keep get these errors in the photo even though I followed the instructions
errors
The errors you're getting are basically saying that the code isn't working, which, if you run the code, you can see.
One handy way to see what's going on with your code is to use console.log and debugger
Note the difference between these two calls:
moveImage(clickX, clickY);
and
timerId = setInterval(moveImage, 10);
In each, you're making the call to moveImage, but in only one of them are you providing arguments for x and y.
We can remedy this by using a higher order function:
let timerId = null;
window.addEventListener("DOMContentLoaded", function() {
document.addEventListener("click", startAnimation);
});
function startAnimation(e) {
// Get mouse coordinates
let clickX = e.clientX;
let clickY = e.clientY;
// TODO: Modify the code below
if (timerId != null) {
clearInterval(timerId);
}
timerId = setInterval(moveImage(clickX, clickY), 10);
};
function moveImage(targetX, targetY) {
const img = document.querySelector("img");
return () => {
// Determine location of image
let imgX = parseInt(img.getBoundingClientRect().x);
let imgY = parseInt(img.getBoundingClientRect().y);
// Determine (x,y) coordinates that center the image
// around the clicked (x, y) coords
const centerX = Math.round(targetX - (img.width / 2));
const centerY = Math.round(targetY - (img.height / 2));
// TODO: Add code here
if ((imgX, imgX == centerX) && (imgY == centerY)) {
clearInterval(timerId);
timerId = null;
}
// Move 1 pixel in both directions toward the click
if (imgX < centerX) {
imgX++;
} else if (imgX > centerX) {
imgX--;
}
if (imgY < centerY) {
imgY++;
} else if (imgY > centerY) {
imgY--;
}
img.style.left = imgX + "px";
img.style.top = imgY + "px";
};
};
img {
position: fixed;
}
<img src="https://i.kym-cdn.com/photos/images/facebook/001/136/185/604.jpg" height="20" weidth="20" />
You can use getBoundingClientRect to find the position of the image, and once its position is set to fixed, changing the left and top properties will cause it to move.

paper.js animate point on graph

I'm trying to build an animated graph with paper.js that can react to different input. So I want to smoothly animate one point vertically to a different point.
I've looked at different examples and the closest ones to mine is this one:
paper.tool.onMouseDown = function(event) {
x = event.event.offsetX;
y = event.event.offsetY;
paper.view.attach('frame', moveSeg);
}
var x;
var y;
function moveSeg(event) {
event.count = 1;
if(event.count <= 100) {
myPath.firstSegment.point._x += (x / 100);
myPath.firstSegment.point._y += (y / 100);
for (var i = 0; i < points - 1; i++) {
var segment = myPath.segments[i];
var nextSegment = segment.next;
var vector = new paper.Point(segment.point.x - nextSegment.point.x,segment.point.y - nextSegment.point.y);
vector.length = length;
nextSegment.point = new paper.Point(segment.point.x - vector.x,segment.point.y - vector.y);
}
myPath.smooth();
}
}
This Code animates one Point to the click position, but I couldn't change it to my needs.
What I need is:
var aim = [120, 100];
var target = aim;
// how many frames does it take to reach a target
var steps = 200;
// Segment I want to move
myPath.segments[3].point.x
And then I dont know how to write the loop that will produce a smooth animation.
example of the graph:
I worked out the answer. The following steps in paperscript:
Generate Path
Set aim for the point
OnFrame Event that does the moving (eased)
for further animations just change the currentAim variable.
var myPath = new Path({
segments: [[0,100],[50,100],[100,100]]});
// styling
myPath.strokeColor = '#c4c4c4'; // red
myPath.strokeWidth = 8;
myPath.strokeJoin = 'round';
myPath.smooth();
// where the middle dot should go
var currentAim = [100,100];
// Speed
var steps = 10;
//Animation
function onFrame(event) {
dX1 = (currentAim[0] - myPath.segments[1].point.x )/steps;
dY1 = (currentAim[1] - myPath.segments[1].point.y )/steps;
myPath.segments[1].point.x += dX1;
myPath.segments[1].point.y += dY1;
}

Is DOM manipulation code queued or run synchronously? [duplicate]

I don't understand why the infinite loop does not work but uncommenting the function call works.
<body>
<canvas id="myCanvas"style="border:2px solid black;" width="1600" height="900">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
var c = document.getElementById ("myCanvas").getContext ("2d");
var boxSize = 25;
var numBoxes = 1;
var x = 1000;
var dx = 1;
var y = 100;
var dy = 1;
var a = 0.01;
var da = 0.1;
var size = 20;
var w = c.canvas.width;
var h = c.canvas.height;
//function testing () {
while (true) {
c.clearRect (0, 0, w, h);
x = x + 1;
y = y + 1;
a = a + 0.1;
x = x + dx;
y = y + dy;
if (x < size / 2 || x + (size / 2) > w) {
dx = -dx;
da = -da;
}
if (y < size / 2 || y + (size / 2) > h) {
dy = -dy;
da = -da;
}
c.save ();
c.translate (x, y);
c.rotate (a);
c.strokeRect (-size / 2, -size / 2, size, size);
c.restore ();
}
// testing ();
// setInterval (testing, 10);
</script>
</body>
When you use setInterval you keep adding the function you are calling to the queue of things for the browser to do. Repaint events are also added to this queue.
When you use an infinite loop, the browser never gets to the end of the function, so it never gets around to running a repaint and the image in the document never updates.
JavaScript-in-a-browser is a part of a larger construction. You need to align to the rules of this construction and don't hurt it. One of the rule is that your JavaScript must run quick and exit then. Exit means that control gets back to the framework, which does all the job, repaint the screen etc.
Try to hide and show something many times:
for (n = 0; n < 200; n++) {
$("#test").hide();
$("#test").show();
}
When this code runs, you won't see any flickering, you will see that the last command will have effect.
Have to say, it's not easy to organize code that way, if you want to make a cycle which paints nice anims on a canvas, you have to do it without while.

get global var of mousemove and update onFrame event in paper.js

I am new to Paper.js therefore might this a basic question but I am trying to the the following:
var xpos;
var ypos;
function onMouseMove(event) {
xpos = event.point.x;
ypos = event.point.y;
}
get the current mouseposition and save it as the variables xpos and ypos
function onFrame(event) {
path.segments[1].point.x = path.segments[1].point.x+xpos/10;
path.segments[1].point.y = path.segments[1].point.y+ypos/10;
}
and then use them to update the onFrame animation. But it does not work, how can I update the animation with the new values?
Thanks in advance.
It looks like your code is increasing the position of path.segments[1] every frame. I believe what you want is to subtract a portion of the difference between the segment and mouse positions per frame.
Try this:
var path = new Path.Line((0,0), view.center);
path.strokeColor = "black";
var pos = new Point(0, 0);
function onMouseMove(event) {
pos = event.point;
}
function onFrame(event) {
path.segments[1].point += (pos - path.segments[1].point) / 10;
}

Raphael transform object diagonally and infinite setIntervals

I'm working on a small animation where the user drags a circle and the circle returns back to the starting point. I figured out a way to have the circle return to the starting point. The only problem is that it will hit one of the sides of the frame before returning. Is it possible for it to go straight back (follow the path of a line drawn between the shape and starting point).
The other problem is that my setInterval doesn't want to stop. If you try pulling it a second time it would pull it back before you release your mouse. It also seems to speed up after every time. I have tried using a while loop with a timer but the results weren't as good. Is this fixable?
var paper = Raphael(0, 0, 320, 200);
//var path = paper.path("M10 10L40 40").attr({stoke:'#000000'});
//var pathArray = path.attr("path");
var circle = paper.circle(50, 50, 20);
var newX;
var newY;
circle.attr("fill", "#f00");
circle.attr("stroke", "#fff");
var start = function () {
this.attr({cx: 50, cy: 50});
this.cx = this.attr("cx"),
this.cy = this.attr("cy");
},
move = function (dx, dy) {
var X = this.cx + dx,
Y = this.cy + dy;
this.attr({cx: X, cy: Y});
},
up = function () {
setInterval(function () {
if(circle.attr('cx') > 50){
circle.attr({cx : (circle.attr('cx') - 1)});
} else if (circle.attr('cx') < 50){
circle.attr({cx : (circle.attr('cx') + 1)});
}
if(circle.attr('cy') > 50){
circle.attr({cy : (circle.attr('cy') - 1)});
} else if (circle.attr('cy') < 50){
circle.attr({cy : (circle.attr('cy') + 1)});
}
path.attr({path: pathArray});
},2);
};
circle.drag(move, start, up);
Here's the Jfiddle: http://jsfiddle.net/Uznp2/
Thanks alot :D
I modified the "up" function to the one below
up = function () {
//starting x, y of circle to go back to
var interval = 1000;
var startingPointX = 50;
var startingPointY = 50;
var centerX = this.getBBox().x + (this.attr("r")/2);
var centerY = this.getBBox().y + (this.attr("r")/2);
var transX = (centerX - startingPointX) * -1;
var transY = (centerY - startingPointY) * -1;
this.animate({transform: "...T"+transX+", "+transY}, interval);
};
and the "start" function as follows:
var start = function () {
this.cx = this.attr("cx"),
this.cy = this.attr("cy");
}
Is this the behavior you are looking for? Sorry if I misunderstood the question.
If the circle need to get back to its initial position post drag, we can achieve that via simple animation using transform attribute.
// Assuming that (50,50) is the location the circle prior to drag-move (as seen in the code provided)
// The animation is set to execute in 1000 milliseconds, using the easing function of 'easeIn'.
up = function () {
circle.animate({transform: 'T50,50'}, 1000, 'easeIn');
};
Hope this helps.

Categories

Resources