How to move the canvas backward in javascript? - javascript

I try to think how the box can move backward when it hit 1000px (canvas.width) ,but I don’t know how it solves after If condition, so there’s my script, anyone can help me ?
var canvas = document.querySelector("canvas");
var canvasCT = canvas.getContext("2d");
var x = 50;
function draw() {
canvas.width = canvas.width;
canvasCT.fillStyle = "blue";
canvasCT.fillRect(x, 50, 100, 100);
}
function run() {
draw();
x += 5 ;
if (x > 1000) {
......
}
}
setInterval(run, 10);

var canvas = document.querySelector("canvas");
var canvasCT = canvas.getContext("2d");
var x = 50;
var speed = 5;
function draw() {
canvas.width = canvas.width;
canvasCT.fillStyle = "blue";
canvasCT.fillRect(x, 50, 100, 100);
}
function run() {
draw();
x += speed;
if (x > 1000 || x < 0) {
speed = -speed;
}
}
setInterval(run, 10);
<canvas width=1000></canvas>

Related

Why does it take longer to draw various colors than one color, both one pixel at a time?

This was narrowed down from a much larger script, but you can see that drawing a gradient based on the x value takes much more time than just passing it value 255.
Why should this matter? In either case, they are both drawing one pixel at a time, and they are both doing the work to derive the value of x.
By the way, my goal is not to find a faster way of drawing gradients.
var canvas = document.getElementById('canvas')
canvas.width = 600
canvas.height = 600
var ctx = canvas.getContext('2d')
init();
function init()
{
requestAnimationFrame(draw)
}
function draw()
{
const t0 = performance.now();
for(x = 0; x < canvas.width; x++)
{
for(y = 0; y < canvas.height; y++)
{
setPixelWhiteColor(x,x,y)
//setPixelWhiteColor(255,x,y) // <- faster?
}
}
const t1 = performance.now();
document.getElementById("debug1").innerHTML = t1 - t0
requestAnimationFrame(draw)
}
function setPixelWhiteColor(w,x,y)
{
ctx.fillStyle = "rgb("+w+","+w+","+w+")";
ctx.fillRect( x, y, 1, 1 );
}
<canvas id="canvas"></canvas>
<div id="debug1"></div>
I had to work with raw image data using putImageData like Wiktor said:
var canvas = document.getElementById('canvas')
canvas.width = 600
canvas.height = 600
var ctx = canvas.getContext('2d')
var id = ctx.getImageData(0, 0, canvas.width, canvas.height);
var pixels = id.data;
init();
function init()
{
requestAnimationFrame(draw)
}
function draw()
{
const t0 = performance.now();
for(x = 0; x < canvas.width; x++)
{
for(y = 0; y < canvas.height; y++)
{
var w = x
if(w > 255){
w = 255
}
setPixelWhiteColor(w,x,y)
}
}
putImageData()
const t1 = performance.now();
document.getElementById("debug1").innerHTML = t1 - t0
requestAnimationFrame(draw)
}
function setPixelWhiteColor(w,x,y)
{
var r = w
var g = w
var b = w
var off = (y * id.width + x) * 4;
pixels[off] = r;
pixels[off + 1] = g;
pixels[off + 2] = b;
pixels[off + 3] = 255;
}
function putImageData(){
ctx.putImageData(id, 0, 0);
}
<html>
<body>
<canvas id="canvas"></canvas>
<div id="debug1"></div>
<div id="debug2"></div>
<script>
</script>
</body>
</html>

making a truck and buttons to increase speed, change direction using html/js via jQuery

