HTML5 canvas requestAnimationFrame() is not working - javascript

I am trying to do a simple animation using window.requestAnimationFrame().Somehow,The function is not getting called recursively and not giving the correct code.The javascript code of my file is:
function OilPainting(){
this.initialize=function(){
var x=100;
var canvas=document.getElementById("canvas");
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;
var context=canvas.getContext('2d');
animate(canvas,context);
}
}
var x=100;
var animate=function(canvas,context){
window.requestAnimationFrame(animate);
console.log("a");
//console.log("a");
/*for(var i=0;i<1;i++){
var x=Math.random()*window.innerWidth;
var y=Math.random()*window.innerHeight;
context.beginPath();
context.arc(x,y,30,0,2*Math.PI);
context.stroke();
//console.log("here");
x+=1;*/
context.beginPath();
context.arc(x,100,30,0,2*Math.PI);
context.clearRect(0,0,innerWidth,innerHeight);
//console.log(x);
context.stroke();
x+=100;
// console.log(x);
}
var app=new OilPainting();
app.initialize();
Here, although the console a is getting printed recursively but the circles are not getting formed.The link to my Codepen is Here.How exactly is requestAnimationFrame() is used?

You have too many issues with your code ...
Here's how it should be done
var x = 100;
function OilPainting() {
this.initialize = function() {
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var context = canvas.getContext('2d');
animate(canvas, context);
}
}
var animate = function(canvas, context) {
//console.log("a");
context.clearRect(0, 0, innerWidth, innerHeight);
context.beginPath();
context.arc(x, 100, 30, 0, 2 * Math.PI);
context.stroke();
x += 1;
requestAnimationFrame(function() {
animate(canvas, context);
});
}
var app = new OilPainting();
app.initialize();
body{margin:0;overflow:hidden}canvas{border:1px solid #d3d3d3}
<canvas id="canvas"></canvas>
apology for not giving any explanation

you didn't pass canvas and context to animate function when calling requestAnimationFrame
var animate=function(canvas,context){
window.requestAnimationFrame(function() {
animate(canvas, context)
});
console.log("a");
context.beginPath();
context.arc(x,100,30,0,2*Math.PI);
//console.log(x);
context.stroke();
x+=100;
}

Related

Why doesn't my code loop the animation correctly with Javascript and HTML5 canvas?

I'm super new to coding and I've been trying to figure out animations with Javascript and HTML5. I have this "loading bar" like animation where a rectangle expands until it fills up the canvas. The idea is that once the canvas is covered the box clears and starts over. Instead, the rectangle fills the canvas and just starts flickering. Any ideas?
window.onload = function() {
var wipeWidth = 0
var canvas = document.getElementById('canvas');
var context = canvas.getContext("2d");
console.log(context);
function drawRect() {
context.clearRect(0,0,300,150)
context.fillStyle = "#305ef2";
context.rect(0, 0, wipeWidth, 150);
context.fill()
wipeWidth += 10
if(wipeWidth > 300) {
wipeWidth = 0;
}
}
setInterval(drawRect,50)
}
You forgot to clear the path (beginPath). You can use fillRect instead to avoid this.
window.onload = function() {
var wipeWidth = 0
var canvas = document.getElementById('canvas');
var context = canvas.getContext("2d");
console.log(context);
function drawRect() {
context.clearRect(0, 0, 300, 150)
context.fillStyle = "#305ef2";
// this
context.beginPath()
context.rect(0, 0, wipeWidth, 150);
context.fill()
// or just this
// context.fillRect(0, 0, wipeWidth, 150);
wipeWidth += 10
if (wipeWidth > 300) {
wipeWidth = 0;
}
}
setInterval(drawRect, 50)
}
<canvas id="canvas"></canvas>
fillRect, requestAnimationFrame
var wipeWidth = 0
var canvas = document.getElementById('canvas');
var context = canvas.getContext("2d");
var direction = +10;
function drawRect() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "#305ef2";
context.fillRect(0, 0, wipeWidth, 150);
wipeWidth += direction
if (wipeWidth > canvas.width || wipeWidth < 0) {
direction *= -1;
}
requestAnimationFrame(drawRect)
}
drawRect()
canvas {
background: gray;
}
<canvas id="canvas" width="600" height="50"></canvas>

Make a draw apps with JS?

