Javascript: code with no animation with requestAnimationFrame? - javascript

I am learning Javacript and test the code from the book (below). It should animate an image but doesn't. I add print out using alert which shows that the function is executed only once. What goes wrong?
<!doctype html>
<html>
<head>
<title> My home page </title>
<script>
var cat = document.querySelector("img");
var angle = 0, lastTime = null;
var count = 0;
function animate(time) {
//alert(count);
//++count;
if (lastTime != null)
angle += (time - lastTime) * 0.001;
lastTime = time ;
cat.style.top = (Math.sin(angle) * 20) + "px";
cat.style.left = (Math.cos(angle) * 200) + "px";
requestAnimationFrame(animate);
}
</script>
</head>
<body>
<p style ="text-align: center">
<img src ="img/cat.jpg" style ="position: relative">
</p >
</body>
<script>requestAnimationFrame(animate);</script>
</html>
Thank you for the help.

If you look at the console, you will see that the cat is undefined.
This happens because var cat = document.querySelector("img"); is run in the head element and so the img does not exist yet.
If you move the code at the end of the body it will work.
Or you could run your code when the DOMContentLoaded event is fired.
<!doctype html>
<html>
<head>
<title> My home page </title>
</head>
<body>
<p style ="text-align: center">
<img src ="img/cat.jpg" style ="position: relative">
</p >
</body>
<script>
var cat = document.querySelector("img");
var angle = 0, lastTime = null;
var count = 0;
function animate(time) {
//alert(count);
//++count;
if (lastTime != null)
angle += (time - lastTime) * 0.001;
lastTime = time ;
cat.style.top = (Math.sin(angle) * 20) + "px";
cat.style.left = (Math.cos(angle) * 200) + "px";
requestAnimationFrame(animate);
}
</script>
<script>requestAnimationFrame(animate);</script>
</html>

When the browser see a <script> tag, he stop rendering the page, and run the code inside.
So, the problem in the code that the line var cat = document.querySelector("img"); happen before the img is append to the document, so you query get nothing.
the only change you need to do- is to move the var cat = document.querySelector("img"); to under the body, like so:
</body>
<script>
var cat = document.querySelector("img");
requestAnimationFrame(animate);
</script>
</html>

Related

How to replace a moving <img> with another one during movement using JavaScript?

I have a moving image that moves across the screen from left to right. I need to replace it in the middle of the screen with another image for 5 seconds and then replace it back again resume the movement. could anyone please help me with that ?
Here's the code I have so far. I'm new to this , any help would be very much appreciated ! Thanks in advance !
const catImg = document.querySelector('img');
let marginLeft = (catImg.style.left = 0);
let marginRight = catImg.style.right;
const body = document.querySelector('body');
body.style.position = 'relative';
function catWalk() {
let halfWidth = window.innerWidth / 2 - catImg.width / 2;
marginLeft = '0px';
if (
parseInt(window.getComputedStyle(catImg).left) <
Math.floor(window.innerWidth / 2 - catImg.width / 2)
) {
marginLeft = parseInt(window.getComputedStyle(catImg).left) + 10 + 'px';
catImg.style.left = marginLeft;
return;
} else if (parseInt(window.getComputedStyle(catImg).left) == Math.round(halfWidth / 10) * 10) {
catImg.src = 'https://tenor.com/StFI.gif';
function dancingCat(timePassed) {
let startTime, endTime;
function start() {
startTime = performance.now();
return startTime;
}
function end() {
endTime = performance.now();
timePassed = endTime - startTime;
console.log(timePassed);
return endTime;
}
if (timePassed == 5000) {
catImg.src = 'http://www.anniemation.com/clip_art/images/cat-walk.gif';
}
}
} else if (
parseFloat(window.getComputedStyle(catImg).left) >
window.innerWidth - catImg.width / 2
) {
console.log('stop here');
catImg.style.left = '0px';
return;
}
return;
}
setInterval(catWalk, 50);
catWalk();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Cat Walk</title>
</head>
<body>
<img style="position: absolute;" src="http://www.anniemation.com/clip_art/images/cat-walk.gif" />
<script src="ex5-catWalk.js"></script>
</body>
</html>
Based on your code I made a refactor separating each sentence between functions. BTW, try to avoid declare functions within functions. I'm giving you just an example of how can you make it. I'm sure it could be better turning each function as pure, but it works fine.
Edition
Adding some lines to start function you can achieve a loop cycle when the cat overflows the right side window.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Cat Walk</title>
</head>
<body>
<img width="200" src="http://www.anniemation.com/clip_art/images/cat-walk.gif" />
<script type="text/javascript">
let interval, leftPos = 0, stopped = 0;
const img = document.querySelector('img');
const windowHalf = window.innerWidth / 2;
const middlePos = windowHalf - img.width / 2;
function step(img, size) {
leftPos += size;
return img.style.marginLeft = leftPos + 'px';
}
function start() {
interval = setInterval(() => {
if (leftPos < window.innerWidth) {
if (leftPos < middlePos || stopped) {
return step(img, 5);
} else {
clearInterval(interval);
return stop();
}
} else {
// restart variables when cat overflows window area
leftPos = 0;
stopped = 0;
}
}, 50)
}
function stop() {
img.src = 'https://tenor.com/StFI.gif';
stopped++
setTimeout(() => {
img.src = 'http://www.anniemation.com/clip_art/images/cat-walk.gif';
start()
}, 5000)
}
start();
</script>
</body>
</html>

