I want to implement a ripple effect in JavaScript for that I am using a canvas element of HTML 5.
I have created 4 circles in order to implement ripple effect I am thinking of showing only one circle at a time here is my code
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var i = window.innerWidth/4;
var canvas = document.getElementById("myCanvas");
canvas.width = window.innerWidth/2;
canvas.height = window.innerWidth/2;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(i, i, i-i/1.5, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(i, i, i-i/2.5, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(i, i, i-i/5, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(i, i, i, 0, 2 * Math.PI);
ctx.stroke();
output
how can I remove a specific circle here
there is a function ctx.clearRect(x, y, width, height); but it works only on rectangle.
also, let me know whether it's a good approach to create a ripple effect in canvas
If you are looking for something like this, you can do it simply by resetting the canvas after some time.
Also you can trigger the elements to be created at a certain time to make that effect of showing them one by one.
Here is a sample
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var i = window.innerWidth/4;
var canvas = document.getElementById("myCanvas");
canvas.width = window.innerWidth/2;
canvas.height = window.innerWidth/2;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(i, i, i-i/1.5, 0, 2 * Math.PI);
ctx.stroke();
window.setTimeout(() => {
ctx.beginPath();
ctx.arc(i, i, i-i/2.5, 0, 2 * Math.PI);
ctx.stroke();
}, 200*1)
window.setTimeout(() => {
ctx.beginPath();
ctx.arc(i, i, i-i/5, 0, 2 * Math.PI);
ctx.stroke();
}, 200*2)
window.setTimeout(() => {
ctx.beginPath();
ctx.arc(i, i, i, 0, 2 * Math.PI);
ctx.stroke();
}, 200*3)
window.setTimeout(() => {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var i = window.innerWidth/4;
var canvas = document.getElementById("myCanvas");
canvas.width = window.innerWidth/2;
canvas.height = window.innerWidth/2;
}, 200*6)
<canvas id="myCanvas"></canvas>
Here's a much much better and smoother ripple effect than the one you seek:
NOTE: run it on CodePen because for some reason it's not fully functional on stack overflow, but works fine in an HTML document or on CodePen
CodePen: https://codepen.io/Undefined_Variable/pen/dqZpzE
Code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>canvas</title>
</head>
<body>
<canvas id="myCanvas"></canvas>
<script>
var canvas = document.body.querySelector("#myCanvas");
var ctx = canvas.getContext("2d");
canvas.width = window.innerWidth * 0.98;
canvas.height = window.innerHeight * 0.97;
var shapeArr = [];
window.addEventListener('resize', function () {
canvas.width = window.innerWidth * 0.98;
canvas.height = window.innerHeight * 0.98;
CW = canvas.width;
CH = canvas.height;
})
var CW = canvas.width;
var CH = canvas.height;
class circle {
constructor(centerX, centerY, radius) {
this.centerX = centerX;
this.centerY = centerY;
this.radius = radius;
this.opacity = 1;
this.strokeStyle = "rgba(0, 0, 0, " + this.opacity + ")";
}
expandCircle() {
this.radius += 3;
this.opacity -= 0.015;
this.strokeStyle = "rgba(0, 0, 0, " + this.opacity + ")";
if (this.radius > window.innerWidth/4) {
this.radius = 0;
this.opacity = 1;
}
}
}
function createCircle(centerX, centerY, radius) {
shapeArr.push(new circle(centerX, centerY, radius));
}
function drawCircle(centerX, centerY, radius, strokeClr) {
ctx.strokeStyle = strokeClr;
ctx.save();
ctx.translate(centerX, centerY);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2);
ctx.closePath();
ctx.stroke();
ctx.restore()
}
createCircle(CW / 2, CH / 2, 0);
createCircle(CW / 2, CH / 2, 0);
createCircle(CW / 2, CH / 2, 0);
function firstWave() {
ctx.clearRect(0, 0, CW, CH);
drawCircle(shapeArr[0].centerX, shapeArr[0].centerY, shapeArr[0].radius, shapeArr[0].strokeStyle);
shapeArr[0].expandCircle();
requestAnimationFrame(firstWave);
};
firstWave();
setTimeout(function secondWave() {
drawCircle(shapeArr[1].centerX, shapeArr[1].centerY, shapeArr[1].radius, shapeArr[1].strokeStyle);
shapeArr[1].expandCircle();
requestAnimationFrame(secondWave);
}, 250);
setTimeout(function thirdWave() {
drawCircle(shapeArr[2].centerX, shapeArr[2].centerY, shapeArr[2].radius, shapeArr[2].strokeStyle);
shapeArr[2].expandCircle();
requestAnimationFrame(thirdWave);
}, 500)
</script>
</body>
</html>
Related
I've got this piece of code that draws a ball and i want to continuously pass in different cooridinates in order to make it move around but when the refresh rate gets way too high, canvas stops updating. How do i force canvas to update and redraw everything with the arguments passed in?
var c = document.getElementById("circle");
var ctx = c.getContext("2d");
var x = Math.floor(Math.random() * 50);
var y = Math.floor(Math.random() * 50);
function determinePosition(x, y) {
var trueX = x + 120;
var trueY = y + 80;
ctx.beginPath();
ctx.arc(trueX, trueY, 10, 0, 2 * Math.PI);
ctx.fillStyle = "black";
ctx.fill();
ctx.strokeStyle = "black";
ctx.stroke();
}
while(true){
determinePosition(x, y);
}
<div class="gcircle">
<canvas id="circle" width="240px" height="160"></canvas>
</div>
var c = document.getElementById("circle");
var ctx = c.getContext("2d");
function determinePosition(x, y) {
//clear the canvas
ctx.clearRect(0, 0, c.width, c.height);
var trueX = x + 120;
var trueY = y + 80;
ctx.beginPath();
ctx.arc(trueX, trueY, 10, 0, 2 * Math.PI);
ctx.fillStyle = "black";
ctx.fill();
ctx.strokeStyle = "black";
ctx.stroke();
}
//set random location for each 0.5 sec
setInterval(function() {
var x = Math.floor(Math.random() * 50);
var y = Math.floor(Math.random() * 50);
determinePosition(x, y);
}, 500)
<div class="gcircle">
<canvas id="circle" width="240px" height="160"></canvas>
</div>
`
Drawing should always happen in a requestAnimationFrame loop. requestAnimationFrame runs at your monitor's refresh rate, so it's the fastest any animation can run. You can set it up like this:
var c = document.getElementById("circle");
var ctx = c.getContext("2d");
var x = Math.floor(Math.random() * 50);
var y = Math.floor(Math.random() * 50);
var trueX = 0;
var trueY = 0;
function determinePosition(x, y) {
trueX = x + 120;
trueY = y + 80;
}
requestAnimationFrame(function draw() {
ctx.clearRect(0, 0, c.width, c.height);
ctx.beginPath();
ctx.arc(trueX, trueY, 10, 0, 2 * Math.PI);
ctx.fillStyle = "black";
ctx.fill();
ctx.strokeStyle = "black";
ctx.stroke();
requestAnimationFrame(draw);
})
determinePosition(x, y);
I want to display a windmill on js canvas. For now, I display a green line on a cube. I have a problem with rotating the line around it's middle point. Also, I don't want my cube to move. Save() doesn't seem to work? I don't know what I'm doing wrong. I tried looking the answer online but they don't seem to work or I don't understand them. Elements in my canvas somehow disappear.
var x = 600;
function init()
{
window.requestAnimationFrame(draw);
}
function draw()
{
var ctx = document.getElementById('canvas').getContext('2d');
ctx.clearRect(0, 0, 600, 600);
// sciana przednia
ctx.lineWidth = 1;
ctx.strokeStyle = "#000000";
ctx.strokeRect(x/2,x/2,x/4,x/4);
//sciana gorna
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = "#000000";
ctx.moveTo(x/2,x/2);
ctx.lineTo(x-x/3,x/4+x/6);
ctx.lineTo(x-x/8,x/4+x/6);
ctx.lineTo(x/2+x/4,x/2);
ctx.closePath();
ctx.stroke();
//sciana prawa
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = "#000000";
ctx.moveTo(x/2+x/4,x/2+x/4);
ctx.lineTo(x-x/8,x/2+x/7);
ctx.lineTo(x-x/8,x/4+x/6);
ctx.stroke();
ctx.closePath();
//raczka
ctx.beginPath();
ctx.lineWidth = 5;
ctx.strokeStyle = "#808080";
ctx.moveTo(x/2+x/5,x/2-x/5);
ctx.lineTo(x/2+x/5,x/2-x/8+50);
ctx.stroke();
ctx.closePath();
ctx.save();
//smiglo
ctx.beginPath();
ctx.translate(x/2, x/2);
ctx.rotate( (Math.PI / 180) * 25);
ctx.translate(-x/2, -x/2);
ctx.fillStyle = "#00cc00";
ctx.fillRect(x/2+x/5-100,x/2-x/5,200,10);
ctx.closePath();
ctx.restore();
window.requestAnimationFrame(draw);
}
init();
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d');
var x = 600;
function init() {
window.requestAnimationFrame(draw);
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// sciana przednia
ctx.lineWidth = 1;
ctx.strokeStyle = "#000000";
ctx.strokeRect(x / 2, x / 2, x / 4, x / 4);
//sciana gorna
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = "#000000";
ctx.moveTo(x / 2, x / 2);
ctx.lineTo(x - x / 3, x / 4 + x / 6);
ctx.lineTo(x - x / 8, x / 4 + x / 6);
ctx.lineTo(x / 2 + x / 4, x / 2);
ctx.closePath();
ctx.stroke();
//sciana prawa
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = "#000000";
ctx.moveTo(x / 2 + x / 4, x / 2 + x / 4);
ctx.lineTo(x - x / 8, x / 2 + x / 7);
ctx.lineTo(x - x / 8, x / 4 + x / 6);
ctx.stroke();
ctx.closePath();
//raczka
ctx.beginPath();
ctx.lineWidth = 5;
ctx.strokeStyle = "#808080";
ctx.moveTo(x / 2 + x / 5, x / 2 - x / 5);
ctx.lineTo(x / 2 + x / 5, x / 2 - x / 8 + 50);
ctx.stroke();
ctx.closePath();
ctx.save();
//smiglo
ctx.beginPath();
ctx.translate(x / 2, x / 2);
ctx.rotate((Math.PI / 180) * 25);
ctx.translate(-x / 2, -x / 2);
ctx.fillStyle = "#00cc00";
ctx.fillRect(x / 2 + x / 5 - 100, x / 2 - x / 5, 200, 10);
ctx.closePath();
ctx.restore();
window.requestAnimationFrame(draw);
}
init();
<canvas id="canvas" width=600 height=600></canvas>
Edit: I understand now how to rotate around a certain point. I still don't know how to rotate only the line not the whole thing.
Talking about the rotation, I think that you did well: the green line is rotated by 25 degrees in your example. You just need to rotate its middle point.
But to do so, I think it's better if you make other changes in your code: the part that draws the cube is difficult to handle, whenever you want to edit your code, this part will cause issues. I suggest to isolate it in a drawCube() function and to use proper (x,y) coordinates.
According to me, it should look like this:
function draw() {
angle += 5;
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate(Math.PI / 180 * angle);
ctx.translate(-canvas.width / 2, -canvas.height / 2);
// It rotates
drawLine();
ctx.restore();
// It doesn't rotate
drawCube();
}
Then, your code will work. All you will have to do is to make the line rotate around its middle point, but you said that you know how to do it.
Good luck!
EDIT: I added a snippet with an working example, and with a cube like yours as well, may help.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var btnExample = document.getElementById('btnExample');
var btnCube = document.getElementById('btnCube');
var angle = 0;
var fps = 1000 / 60;
var propellerWidth = 100;
var propellerHeight = 10;
var towerWidth = 2;
var towerHeight = 100;
var mode = {
CUBE: 'CUBE',
EXAMPLE: 'EXAMPLE'
}
var currentMode = mode.EXAMPLE;
btnExample.onclick = function() {
currentMode = mode.EXAMPLE;
}
btnCube.onclick = function() {
currentMode = mode.CUBE;
}
setInterval(function() {
angle += 3;
draw(canvas, ctx, (canvas.width - propellerWidth) / 2, (canvas.height - propellerWidth) / 2, angle);
}, fps);
function draw(canvas, ctx, cx, cy, angle) {
var towerX = cx + propellerWidth / 2 - towerWidth / 2;
var towerY = cy + propellerWidth / 2;
var propellerX = (canvas.width - propellerWidth) / 2;
var propellerY = (canvas.height - propellerHeight) / 2;
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw other things that don't rotate
if (currentMode === mode.EXAMPLE) {
drawHelp(canvas, ctx);
}
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate(Math.PI / 180 * angle);
ctx.translate(-canvas.width / 2, -canvas.height / 2);
// Draw things that rotate
drawPropeller(ctx, propellerX, propellerY, propellerWidth, propellerHeight);
ctx.restore();
// Draw other things that don't rotate
if (currentMode === mode.EXAMPLE) {
drawTower(ctx, towerX, towerY, towerWidth, towerHeight);
} else if (currentMode === mode.CUBE) {
drawCube(ctx, towerX, towerY, 30);
}
}
function drawPropeller(ctx, propellerX, propellerY, propellerWidth, propellerHeight) {
ctx.fillStyle = 'black';
ctx.fillRect(propellerX, propellerY, propellerWidth, propellerHeight);
}
function drawTower(ctx, towerX, towerY, towerWidth, towerHeight) {
ctx.fillStyle = 'red';
ctx.fillRect(towerX, towerY, towerWidth, towerHeight);
}
function drawCube(ctx, x, y, size) {
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, y + size);
ctx.closePath();
ctx.stroke();
var x1 = x - size + (size / 4) + (size / 16);
var y1 = y + (size * 1.25);
var x2 = x1 + (size / 3);
var y2 = y1 - (size * 2 / 3);
var x3 = x2 + size;
var y3 = y2;
var x4 = x3 - (size / 3);
var y4 = y1;
var x5 = x4;
var y5 = y4 + size;
var x6 = x3;
var y6 = y3 + size;
ctx.strokeRect(x1, y1, size, size);
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x2, y2);
ctx.lineTo(x3, y3);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x3, y3);
ctx.lineTo(x4, y4);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x3, y3);
ctx.lineTo(x6, y6);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x5, y5);
ctx.lineTo(x6, y6);
ctx.closePath();
ctx.stroke();
}
function drawHelp(canvas, ctx) {
ctx.globalAlpha = 0.2;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(canvas.width, canvas.height);
ctx.moveTo(canvas.width, 0);
ctx.lineTo(0, canvas.height);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.arc(canvas.width / 2, canvas.height / 2, propellerWidth / 2, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.arc(canvas.width / 2, canvas.height / 2, propellerWidth / 2, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
ctx.globalAlpha = 1;
}
canvas {
border: 1px solid black;
}
<canvas id="canvas" width=200 height=200></canvas>
<br>
<button id="btnExample">Example</button>
<button id="btnCube">Cube</button>
I have a html5 canvas that I'm drawing circles with. These circles need images in the center of them, but also need to update. With the help of this SO question
I have come up with this code to draw everything:
var Circle1 = new Circle((c.width / 8) + (c.width / 2), 200, eighthWidth / 2.5, Color1, "1");
var Circle2 = new Circle(c.width - eighthWidth, 200, eighthWidth / 2.5, Color2, "2");
function Circle(x, y, radius, color, name) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.name = name;
this.draw = function () {
var MiddleImage = new Image();
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
ctx.drawImage(MiddleImage, this.x - MiddleImage.width / 2, this.y - MiddleImage.height / 2);
MiddleImage.src = "/Images/" + this.name + ".png";
}
this.update = function () {
this.x += 1;
this.draw();
}
this.update();
}
This isn't drawing the image like I hope it would, but if I take it out this method like below, it does work?
function drawCircle() {
var MiddleImage = new Image();
MiddleImage.onload = function () {
var X = c.width - eighthWidth;
var Y = 200;
ctx.beginPath();
ctx.arc(X, Y, eighthWidth / 2.5, 0, 2 * Math.PI);
ctx.clip;
ctx.fillStyle = Color1;
ctx.fill();
ctx.closePath();
ctx.drawImage(MiddleImage, X - MiddleImage.width / 2, Y - MiddleImage.height / 2);
};
BankImage.src = "/Images/1.png";
requestAnimationFrame(drawCircle);
}
I have also tried using the Image.onLoad method, as I have copied the working method into the new loop.
The console is showing no errors.
You can see a JSFiddle here
The problem you're having is that you're loading the image within the draw function at every frame and not waiting for it to be loaded.
I've tweaked your code slightly so it will load and attach the image to your circle as you wish.
var c = document.getElementById('canvas');
c.width = window.innerWidth;
c.height = 400;
var ctx = c.getContext("2d");
var eighthWidth = c.width / 8;
var Color1 = "#9c9c9b";
var Color2 = "#9c9c9b";
var Circle1 = new Circle((c.width / 8) + (c.width / 2), 200, eighthWidth / 2.5, Color1, "1");
var Circle2 = new Circle(c.width - eighthWidth, 200, eighthWidth / 2.5, Color2, "2");
function Circle(x, y, radius, color, name) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.name = name;
this.image = new Image();
this.image.src = "https://www.gstatic.com/webp/gallery3/1.png";
var _this = this;
this.image_loaded = false;
this.image.addEventListener('load', function() {
_this.image_loaded = true;
} );
this.draw = function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
ctx.save();
ctx.clip();
ctx.drawImage(this.image, this.x - this.image.width / 2, this.y - this.image.height / 2);
ctx.restore();
}
this.update = function() {
//if(!this.image_loaded) return;
this.x += 1;
this.draw();
}
}
function animate() {
ctx.clearRect(0, 0, window.innerWidth, 400);
Circle1.update();
Circle2.update();
requestAnimationFrame(animate);
}
animate();
<canvas id="canvas" style="width:100%;"></canvas>
Is this what you want?
I'd like to draw an ellipse given a cx and cy position-property and a width and height property of the ellipse itself.
Below you can find some working code for this setup:
But now I want to generate a kind of "progress display" by painting a percentage (from 0 to 100) of the ellipse instead of the complete ellipse.
I have attached a graphic here to illustrate the whole thing:
I don't really have a clear idea how to do that. I would prefer a solution where I can do without resizing the canvas - just for performance reasons and I hope someone has a good idea how to solve my problem.
let canvas = document.getElementById("canvas")
let ctx = canvas.getContext("2d");
canvas.width = 400;
canvas.height = 280;
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height)
let ellipse = function(cx, cy, w, h) {
let lx = cx - w / 2,
rx = cx + w / 2,
ty = cy - h / 2,
by = cy + h / 2;
let magic = 0.551784;
let xmagic = magic * w / 2,
ymagic = h * magic / 2;
let region = new Path2D();
region.moveTo(cx, ty);
region.bezierCurveTo(cx + xmagic, ty, rx, cy - ymagic, rx, cy);
region.bezierCurveTo(rx, cy + ymagic, cx + xmagic, by, cx, by);
region.bezierCurveTo(cx - xmagic, by, lx, cy + ymagic, lx, cy);
region.bezierCurveTo(lx, cy - ymagic, cx - xmagic, ty, cx, ty);
ctx.strokeStyle = "red";
ctx.lineWidth = "10";
region.closePath();
ctx.stroke(region);
}
ellipse(canvas.width / 2, canvas.height / 2, 300, 120)
<canvas id="canvas"></canvas>
You can use the built-in function ctx.ellipse - first we draw the green line as a full ellipse. Next, draw the red partial ellipse on top:
let canvas = document.getElementById("canvas")
let ctx = canvas.getContext("2d");
canvas.width = 400;
canvas.height = 280;
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height)
function ellipse(ctx, color, x,y, w, h, thickness, angle) {
ctx.strokeStyle = color;
ctx.beginPath();
ctx.ellipse(canvas.width / 2, canvas.height / 2, h/2,w/2, Math.PI*3/2, 0, angle);
ctx.lineWidth = thickness;
ctx.stroke();
}
function ell(percent) {
let x= canvas.width / 2;
let y= canvas.height / 2;
let w=300;
let h=120;
let th = 10; // example thickness 10px
ellipse(ctx, '#608a32', x,y, w, h, th, Math.PI*2);
ellipse(ctx, '#ed3833', x,y , w, h, th+.3, 2*Math.PI*percent/100);
}
ell(90); // here we start draw for 90%
<canvas id="canvas"></canvas>
You can draw the ellipse with a bit of trigonometry
let canvas = document.getElementById("canvas")
let ctx = canvas.getContext("2d");
canvas.width = 400;
canvas.height = 170;
let ellipse = function(cx, cy, ds, de, w, h, color) {
for (var i = ds; i < de; i ++) {
var angle = i * ((Math.PI * 2) / 360);
var x = Math.cos(angle) * w;
var y = Math.sin(angle) * h;
ctx.beginPath();
ctx.fillStyle = color;
ctx.arc(cx+ x, cy+y, 6, 0, 2 * Math.PI);
ctx.fill();
}
}
let draw = function(cx, cy, ds, de, w, h, color) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
delta += 10
if (delta > 350) delta = 40
hw = canvas.width / 2
hh = canvas.height / 2
ellipse(hw, hh, 0, 360, 150, 60, "red")
ellipse(hw, hh, 0, delta, 150, 60, "blue")
ctx.font = "80px Arial";
ctx.fillStyle = "green";
ctx.fillText(Math.round(delta/3.6) + "%", hw-70, hh+30);
}
delta = 90
setInterval(draw, 100)
<canvas id="canvas"></canvas>
Once you have a nice function you can animate it
I am trying to add a few more circles in the circular loop using HTML5 canvas but it doesn't seem to work. I want the other circles to kind of trail the circle is already rotating there. I am also wondering how to make the circular motion non-linear (that is, it moves in varying speed like it has easing).
Can you guys help? :/ Thanks heaps. Below is my code.
<canvas id="canvas" width="450" height="450"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var w = canvas.width;
var h = canvas.height;
var dd = 4;
var angle = 0;
/*var cx = 197;
var cy = 199;
var radius = 200;*/
var cx = w/2;
var cy = h/2;
var radius = 200;
function draw(x, y) {
ctx.fillStyle = "rgb(38,161,220)";
ctx.strokeStyle = "rgb(38,161,220)";
ctx.clearRect(0, 0, w, h);
ctx.save();
ctx.beginPath();
ctx.beginPath();
//ctx.rect(x - 30 / 2, y - 30 / 2, 50, 30);
// Circle 1
ctx.arc(x-1/2, y-1/2, 10, 0, 2 * Math.PI, false);
ctx.fill();
ctx.stroke();
ctx.restore();
};
/** context.beginPath();
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke(); **/
var fps = 120;
window.requestAnimFrame = (function (callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / fps);
};
})();
function animate() {
setTimeout(function () {
requestAnimFrame(animate);
// increase the angle of rotation
//angle += Math.acos(1-Math.pow(dd/radius,2)/2);
angle += Math.acos(1-Math.pow(dd/radius,2)/2);
// calculate the new ball.x / ball.y
var newX = cx + radius * Math.cos(angle);
var newY = cy + radius * Math.sin(angle);
// draw
draw(newX, newY);
// draw the centerpoint
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.stroke();
}, 1000 / fps );
}
animate();
</script>
Easing between where and where?
Heres some non-linear angular velocities:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<canvas id="canvas" width="450" height="450"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var w = canvas.width;
var h = canvas.height;
var dd = 4;
var angle = 0;
var cx = w/2;
var t = 0;
var velocity = 0.01;
var cy = h/2;
var radius = 200;
function draw(x, y) {
ctx.fillStyle = "rgb(38,161,220)";
ctx.strokeStyle = "rgb(38,161,220)";
ctx.clearRect(0, 0, w, h);
ctx.save();
ctx.beginPath();
ctx.beginPath();
ctx.arc(x-1/2, y-1/2, 10, 0, 2 * Math.PI, false);
ctx.fill();
ctx.stroke();
ctx.restore();
};
var fps = 120;
window.requestAnimFrame = (function (callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / fps);
};
})();
function animate() {
setTimeout(function () {
// increase the angle of rotation
angle += velocity;
//sinusoidal velocity
velocity += 0.005 * (Math.sin(t));
t += 0.1;
// randomzed velocity:
//velocity += 0.001 * (Math.random() - 1);
// draw
// calculate the new ball.x / ball.y
var newX = cx + radius * Math.cos(angle);
var newY = cy + radius * Math.sin(angle);
draw(newX, newY);
// draw the centerpoint
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.stroke();
requestAnimFrame(animate);
}, 1000 / fps );
}
animate();
</script>
</body>
</html>
You can make a circle class like this:
var Circle = function(radius,velocity,etc){
this.radius = radius
this.velocity = velocity
this.etc = etc
// and whatever other properties you think you need
}
then
var circleArray = []
for(var i = 0; i < circleCount; i++){
circleArray.push(new Circle(2,0.1,"some_property"))
}
then inside animate():
circleArray.forEach(function(circle){
//drawing code
})
Until you ask a more specific question, thats all I can give you