I want to make a draw app in JS. So I've started to create a canvas in HTML and also write some codeIN JS. However, when I run my script, I can only draw some point and what I would like is to draw lines manually with the mouse.
Could you help me, please ?
window.addEventListener("load", function(){
var clear = document.getElementById("clear");
var paint = false;
can = document.querySelector("canvas");
context = can.getContext("2d");
can.addEventListener("mouseup", finish);
can.addEventListener("mousemove", draw);
clear.addEventListener("click", clearContent);
can.addEventListener("mousedown", painting);
function clearContent(){
context.clearRect(0, 0, can.width, can.height);
}
function painting(){
paint = true;
}
function finish(){
paint = false;
}
function draw(e){
if (!paint) return 0;
context.strokeStyle="black";
context.lineWidth = 5;
context.lineCap = "round";
context.beginPath();
context.moveTo(e.clientX, e.clientY);
context.lineTo(e.clientX, e.clientY);
context.stroke();
}
});
canvas { border: 1px solid }
<canvas></canvas>
<br>
<button id="clear">Clear</button>
You need to draw the line from the previous point, not the current point. It is quite straightforward to do that, because the canvas context remembers the previous point. Also, don't call beginPath as this would interrupt the sequence of points to connect.
You could also use a better way to pinpoint the exact coordinates.
See this variant of your code:
window.addEventListener("load", function(){
var clear = document.getElementById("clear");
var paint = false;
can = document.querySelector("canvas");
context = can.getContext("2d");
can.addEventListener("mouseup", finish);
can.addEventListener("mousemove", draw);
clear.addEventListener("click", clearContent);
can.addEventListener("mousedown", painting);
function clearContent(){
context.clearRect(0, 0, can.width, can.height);
}
function painting(){
paint = true;
context.beginPath(); /// <--- move this here
}
function finish(){
paint = false;
}
function draw(e){
if (!paint) return 0;
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
context.strokeStyle="black";
context.lineWidth = 5;
context.lineCap = "round";
// Don't do any of these here:
// context.beginPath();
// context.moveTo(x, y);
// ... only draw line from previous point:
context.lineTo(x, y);
context.stroke();
}
});
canvas { border: 1px solid }
<canvas></canvas>
<br>
<button id="clear">Clear</button>

"var canvas = document.getElementById("canvas")" can't be a global variable?

I made the following script. When I push the button, the word "blood" moves, and push the button and it stops.
This script worked in Chrome but when I move the following scripts to the TOP line. (between var flag; and window.setInterval), an error happens saying
uncaught typeerror cannot call method 'getcontext' of null"
would you explain why it happens please?
var canvas = document.getElementById("canvas"), ctx = canvas.getContext("2d");
var y = 100;
var flag = false;
window.onload = setInterval(function(){
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "red";
ctx.font = "50px Helvetica";
ctx.fillText("blood", 200, y);
if(flag){
y++;
}
}, 30);
function start(){
flag = true;
}
function stop(){
flag = false;
}
If you run your code in a script element at the end of the html body, you can ensure that it doesn't try to get the canvas context before the DOM is ready. Also, I made an optimization to your code to cache the DOM lookup:
<html>
<head>
<title>Canvas Scrolling Text</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript">
var y = 100;
var flag = false;
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
setInterval(function() {
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "red";
ctx.font = "50px Helvetica";
ctx.fillText("blood", 100, y);
if(flag)
y++;
}, 30);
function start()
{
flag = true;
}
function stop()
{
flag = false;
}
start();
</script>
</body>
Here's a working jsFiddle.
If you move it out of the onload function, then the DOM elements (specifically your canvas) don't exist yet. See https://stackoverflow.com/a/15564394/1370556 for more information on DOM content loaded events.

'loading circle' through Canvas