this is the question for my assignment
You are required to create the same animation in Canvas. This can be any object: a truck, a car, a cycle an airplane, etc. Many example codes are provided in Blackboard for your help, and I have given you hints in the lecture as well.
The object should be at the left of the screen when you load the page.
There will be five buttons: start, stop, +, -, and change direction. You can show or hide whichever button you want. It is up to you.
The object should start moving when click on the start button.
The object should stop moving when you click on the stop button.
The object should change the direction when you click on “change direction” button.
When you click on the + button, the speed of the object should be increased and when you click on the - button, the speed should be decreased.
Below the buttons, there should be names of the students who did that question.
I've tried to solve it but it's seems not to work with me.
and this is the code for my page.
I want to make change direction button using html/js via jQuery please.
$(document).ready(function() {
var canvas = $("#myCanvas");
var ctx = canvas.get(0).getContext("2d");
var playAnimation = true;
var startButton = $("#startAnimation");
var stopButton = $("#stopAnimation");
var increaseButton = $("#increase");
var decreaseButton = $("#decrease")
var x = 0;
var b = 200;
var t = 200;
var w = 200;
var q = 255;
var cir = 240;
var cir2 = 90;
var ctx;
startButton.hide();
startButton.click(function() {
$(this).hide();
stopButton.show();
playAnimation = true;
animate();
});
stopButton.click(function() {
$(this).hide();
startButton.show();
playAnimation = false;
});
/*function increase() {
speed += 10;
};*/
increaseButton.click(function() {
var interval = 1000;
timer = function() {
interval--;
//do your thing here
interval = interval < 40 ? 40 : interval;
setTimeout(timer, interval);
};
timer();
});
/*stopButton.click.(function(){
if(mouseX >= 335 && mouseX <= 390 && mouseY >= 15 && mouseY <= 115){
x++;//Make faster
}
if(mouseX >= 335 && mouseX <= 390 && mouseY >= 295 && mouseY <= 395){
x--;//Make slower
if(speed < 0){
speed++;//Make faster, I said IT CAN'T GO TO 0 or less...
}
}
});*/
//var increase = x++;
//var decrease = x--;
function animate() {
x++;
b++;
t++;
w++;
q++;
cir++;
cir2++;
//y++; //update
//ctx.clearRect(0, 0, 800, 600); //clear
ctx.clearRect(0, 0, canvas.width(), canvas.height());
ctx.fillRect(x, 350, 190, 120);
ctx.fillRect(b, 410, 60, 60);
ctx.beginPath();
ctx.moveTo(t, 350);
ctx.lineTo(w, 400);
ctx.lineTo(q, 400);
ctx.closePath();
ctx.fillStyle = "#black";
ctx.fill();
//var c = document.getElementById("myCanvas");
//var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(cir, 490, 18, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
ctx.lineWidth = 4;
ctx.strokeStyle = '#black';
ctx.stroke();
ctx.beginPath();
ctx.arc(cir2, 490, 18, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
ctx.lineWidth = 4;
ctx.strokeStyle = '#black';
ctx.stroke();
//draw();
// removed for snippet: console.log(x);
if (playAnimation)
setTimeout(animate, 20);
//repeat
};
animate();
});
/* for snippet - a huge gap at the top makes it unviewable */
#myCanvas { margin-top: -340px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="myCanvas" width="800" height="600">
<!-- Insert fallback content here -->
</canvas>
<div>
<button id="startAnimation">Start</button>
<button id="stopAnimation">Stop</button>
<button id="increase"> Increase the speed</button>
<button id="decrease"> Decrease the speed</button>
</div>
It seems like you are calling animate() inside animate(), that is not a good idea.
Start and stop
I use this to run the function repeatedly
var speed = 10;
var animation = setInterval(function () {
animate();
}, speed);
Now, the animate() will run every speed ms, which in this case is 10ms. (Canvas will clear and update every 10ms)
To stop the animation, just stop the interval with clearInterval(animation), start again by assigning back it.
startButton.click(function () {
$(this).hide();
stopButton.show();
animation = setInterval(function () {
animate();
}, speed);
});
Change speed
increaseButton.click(function () {
changeSpeed(-10);
});
decreaseButton.click(function () {
changeSpeed(10);
});
function changeSpeed(changeValue) {
speed += changeValue;
clearInterval(animation)
animation = setInterval(function () {
animate();
}, speed);
}
Change direction
I have added in new variable named direction, which will let the animation move forward when it is in 1 and backward when -1.
I replace your code in animate()
x++;
b++;
t++;
w++;
q++;
cir++;
cir2++;
with:
x += direction;
b += direction;
t += direction;
w += direction;
q += direction;
cir += direction;
cir2 += direction;
and add button that allow it to change the value of direction
var changeDirection = $("#changeDirection");
changeDirection.click(function () {
direction *= -1;
})
All together:
$(document).ready(function () {
var canvas = $("#myCanvas");
var ctx = canvas.get(0).getContext("2d");
var playAnimation = true;
var startButton = $("#startAnimation");
var stopButton = $("#stopAnimation");
var increaseButton = $("#increase");
var decreaseButton = $("#decrease");
var changeDirection = $("#changeDirection");
var x = 0;
var b = 200;
var t = 200;
var w = 200;
var q = 255;
var cir = 240;
var cir2 = 90;
var ctx;
var direction = 1;
var speed = 10;
startButton.hide();
startButton.click(function () {
$(this).hide();
stopButton.show();
animation = setInterval(function () {
animate();
}, speed);
});
stopButton.click(function () {
$(this).hide();
startButton.show();
clearInterval(animation)
});
increaseButton.click(function () {
changeSpeed(-10);
});
decreaseButton.click(function () {
changeSpeed(10);
});
changeDirection.click(function () {
direction *= -1;
})
function changeSpeed(changeValue) {
speed += changeValue;
clearInterval(animation)
animation = setInterval(function () {
animate();
}, speed);
}
function animate() {
x += direction;
b += direction;
t += direction;
w += direction;
q += direction;
cir += direction;
cir2 += direction;
//update
ctx.clearRect(0, 0, canvas.width(), canvas.height());
ctx.fillRect(x, 350, 190, 120);
ctx.fillRect(b, 410, 60, 60);
ctx.beginPath();
ctx.moveTo(t, 350);
ctx.lineTo(w, 400);
ctx.lineTo(q, 400);
ctx.closePath();
ctx.fillStyle = "#black";
ctx.fill();
ctx.beginPath();
ctx.arc(cir, 490, 18, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
ctx.lineWidth = 4;
ctx.strokeStyle = '#black';
ctx.stroke();
ctx.beginPath();
ctx.arc(cir2, 490, 18, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
ctx.lineWidth = 4;
ctx.strokeStyle = '#black';
ctx.stroke();
};
var animation = setInterval(function () {
animate();
}, speed);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<canvas id="myCanvas" width="800" height="600">
<!-- Insert fallback content here -->
</canvas>
<div>
<button id="startAnimation">Start</button>
<button id="stopAnimation">Stop</button>
<button id="increase"> Increase the speed</button>
<button id="decrease"> Decrease the speed</button>
<button id="changeDirection"> Change direction</button>
</div>
</body>

How can I reverse the direction of this square after it reaches a certain value?

I'm trying to create an idle animation where the red rectangle moves back and forth slightly in a loop. For some reason once it reaches the specified threshhold instead of proceeding to move in the opposite direction, it just stops.
What did I do wrong?
<canvas id="myCanvas" width="1500" height="500" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
// Spaceship structure
var shipWidth = 250;
var shipHeight = 100;
// Canvas parameters
var cWidth = canvas.width;
var cHeight = canvas.height;
// Positioning variables
var centerWidthPosition = (cWidth / 2) - (shipWidth / 2);
var centerHeightPosition = (cHeight / 2) - (shipHeight / 2);
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
function drawShip(){
ctx.clearRect(0, 0, cWidth, cHeight);
ctx.fillStyle = "#FF0000";
ctx.fillRect(centerWidthPosition,centerHeightPosition,shipWidth,shipHeight);
centerWidthPosition--;
if (centerWidthPosition < 400){
++centerWidthPosition;
}
requestAnimationFrame(drawShip);
}
drawShip();
</script>
#TheAmberlamps explained why it's doing that. Here I offer you a solution to achieve what I believe you are trying to do.
Use a velocity variable that changes magnitude. X position always increases by velocity value. Velocity changes directions at screen edges.
// use a velocity variable
var xspeed = 1;
// always increase by velocity
centerWidthPosition += xspeed;
// screen edges are 0 and 400 in this example
if (centerWidthPosition > 400 || centerWidthPosition < 0){
xspeed *= -1; // change velocity direction
}
I added another condition in your if that causes the object to bounce back and forth. Remove the selection after || if you don't want it doing that.
Your function is caught in a loop; once centerWidthPosition reaches 399 your conditional makes it increment back up to 400, and then it decrements back to 399.
here is another one as a brain teaser - how would go by making this animation bounce in the loop - basically turn text into particles and then reverse back to text and reverse back to particles and back to text and so on and on and on infinitely:
var random = Math.random;
window.onresize = function () {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
window.onresize();
var ctx = canvas.getContext('2d');
ctx.font = 'bold 50px "somefont"';
ctx.textBaseline = 'center';
ctx.fillStyle = 'rgba(255,255,255,1)';
var _particles = [];
var particlesLength = 0;
var currentText = "SOMETEXT";
var createParticle = function createParticle(x, y) {_particles.push(new Particle(x, y));};
var checkAlpha = function checkAlpha(pixels, i) {return pixels[i * 4 + 3] > 0;};
var createParticles = function createParticles() {
var textSize = ctx.measureText(currentText);
ctx.fillText(currentText,Math.round((canvas.width / 2) - (textSize.width / 2)),Math.round(canvas.height / 2));
var imageData = ctx.getImageData(1, 1, canvas.width, canvas.height);
var pixels = imageData.data;
var dataLength = imageData.width * imageData.height;
for (var i = 0; i < dataLength; i++) {
var currentRow = Math.floor(i / imageData.width);
var currentColumn = i - Math.floor(i / imageData.height);
if (currentRow % 2 || currentColumn % 2) continue;
if (checkAlpha(pixels, i)) {
var cy = ~~(i / imageData.width);
var cx = ~~(i - (cy * imageData.width));
createParticle(cx, cy);
}}
particlesLength = _particles.length;
};
var Point = function Point(x, y) {
this.set(x, y);
};
Point.prototype = {
set: function (x, y) {
x = x || 0;
y = y || x || 0;
this._sX = x;
this._sY = y;
this.reset();
},
add: function (point) {
this.x += point.x;
this.y += point.y;
},
multiply: function (point) {
this.x *= point.x;
this.y *= point.y;
},
reset: function () {
this.x = this._sX;
this.y = this._sY;
return this;
},
};
var FRICT = new Point(0.98);//set to 0 if no flying needed
var Particle = function Particle(x, y) {
this.startPos = new Point(x, y);
this.v = new Point();
this.a = new Point();
this.reset();
};
Particle.prototype = {
reset: function () {
this.x = this.startPos.x;
this.y = this.startPos.y;
this.life = Math.round(random() * 300);
this.isActive = true;
this.v.reset();
this.a.reset();
},
tick: function () {
if (!this.isActive) return;
this.physics();
this.checkLife();
this.draw();
return this.isActive;
},
checkLife: function () {
this.life -= 1;
this.isActive = !(this.life < 1);
},
draw: function () {
ctx.fillRect(this.x, this.y, 1, 1);
},
physics: function () {
if (performance.now()<nextTime) return;
this.a.x = (random() - 0.5) * 0.8;
this.a.y = (random() - 0.5) * 0.8;
this.v.add(this.a);
this.v.multiply(FRICT);
this.x += this.v.x;
this.y += this.v.y;
this.x = Math.round(this.x * 10) / 10;
this.y = Math.round(this.y * 10) / 10;
}
};
var nextTime = performance.now()+3000;
createParticles();
function clearCanvas() {
ctx.fillStyle = 'rgba(0,0,0,1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
(function clearLoop() {
clearCanvas();
requestAnimationFrame(clearLoop);
})();
(function animLoop(time) {
ctx.fillStyle = 'rgba(255,255,255,1)';
var isAlive = true;
for (var i = 0; i < particlesLength; i++) {
if (_particles[i].tick()) isAlive = true;
}
requestAnimationFrame(animLoop);
})();
function resetParticles() {
for (var i = 0; i < particlesLength; i++) {
_particles[i].reset();
}}

Inquiry about Undefined array

As I have revised on the codes, I have found that the code that I wrote cannot function normally but the words shown are always “undefined”, but I have checked many times that the code seems perfect. Could you mind to have a look and check for me? That really confused me a lot...Thank you very much. I appreciate your help very much.
<!DOCTYPE html>
<html>
<head>
<style>
body{display:block;
margin:auto;
text-align:center;}
canvas{border:1px solid black;}
</style>
<script>
var canvas;
var ctx;
var timer;
var words=["canoe","buddha","elephant","dice"];//
var words=["canoe","buddha","elephant","dice"];
var answerIndex=-1;
var answer_x=-1;
var answer_y=-1;
var plate_x=-1;
var plate_y=-1;
var score=0;
function draw()
{ ctx.clearRect(0,0,canvas.width,canvas.height-10);
//canvas=document.getElementById("Canvas");
//ctx=canvas.getcontext("2d")
answer_x+=3;
answer_y+=3;
var answer=words[answerIndex];
ctx.font="20px Arial";
ctx.fillStyle="black";
ctx.fillText(answer,answer_x,answer_y);
var distance=answer_x-plate_x;
document.getElementById("plate_x").innerHTML=plate_x;
document.getElementById("word_x").innerHTML=answer_x;
document.getElementById("dist").innerHTML=distance;
if (answer_y>=plate_y)
{
clearInterval(timer);
if ((distance<50) && (distance>-50))
{
document.getElementById("message").innerHTML="Bravo!";
score++;
document.getElementById("score").innerHTML=score;
}
else
{
document.getElementById("message").innerHTML="Game over!";
}
}
}
function getRandomIndex()
{var random_number=Math.random*words.length;
var random_int=Math.floor(random_number);
return random_int;
}
function play()
{
canvas=document.getElementById("Canvas");
ctx=canvas.getContext("2d");
answerIndex = getRandomIndex();
var answer = words[answerIndex];
var imageFileName = answer + ".jpg";
document.getElementById("myPic").src = imageFileName;
answer_x=0;
answer_y=0;
ctx.clearRect(0,0,canvas.width,canvas.height);
plate_x=0;
plate_y=canvas.height-10;
ctx.fillStyle="blue";
ctx.fillRect(plate_x,plate_y,50,10);
clearInterval(timer);
timer=setInterval("draw()",100);
}
function moveleft()
{ ctx.clearRect(plate_x,plate_y,50,10);
if(plate_x>0)
{plate_x-=20;}
ctx.fillStyle="blue";
ctx.fillRect(plate_x,plate_y,50,10);
}
function moveright()
{ ctx.clearRect(plate_x,plate_y,50,10);
if(plate_x<(canvas.width-50))
{plate_x+=20;}
ctx.fillStyle="blue";
ctx.fillRect(plate_x,plate_y,50,10);
}
</script>
</head>
<body>
<h1>Catch the word!</h1>
<img id="myPic" alt="no pic" src="" width="200"/><br/>
<canvas id="Canvas" width="300" height="250"></canvas>
<br/><button onclick="play()">Play</button>
<button onclick="moveleft()">←</button>
<button onclick="moveright()">→</button>
<p id="message">Move to catch the word!</p>
<p id="score"></p>
<p>Plate X-coordinate:</p><p id="plate_x"></p>
<p>Word X-coordinate:</p><p id="word_x"></p>
<p>Distance:</p><p id="dist"></p>
</body>
</html>
In your getRandomIndex() function, you forgot the parenthesis after Math.random, which accesses random as a property rather than a method. So Math.random in your formula should be Math.random() instead.
Your current code doesn't work because your getRandomIndex() function returns NaN:
function getRandomIndex() {
var random_number = Math.random * words.length;
var random_int = Math.floor(random_number);
console.log(Math.random);
// ƒ random() { [native code] }
console.log(random_number);
// NaN
console.log(random_int);
// NaN
return random_int;
}
If you change your current code to use Math.random() instead, then your getRandomIndex() function will return the random integer value you are expecting:
function getRandomIndex() {
var random_number = Math.random() * words.length; // changed code
var random_int = Math.floor(random_number);
console.log(Math.random());
// 0.40108128192401526 (of course this value will change each time)
console.log(random_number);
// 3.613675793700807 (of course this value will change each time)
console.log(random_int);
// 3 (of course this value will change each time)
return random_int;
}
To follow on the comment from #David, in the future if you run into something like this you could always console.log() some of the values from the function that is not returning the expected output. This will help you run down your issue when there are no errors in the console.
Your variable ctx is undefined because you define ctx in the function play().
and at the beginning of your script you are declaring all your variables but you leave ctx and canvas empty
var canvas; //<------ You leave canvas empty
var ctx; //<------ You leave ctx empty
var timer;
var words = ["canoe", "buddha", "elephant", "dice"];
var words = ["canoe", "buddha", "elephant", "dice"];
var answerIndex = -1;
var answer_x = -1;
var answer_y = -1;
var plate_x = -1;
var plate_y = -1;
var score = 0;
At the play function you assign a value to it.
function play() {
canvas = document.getElementById("Canvas");
ctx = canvas.getContext("2d"); //<---- Here you add a value
answerIndex = getRandomIndex();
var answer = words[answerIndex];
var imageFileName = answer + ".jpg";
document.getElementById("myPic").src = imageFileName;
answer_x = 0;
answer_y = 0;
ctx.clearRect(0, 0, canvas.width, canvas.height);
plate_x = 0;
plate_y = canvas.height - 10;
ctx.fillStyle = "blue";
ctx.fillRect(plate_x, plate_y, 50, 10);
clearInterval(timer);
timer = setInterval("draw()", 100);
}
But that value will only be available within that function.
and all your other functions also use ctx!
In the folowing code block I clarified all the places where it went wrong and where it didn't go wrong.
var canvas;
var ctx; //<--- here you leave it empty
var timer;
var words = ["canoe", "buddha", "elephant", "dice"];
var words = ["canoe", "buddha", "elephant", "dice"];
var answerIndex = -1;
var answer_x = -1;
var answer_y = -1;
var plate_x = -1;
var plate_y = -1;
var score = 0;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height - 10); //<--- Here you are calling ctx but ctx is not defined!
//canvas=document.getElementById("Canvas");
//ctx=canvas.getcontext("2d") //Here you are randomly identifying ctx but you made a comment of it...
answer_x += 3;
answer_y += 3;
var answer = words[answerIndex];
ctx.font = "20px Arial"; //<--- Here you are calling ctx but ctx is not defined!
ctx.fillStyle = "black"; //<--- Here you are calling ctx but ctx is not defined!
ctx.fillText(answer, answer_x, answer_y); //<--- Here you are calling ctx but ctx is not defined!
var distance = answer_x - plate_x;
document.getElementById("plate_x").innerHTML = plate_x;
document.getElementById("word_x").innerHTML = answer_x;
document.getElementById("dist").innerHTML = distance;
if (answer_y >= plate_y) {
clearInterval(timer);
if ((distance < 50) && (distance > -50)) {
document.getElementById("message").innerHTML = "Bravo!";
score++;
document.getElementById("score").innerHTML = score;
} else {
document.getElementById("message").innerHTML = "Game over!";
}
}
}
function getRandomIndex() {
var random_number = Math.random * words.length;
var random_int = Math.floor(random_number);
return random_int;
}
function play() {
canvas = document.getElementById("Canvas");
ctx = canvas.getContext("2d"); // <--- here you correctly identified ctx
answerIndex = getRandomIndex();
var answer = words[answerIndex];
var imageFileName = answer + ".jpg";
document.getElementById("myPic").src = imageFileName;
answer_x = 0;
answer_y = 0;
ctx.clearRect(0, 0, canvas.width, canvas.height); //<---- So this can be executed and is NOT undefined
plate_x = 0;
plate_y = canvas.height - 10;
ctx.fillStyle = "blue"; //<---- So this can be executed and is NOT undefined
ctx.fillRect(plate_x, plate_y, 50, 10); //<---- So this can be executed and is NOT undefined
clearInterval(timer);
timer = setInterval("draw()", 100);
}
function moveleft() {
ctx.clearRect(plate_x, plate_y, 50, 10); //<--- Here you are calling ctx but ctx is not defined!
if (plate_x > 0) {
plate_x -= 20;
}
ctx.fillStyle = "blue"; //<--- Here you are calling ctx but ctx is not defined!
ctx.fillRect(plate_x, plate_y, 50, 10); //<--- Here you are calling ctx but ctx is not defined!
}
function moveright() {
ctx.clearRect(plate_x, plate_y, 50, 10); //<--- Here you are calling ctx but ctx is not defined!
if (plate_x < (canvas.width - 50)) {
plate_x += 20;
}
ctx.fillStyle = "blue"; //<--- Here you are calling ctx but ctx is not defined!
ctx.fillRect(plate_x, plate_y, 50, 10); //<--- Here you are calling ctx but ctx is not defined!
}
SO the solution will be to declare ctx and canvas at the beginning like this:
var canvas = document.getElementById("Canvas"); //<----- Like this
var ctx = canvas.getContext("2d"); //<------ Like this
var timer;
var words = ["canoe", "buddha", "elephant", "dice"];
var words = ["canoe", "buddha", "elephant", "dice"];
var answerIndex = -1;
var answer_x = -1;
var answer_y = -1;
var plate_x = -1;
var plate_y = -1;
var score = 0;
But in order for this to work you will need the remove the script from the head and place it all the way to the bottom of your body like this:
<html>
<head>
Remove your script from here
</head>
<body>
All the contents of your body
And place your script here
</body>
</html>
or declare ctx at the beginning of every function that needs it like this:
var canvas;
var ctx;
var timer;
var words = ["canoe", "buddha", "elephant", "dice"];
var words = ["canoe", "buddha", "elephant", "dice"];
var answerIndex = -1;
var answer_x = -1;
var answer_y = -1;
var plate_x = -1;
var plate_y = -1;
var score = 0;
function draw() {
canvas = document.getElementById("Canvas"); //<----- declare canvas here
ctx = canvas.getcontext("2d"); // <--- declare ctx here
ctx.clearRect(0, 0, canvas.width, canvas.height - 10);
answer_x += 3;
answer_y += 3;
var answer = words[answerIndex];
ctx.font = "20px Arial";
ctx.fillStyle = "black";
ctx.fillText(answer, answer_x, answer_y);
var distance = answer_x - plate_x;
document.getElementById("plate_x").innerHTML = plate_x;
document.getElementById("word_x").innerHTML = answer_x;
document.getElementById("dist").innerHTML = distance;
if (answer_y >= plate_y) {
clearInterval(timer);
if ((distance < 50) && (distance > -50)) {
document.getElementById("message").innerHTML = "Bravo!";
score++;
document.getElementById("score").innerHTML = score;
} else {
document.getElementById("message").innerHTML = "Game over!";
}
}
}
function getRandomIndex() {
var random_number = Math.random * words.length;
var random_int = Math.floor(random_number);
return random_int;
}
function play() {
canvas = document.getElementById("Canvas"); //<----- declare canvas here
ctx = canvas.getcontext("2d"); // <--- declare ctx here
answerIndex = getRandomIndex();
var answer = words[answerIndex];
var imageFileName = answer + ".jpg";
document.getElementById("myPic").src = imageFileName;
answer_x = 0;
answer_y = 0;
ctx.clearRect(0, 0, canvas.width, canvas.height);
plate_x = 0;
plate_y = canvas.height - 10;
ctx.fillStyle = "blue";
ctx.fillRect(plate_x, plate_y, 50, 10);
clearInterval(timer);
timer = setInterval("draw()", 100);
}
function moveleft() {
canvas = document.getElementById("Canvas"); //<----- declare canvas here
ctx = canvas.getcontext("2d"); // <--- declare ctx here
ctx.clearRect(plate_x, plate_y, 50, 10);
if (plate_x > 0) {
plate_x -= 20;
}
ctx.fillStyle = "blue";
ctx.fillRect(plate_x, plate_y, 50, 10);
}
function moveright() {
canvas = document.getElementById("Canvas"); //<----- declare canvas here
ctx = canvas.getcontext("2d"); // <--- declare ctx here
ctx.clearRect(plate_x, plate_y, 50, 10);
if (plate_x < (canvas.width - 50)) {
plate_x += 20;
}
ctx.fillStyle = "blue";
ctx.fillRect(plate_x, plate_y, 50, 10);
}
Also please read the comments of other people too because they might note other mistakes that I didn't see

Why is my line not drawing over time?

I am trying to have a line draw to the canvas over a certain amount of time(ten seconds to be exact). I'm able to see that the script is counting to a certain time and then stopping, but I'm not seeing the line being drawn. Can anyone show me what I'm doing wrong?
$(document).ready(function(){
canvas = document.getElementById("test");
ctx = canvas.getContext("2d");
var count = 0;
var start_x = 0;
var start_y = 100;
var end_x = 50;
var end_y = 100;
var counter = setInterval(countNumbers, 1000);
ctx.beginPath();
ctx.moveTo(start_x, start_y);
console.log("Start");
function countNumbers(){
count += 1;
ctx.lineTo((start_x + count), start_y);
console.log(count);
if((start_x == end_x) || (count == 10)){
clearInterval(counter);
console.log("End");
}
}
ctx.lineWidth = 5;
ctx.strokeStyle = "white";
ctx.stroke();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="test"></canvas>
Try to move stroke inside the Interval. Because in your case stroke are called immediately without lineTo data. And after that lineTo are called in interval function and cannot be rendered without stroke.
$(document).ready(function(){
canvas = document.getElementById("test");
ctx = canvas.getContext("2d");
var count = 0;
var start_x = 0;
var start_y = 100;
var end_x = 50;
var end_y = 100;
var counter = setInterval(countNumbers, 1000);
ctx.beginPath();
ctx.moveTo(start_x, start_y);
console.log("Start");
function countNumbers(){
count += 1;
ctx.lineTo((start_x + count), start_y);
console.log(count);
if((start_x == end_x) || (count == 10)){
clearInterval(counter);
console.log("End");
ctx.lineWidth = 5; // <----- move here
ctx.strokeStyle = "white";
ctx.stroke();
}
}
})
Also ensure that you are not drawing white lines on white background
$(document).ready(function(){
canvas = document.getElementById("test");
ctx = canvas.getContext("2d");
var count = 0;
var start_x = 0;
var start_y = 100;
var end_x = 50;
var end_y = 100;
var counter = setInterval(countNumbers, 1000);
ctx.beginPath();
ctx.moveTo(start_x, start_y);
console.log("Start");
ctx.lineWidth = 5;
ctx.strokeStyle = "black";
function countNumbers(){
count += 1;
ctx.lineTo((start_x + count), start_y);
ctx.stroke();
console.log(count);
if((start_x == end_x) || (count == 10)){
clearInterval(counter);
console.log("End");
ctx.strokeStyle = "white";
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="test"></canvas>
I would count down for the step. This will allow you to figure out the step.
I modified your code to allow you to pass parameters into the interval function to minimize global scope variables. Since I passed a reference of the interval into itself, you no longer need to have global variables.
I created two function, the first will create a path and then stroke it. The second one will stroke a sub-line after each tick of the interval. I added a simple check for even-odd to swap between colors.
$(document).ready(function() {
var canvas = $('canvas#test')[0];
var ctx = canvas.getContext('2d');
var count = 10;
var start_x = 50, start_y = 50;
var end_x = 250, end_y = 150;
var delta_x = end_x - start_x, delta_y = end_y - start_y;
var step_x = delta_x / count, step_y = delta_y / count;
canvas.width = 300;
canvas.height = 200;
// Fill canvas with solid black.
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'black';
ctx.fill();
// Kick off the line stroke timer. No more global variables!
var counter = setInterval(function(opts) {
// Pass a reference to the timer into the interval.
strokeLineTimerLive(counter, opts);
}, 500, {
ctx : ctx,
n : count,
x1 : start_x,
y1 : start_y,
x2 : end_x,
y2 : end_y,
dx : step_x,
dy : step_y,
});
// After the interval has ended, the path is finally stroked.
function strokeLineTimer(timer, opts) {
if (!opts.init) {
console.log("Start");
opts.ctx.beginPath();
opts.ctx.moveTo(opts.x1, opts.y1);
opts.ctx.lineWidth = 5;
opts.ctx.strokeStyle = 'white';
opts.init = true;
}
opts.n -= 1;
opts.ctx.lineTo((opts.x1 += opts.dx), (opts.y1 += opts.dy));
console.log(opts.n);
if ((opts.x1 == opts.x2) || (opts.n == 0)){
clearInterval(timer);
opts.ctx.stroke();
console.log("End");
}
}
// After each tick of the interval, a line is stroked.
function strokeLineTimerLive(timer, opts) {
if (!opts.init) {
console.log("Start");
opts.ctx.beginPath();
opts.ctx.moveTo(opts.x1, opts.y1);
opts.ctx.lineWidth = 5;
opts.init = true;
}
opts.n -= 1;
opts.ctx.strokeStyle = opts.n % 2 == 0 ? 'white' : 'red';
opts.ctx.lineTo((opts.x1 += opts.dx), (opts.y1 += opts.dy));
opts.ctx.stroke();
console.log(opts.n);
if ((opts.x1 == opts.x2) || (opts.n == 0)){
clearInterval(timer);
console.log("End");
} else {
opts.ctx.beginPath();
opts.ctx.moveTo(opts.x1, opts.y1);
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="test"></canvas>

Categories

Resources