drawing more on the canvas without having to create more script tags

I've been attempting to create a ecology simulation and so far its been going good. The code below does work I'm just wondering if theres an easier way to draw more items on the canvas with code instead of manually doing it. The way I'm doing it makes me consider the lag because I will be adding a lot to the code (e.g. move, detected, reproduce, chase, run, etc). Thank you for seeing this
//This tag will regulate the spawning of new sheep/wolves
var totalWolves = 0;
var totalSheep = 0;
var canavs = document.getElementById("canvas");
var body = document.getElementById("body");
//styler
body.style.overflow = "hidden";
body.style.margin = "0px";
canvas.style.backgroundColor = "black";
function spawnWolves(){
totalWolves++;
var name = "wolf" + totalWolves;
var scrpt = document.createElement("SCRIPT");
document.body.appendChild(scrpt);
scrpt.setAttribute("id", name);
var script = document.getElementById(name);
script.innerHTML = "var rand3 = Math.floor(Math.random() * 100) + 1; var rand4 = Math.floor(Math.random() * 100) + 1; var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); context.fillStyle = 'red'; context.fillRect(rand3, rand4, 10, 10); context.fill();";
}
spawnWolves();
spawnWolves();
spawnWolves();
<!DOCTYPE html>
<html>
<head>
<title>AI spawn test</title>
</head>
<body id="body">
<canvas id="canvas" width="1366px" height="768px"/>
<script>
</script>
</body>
</html>
Your solution seems very complicated ...
Please, take a look at the following code.
<!DOCTYPE html>
<html>
<title>AI spawn test</title>
<canvas id="canvas" width="110" height="110"></canvas>
<script>
var ctx = canvas.getContext("2d");
var drawRect=function(rects){
for (var i=1; i<=rects; i++){
var rand3=Math.floor(Math.random() * 100) + 1;
var rand4=Math.floor(Math.random() * 100) + 1;
ctx.fillStyle='red';
ctx.fillRect(rand3, rand4, 10, 10)
}
}
drawRect(20);
</script>
This type of 'replication' is done by using loop. There are several loop types, but their explanation is too broad. You can browse the net.
I gave you 2 examples below - with for loop and with while loop.
//This tag will regulate the spawning of new sheep/wolves
var totalWolves = 0;
var totalSheep = 0;
var canavs = document.getElementById("canvas");
var body = document.getElementById("body");
//styler
body.style.overflow = "hidden";
body.style.margin = "0px";
canvas.style.backgroundColor = "black";
function spawnWolves(){
totalWolves++;
var name = "wolf" + totalWolves;
var scrpt = document.createElement("SCRIPT");
document.body.appendChild(scrpt);
scrpt.setAttribute("id", name);
var script = document.getElementById(name);
script.innerHTML = "var rand3 = Math.floor(Math.random() * 100) + 1; var rand4 = Math.floor(Math.random() * 100) + 1; var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); context.fillStyle = 'red'; context.fillRect(rand3, rand4, 10, 10); context.fill();";
}
for(var i=0; i<12; i++)
{
spawnWolves();
}
var maxWolves=9;
while(totalWolves < maxWolves)
{
spawnWolves();
}
<!DOCTYPE html>
<html>
<head>
<title>AI spawn test</title>
</head>
<body id="body">
<canvas id="canvas" width="1366px" height="768px"/>
<script>
</script>
</body>
</html>
The first loop will run until its internal counter i goes from 0 to 12 and will call the function exactly 12 times.
The second loop will run as long as the condition totalWolves < maxWolves is true. totalWolves is your counter you increase in your function and maxWolves is the limit when you want the loop to stop.
Because these 2 examples are added here one after another the second wont work. After the first one executes you will already have 12 wolves and the second loop will not enter because 12 < 9 is false.