Alright guys, I'm sure this has been asked before, but I couldn't find anything that directly related to what I was doing. So I have these 4 self drawing circles (or gauges.) Each one has it's own value, and I've been looking through just nit picking through codes and books to build this. My question I need to figure out is how I would go about putting in a count up? Basically I want a counter to go from 1 - x (x being the degree of the circle it's in). I've included my js and HTML 5 for you guys to look at.
HTML
<canvas id="a" width="300" height="300"></canvas>
<script>
var canvas = document.getElementById('a');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 1.5 * Math.PI;
var endAngle = 3.2 * Math.PI;
var counterClockwise = false;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.lineWidth = 15;
// line color
context.strokeStyle = 'black';
context.stroke();
</script>
Canvas.JS
$(document).ready(function(){
function animate(elementId, endPercent) {
var canvas = document.getElementById(elementId);
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var curPerc = 0;
var counterClockwise = false;
var circ = Math.PI * 2;
var quart = Math.PI / 2;
context.lineWidth = 15;
context.strokeStyle = '#85c3b8';
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 10;
function render(current) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.arc(x, y, radius, -(quart), ((circ) * current) - quart, false);
context.stroke();
curPerc++;
if (curPerc < endPercent) {
requestAnimationFrame(function () {
render(curPerc / 100);
});
}
}
render();
}
$(window).scroll(function(){
if($(this).scrollTop()<1600){
animate('a', 85);
animate('b', 95);
animate('c', 80);
animate('d', 75);
}
});
});
Keep in mind that I am very new to canvas, I appreciate all the help guys!
Demo: http://jsfiddle.net/m1erickson/mYKp5/
You can save your gauges as objects in an array:
var guages=[];
guages.push({ x:50, y:100, radius:40, start:0, end:70, color:"blue" });
guages.push({ x:200, y:100, radius:40, start:0, end:90, color:"green" });
guages.push({ x:50, y:225, radius:40, start:0, end:35, color:"gold" });
guages.push({ x:200, y:225, radius:40, start:0, end:55, color:"purple" });
The render function takes a guage object draws its progress
function render(guage,percent) {
var pct=percent/100;
var extent=parseInt((guage.end-guage.start)*pct);
var current=(guage.end-guage.start)/100*PI2*pct-quart;
ctx.beginPath();
ctx.arc(guage.x,guage.y,guage.radius,-quart,current);
ctx.strokeStyle=guage.color;
ctx.stroke();
ctx.fillStyle=guage.color;
ctx.fillText(extent,guage.x-15,guage.y+5);
}
And the animation loop asks render to draw all gauges from 0-100 percent of their full values
function animate() {
// if the animation is not 100% then request another frame
if(percent<100){
requestAnimationFrame(animate);
}
// redraw all guages with the current percent
drawAll(percent);
// increase percent for the next frame
percent+=1;
}
function drawAll(percent){
// clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// draw all the guages
for(var i=0;i<guages.length;i++){
render(guages[i],percent);
}
}

Html5 Canvas rotate single element

I know that there are many similiar questions already asked on stackoverflow, but still, I can not figure out how to do it. I want to rotate only ball texture. draw is called with timer:
var canvas;
var ctx;
var width;
var height;
var ready;
var textures;
var loadIndex;
var loadCount;
var keyCodes;
var mouseLoc;
var playerX;
var playerY;
var playerVelocity;
function init() {
canvas = document.getElementById('game');
ctx = canvas.getContext("2d");
width = canvas.width;
height = canvas.height;
textures = [];
loadingCount = 0;
keyCodes = [];
mouseLoc = {};
playerX = 0;
playerY = 0;
playerVelocity = 6;
textures['Background'] = loadTexture('./textures/Background.png');
textures['Ball'] = loadTexture('./textures/Ball.png');
setInterval(function(){
if(loadingCount == 0) {
update();
draw();
}
}, 50);
}
function update(){
if(keyCodes[37])
playerX -= playerVelocity;
if(keyCodes[38])
playerY -= playerVelocity;
if(keyCodes[39])
playerX += playerVelocity;
if(keyCodes[40])
playerY += playerVelocity;
}
function draw() {
//ctx.clearRect(0, 0, width, height);
//ctx.beginPath();
drawBackground();
drawPlayer();
//ctx.closePath();
//ctx.fill();
}
function drawBackground(){
ctx.drawImage(textures['Background'], 0, 0, width, height);
}
function drawPlayer(){
ctx.save();
ctx.rotate(0.17);
ctx.drawImage(textures['Ball'], playerX, playerY, 100, 100);
ctx.restore();
}
function loadTexture(src){
var image = new Image();
image.src = src;
loadingCount++;
image.onload = function(){
loadingCount--;
};
return image;
}
document.onkeydown = function(evt){
keyCodes[evt.keyCode] = true;
evt.returnValue = false;
}
document.onkeyup = function(evt){
keyCodes[evt.keyCode] = false;
}
document.onmousemove = function(evt){
mouseLoc.x = evt.layerX;
mouseLoc.y = evt.layerY;
}
document.onmousedown = function(evt){
mouseLoc.down = true;
}
document.onmouseup = function(evt){
mouseLoc.down = false;
}
init();
Assuming that you want to give the illusion of the ball continuing to rotate, you should increase the rotation angle for each frame drawn.
As written, your code will give the ball a fixed rotation of 0.17 radians on each frame.
var frame = 0;
function drawPlayer() {
ctx.save();
ctx.rotate(0.17 * frame);
...
ctx.restore();
}
function draw() {
++frame;
drawPlayer();
...
}
You just need to save and restore the state of the canvas('s state-machine)
function drawPlayer(){
ctx.save();
ctx.rotate(0.17);
ctx.drawImage(textures['Ball'], playerX, playerY, 100, 100);
ctx.restore();
}
You want to use delta time for calculating the distance of your rotation. That is, the time that has passed since the last frame. That will make your rotation smoother should your browser hiccup and lose a frame here or there.
So store the time of each frame so you can make the comparison between frames and set your rotation speed as radians per second.

Categories

Resources