Button not calling function correctly

I am trying to call a function on a button click, but for some reason the button will not call the function. Dreamweaver does not show any syntax errors. Can anyone tell me why the button is not working?
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
</head>
<head>
<title></title>
<script type="text/javascript">
var imgObj = 0;
var imgObj1 = 0;
var animate;
var animate1;
function init(){
imgObj = document.getElementById('red');
imgObj.style.position= 'relative';
imgObj.style.left = '0px';
imgObj1 = document.getElementById('blue');
imgObj1.style.position = 'relative';
imgObj1.style.left = '0px';
}
function moveRight(){
imgObj.style.left = parseInt(imgObj.style.left = 0) + Math.floor((Math.random() * 100) + 1) + 'px';
animate = setTimeout(moveRight(), 1000);
imgObj1.style.left = parseInt(imgObj1.style.left = 0) + Math.floor((Math.random() * 100) + 1) + 'px';
animate1 = setTimeout(moveRight(), 1000);
if (imgObj.style.left >= 1000px || imgObj1.style.left >= 1000px)
{
break;
else if
{
imgObj.style.left>= 1000
MessageBox.show("The Red Car has won the Race!");
}
else
{
MessageBox.show("The Blue Car has won the Race!");
}
}
}
</script>
</head>
<body onload = "init()">
<form>
<input type="button" value="Start" onclick="moveRight()" />
<br/><br/><br/><br><br/><br/><br/>
<img id="red" src="redcar.png" alt="Car 1"/>
<br/><br/><br/><br>
<img id="blue" src="bluecar.png" alt ="Car 2" />
</form>
</body>
</html>
Unfortunately there are so many errors that it's difficult to know where to start. The first answer to your question is that the button did nothing because your code doesn't compile. I don't know why Dreamweaver didn't report an error. Chrome's developer tools was more than happy to do so.
Here's a "working" version:
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript">
var imgObj = 0;
var imgObj1 = 0;
var animate1;
function init(){
imgObj = document.getElementById('red');
imgObj.style.position= 'relative';
imgObj.style.left = '0px';
imgObj1 = document.getElementById('blue');
imgObj1.style.position = 'relative';
imgObj1.style.left = '0px';
}
function moveRight(){
var redPosition = parseInt(imgObj.style.left);
imgObj.style.left = redPosition + Math.floor((Math.random() * 20) + 1) + 'px';
var bluePosition = parseInt(imgObj.style.left);
imgObj1.style.left = bluePosition + Math.floor((Math.random() * 20) + 1) + 'px';
if (redPosition >= 1000 || bluePosition >= 1000)
{
if (redPosition >= 1000) {
alert("The Red Car has won the Race!");
}
else
{
alert("The Blue Car has won the Race!");
}
return;
}
animate1 = setTimeout(moveRight, 50);
}
</script>
</head>
<body onload = "init()">
<form>
<input type="button" value="Start" onclick="moveRight()" />
<br/><br/><br/><br><br/><br/><br/>
<img id="red" src="redcar.png" alt="Car 1"/>
<br/><br/><br/><br>
<img id="blue" src="bluecar.png" alt ="Car 2" />
</form>
</body>
</html>

Moving Pictures Bugs - JavaScript

After abt 2hrs or so, I managed to get the images moving, but i met with some issues:
1) Images move beyond the "bound" - image overlap is ok, but beyond the side of the browser
2) Moving the scroll bar to the right (0 -> 20) makes the image move closer - OK
but moving the scroll bar to the left (20 -> 0) does not return the images back to where they were
I seek you guys assistance to help debug and clean the code.
Thank You in advance :) and apologies for my weak sense of coding >.<
Images Used:
lion tail
lion head
Below is the "Draft" HTML Code:
<!DOCTYPE html>
<html>
<head>
<title>Moving Image</title>
<script src="./movingPicture.js" type="text/javascript"></script>
</head>
<body>
<form>
<img id="IMG_LEFT" src="./lion tail.gif" />
<img id="IMG_RIGHT" src="./lion head.gif" />
<p>Move the Bar to Move the Images Closer</p>
<input type="range" min="0" max="100" value="0" steps="2" oninput="moveRight(value);"/>
</form>
</body>
</html>
Below is the Javascript Code:
var imgObjLeft = null;
var imgObjRight = null;
function init()
{
imgObjLeft = document.getElementById('IMG_LEFT');
imgObjLeft.style.position= 'relative';
imgObjLeft.style.left = '0px';
imgObjRight = document.getElementById('IMG_RIGHT');
imgObjRight.style.position= 'relative';
imgObjRight.style.left = '100px';
}
function moveRight(value)
{
valueH = value/2;
imgObjLeft.style.left = parseInt(imgObjLeft.style.left) + valueH + 'px';
imgObjRight.style.left = parseInt(imgObjRight.style.left) - valueH + 'px';
}
window.onload =init;
Try the following JS. You dont seem to give a range for the movement of these images. I have added a limit which is the max value of your range control. you can increase the value by increasing the max value of your slider
var imgObjLeft = null;
var imgObjRight = null;
function init() {
imgObjLeft = document.getElementById('IMG_LEFT');
imgObjLeft.style.position = 'relative';
imgObjLeft.style.left = '0px';
imgObjRight = document.getElementById('IMG_RIGHT');
imgObjRight.style.position = 'relative';
imgObjRight.style.left = '100px';
}
function moveRight(value) {
valueH = value;
imgObjLeft.style.left = valueH + 'px';
imgObjRight.style.left = (100 - valueH) + 'px';
}
window.onload = init;

Change div width every 1 second by 5px

I tried to change div width every 1 second by 5px using JavaScript. How can I make this work?
Here's my code:
<html>
<head>
<title>JS Functions</title>
</head>
<body>
<div style="width:100px; height:100px; background:gray" id="box" onclick="bigger()"></div>
<script>
function bigger()
{
var w = 100
var h = 100
while(w < 1000, h < 1000)
{
w = w+5;
h = h+5;
document.getElementById('box').style.width = w
document.getElementById('box').style.height = h
setInterval();
}
}
</script>
</body>
</html>
No while loop needed. You can just use setInterval:
var w = 100;
var h = 100;
var foo = setInterval(function () {
if(w>1000) cancelInterval(foo)
w = w + 5;
h = h + 5;
document.getElementById('box').style.width = w + 'px';
document.getElementById('box').style.height = h + 'px';
}, 1000);
<div style="width:100px; height:100px; background:gray" id="box" onclick="bigger()"></div>
You need to use setInterval to call your code every second, so move it outside of the bigger() function. Also you need the full value for style, including the unit you're using.
try this
<html>
<head>
<title>JS Functions</title>
</head>
<body>
<div style="width:100px; height:100px; background:gray" id="box"></div>
<script>
var w = 100;
var h = 100;
function bigger()
{
if (w < 1000 && h < 1000)
{
w = w+5;
h = h+5;
document.getElementById('box').style.width = w + 'px';
document.getElementById('box').style.height = h + 'px';
} else {
clearInterval(int);
}
}
var int = setInterval(bigger, 1000);
</script>
</body>
</html>
Let's say you have a div wth id='boxToEnlarge'
The JSFiddle: http://jsfiddle.net/7qtb1u8e/1/
And this is the actual code:
function enlargeBox(){
//get current size
var currentWidth = document.getElementById('boxToEnlarge').offsetWidth;
var currentHeight = document.getElementById('boxToEnlarge').offsetHeight;
//add 5 more pixels to current size
document.getElementById('boxToEnlarge').style.width = currentWidth + 5 +'px';
document.getElementById('boxToEnlarge').style.height = currentHeight + 5 +'px';
}
//call the enlargeBox func every 1 sec (1000 milliseconds)
setInterval(function(){enlargeBox()},1000);
We are reading the current size of the div we want to enlarge then we add 5px to that amount and apply it on it's width/height CSS properties.
We wrap the above in a function and using setInterval, we call that function once every n milliseconds, in this case 1000ms which equals 1 second

Categories