Progress var using canvas and javascript - javascript

I'm trying to make a circle progress bar circle to show my skills but since I put a setInterval function, It doesn't work. I think the ligne context.arc() doesn't take the values and so it shows nothing, but I can't get throught this problem, how can i do ? Thank you in advance
HTML :
<section id="skills">
<div class="load-container">
<canvas id="canvas" width="800" height="800"></canvas>
<span id="percent"></span>
</div>
</section>
JavaScript :
<script>
class Circle
{
constructor(x, y, percent)
{
this.posX = x;
this.posY = y;
this.percent = percent;
this.radius = 100;
}
drawing(context)
{
let unitValue = (Math.PI - 0.5 * Math.PI) / 25;
let startAngle = 0;
let endAngle = startAngle + (this.percent * unitValue);
let arcInterval = setInterval (function()
{
startAngle += 1;
/*grey circle*/
context.beginPath();
context.arc(this.posX, this.posY, this.radius, startAngle, (2 * Math.PI), false);
context.strokeStyle = '#b1b1b1';
context.lineWidth = '10';
context.stroke();
/*blue circle*/
context.beginPath();
context.arc(this.posX, this.posY, this.radius, startAngle, endAngle, false);
context.strokeStyle = '#3949AB';
context.lineWidth = '10';
context.stroke();
if (startAngle >= endAngle)
{
clearInterval(arcInterval);
}
}, 500);
}
}
function setup()
{
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
/*draw the circles*/
let circle = new Circle(150, 200, 86);
circle.drawing(context);
let circle2 = new Circle(400, 200, 76);
circle2.drawing(context);
let circle3 = new Circle(650, 200, 44);
circle3.drawing(context);
let circle4 = new Circle(150, 450, 35);
circle4.drawing(context);
}
window.onload = function()
{
setup();
}
</script>

Here is how I would do it...
Keep your class Circle code as small as possible, and do the loop (setInterval) in the setup, that way you can clear the entire canvas there, I think that is a better way.
class Circle {
constructor(x, y) {
this.posX = x;
this.posY = y;
}
drawing(context, radius, startAngle, endAngle) {
context.beginPath();
context.arc(this.posX, this.posY, radius, startAngle, endAngle, false);
context.stroke();
}
}
function setup() {
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
let startAngle = 0;
let endAngle = 2 * Math.PI
/*draw the circles*/
let circle = new Circle(30, 30);
let circ2 = new Circle(60, 80);
let circ3 = new Circle(80, 40);
let arcInterval = setInterval(function() {
startAngle += 0.1;
context.clearRect(0, 0, 180, 180);
circle.drawing(context, 20, startAngle, endAngle - 1);
circ2.drawing(context, 20, startAngle - 1, endAngle);
circ3.drawing(context, 15 - startAngle * 2, 0, 2 * Math.PI);
if (startAngle > endAngle) {
clearInterval(arcInterval);
}
}, 100);
}
window.onload = function() {
setup();
}
<canvas id="canvas" width="180" height="180"></canvas>
As you can see I'm passing multiple parameters to the drawing function:
drawing(context, radius, startAngle, endAngle)
that way we can control those parameters from the loop, and with a bit of math you can make the progress animation more fun, but I let you to fine-tune that.

Try this. I've just changed the step count. You may change it from 5 to what ever you want.
<script>
class Circle {
constructor(x, y, percent) {
this.posX = x;
this.posY = y;
this.percent = percent;
this.radius = 100;
this.arcInterval = null; // Changed
}
drawCallback(ctx, start, end) { // Added
let inc = 1;
return () => {
inc += 1;
console.log(inc);
drawArc(ctx, this.posX, this.posY, this.radius, '#3949AB', start, end * inc / 5);
if (inc > 5) {
clearInterval(this.arcInterval);
}
}
}
drawing(context) { // Added
let unitValue = 0.5 * Math.PI / 25; // Changed
const startAngle = 0; // Changed
const endAngle = startAngle + (this.percent * unitValue); // Changed
/* grey circle */
drawArc(context, this.posX, this.posY, this.radius, '#b1b1b1', startAngle, 2 * Math.PI); // Changed
/* blue circle */
this.arcInterval = setInterval(this.drawCallback(context, startAngle, endAngle), 500); // Changed
}
}
function drawArc(ctx, posX, posY, radius, color, startAngle, endAngle) { // Added
ctx.beginPath();
ctx.arc(posX, posY, radius, startAngle, endAngle, false);
ctx.strokeStyle = color;
ctx.lineWidth = '10';
ctx.stroke();
}
function setup() {
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
/*draw the circles*/
let circle = new Circle(150, 200, 86);
circle.drawing(context);
let circle2 = new Circle(400, 200, 76);
circle2.drawing(context);
let circle3 = new Circle(650, 200, 44);
circle3.drawing(context);
let circle4 = new Circle(150, 450, 35);
circle4.drawing(context);
}
window.onload = function () {
setup();
}
</script>

<!doctype html>
<html>
<body>
<section id="skills">
<div class="load-container">
<canvas id="canvas" width="800" height="800"></canvas>
<span id="percent"></span>
</div>
</section>
<script>
class Circle
{
constructor(x, y, percent) {
this.posX = x;
this.posY = y;
this.percent = percent;
this.radius = 100;
this.startAngle = 0; // <---
this.unitValue = (Math.PI - 0.5 * Math.PI) / 25; //
this.endAngle = this.startAngle + (this.percent * this.unitValue);
}
drawing(context) {
this.arcInterval = setInterval (function(ctx,that) {
that.startAngle += 1;
/*grey circle*/
ctx.beginPath();
ctx.arc(that.posX, that.posY, that.radius, that.startAngle, (2 * Math.PI), false);
ctx.strokeStyle = '#b1b1b1';
ctx.lineWidth = '10';
ctx.stroke();
/*blue circle*/
ctx.beginPath();
ctx.arc(that.posX, that.posY, that.radius, that.startAngle, that.endAngle, false);
ctx.strokeStyle = '#3949AB';
ctx.lineWidth = '10';
ctx.stroke();
// Why stop ?
// if (that.startAngle >= that.endAngle) { clearInterval(that.arcInterval); }
}, 500,context, this); // <------ this -> that and context -> ctx
}
}
function setup() {
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
/*create circles*/
window.myCircles = [new Circle(150, 200, 86),
new Circle(400, 200, 76),
new Circle(650, 200, 44),
new Circle(150, 450, 35)];
for (let o of window.myCircles) { o.drawing(context); }
}
window.onload = function() { setup(); }
</script>
</body>
</html>
You can try the funny way ->
class Circle
{
constructor(x, y, percent) {
this.posX = x;
this.posY = y;
this.percent = percent;
this.radius = 100;
this.startAngle = 0; // <---
this.unitValue = (Math.PI - 0.5 * Math.PI) / 25; //
this.endAngle = this.startAngle + (this.percent * this.unitValue);
}
drawing(context) {
this.arcInterval = setInterval (function(ctx,that) {
that.startAngle += 1;
/*grey circle*/
ctx.beginPath();
ctx.arc(that.posX, that.posY, that.radius, that.startAngle, (2 * Math.PI), false);
ctx.strokeStyle = '#b1b1b1';
ctx.lineWidth = '10';
ctx.stroke();
/*blue circle*/
ctx.beginPath();
ctx.arc(that.posX, that.posY, that.radius, that.startAngle, that.endAngle, false);
ctx.strokeStyle = '#3949AB';
ctx.lineWidth = '10';
ctx.stroke();
// Why stop ?
// if (that.startAngle >= that.endAngle) { clearInterval(that.arcInterval); }
}, 500,context, this); // <------ this -> that and context -> ctx
}
}
function setup() {
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
/*create circles*/
window.myCircles = [new Circle(150, 200, 86),
new Circle(400, 200, 76),
new Circle(650, 200, 44),
new Circle(150, 450, 35)];
for (let o of window.myCircles) { o.drawing(context); }
}
window.onload = function() { setup(); }

Related

Change color inside circle

I want to change color inside circle example:(two color) from red to blue and blue to red.
I tried this using if else but it didn't work for me.
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
// for canvas size
var window_width = window.innerWidth;
var window_height = window.innerHeight;
canvas.width = window_width;
canvas.height = window_height;
let hit_counter = 0;
// object is created using class
class Circle {
constructor(xpos, ypos, radius, speed, color, text) {
this.position_x = xpos;
this.position_y = ypos;
this.radius = radius;
this.speed = speed;
this.dx = 1 * this.speed;
this.dy = 1 * this.speed;
this.text = text;
this.color = color;
}
// creating circle
draw(context) {
context.beginPath();
context.strokeStyle = this.color;
context.fillText(this.text, this.position_x, this.position_y);
context.textAlign = "center";
context.textBaseline = "middle"
context.font = "20px Arial";
context.lineWidth = 5;
context.arc(this.position_x, this.position_y, this.radius, 0, Math.PI * 2);
context.stroke();
context.closePath();
}
update() {
this.text = hit_counter;
context.clearRect(0, 0, window_width, window_height)
this.draw(context);
if ((this.position_x + this.radius) > window_width) {
this.dx = -this.dx;
hit_counter++;
}
if ((this.position_x - this.radius) < 0) {
this.dx = -this.dx;
hit_counter++;
}
if ((this.position_y - this.radius) < 0) {
this.dy = -this.dy;
hit_counter++;
}
if ((this.position_y + this.radius) > window_height) {
this.dy = -this.dy;
hit_counter++;
}
this.position_x += this.dx;
this.position_y += this.dy;
}
}
let my_circle = new Circle(100, 100, 50, 3, 'Black', hit_counter);
let updateCircle = function() {
requestAnimationFrame(updateCircle);
my_circle.update();
}
updateCircle();
//for color
function changeColor(event) {
var coloorr = event.value;
canvas.style.background = coloorr;
}
// I tried it in bllk function but it didn't work for me.
function bllk() {
canvas.style.background = "black";
context.fillStyle = "blue";
// I tried it in bllk function but it didn't work for me.
// setInterval(() => {
// if(context.fillStyle=="blue"){
// context.fillStyle=red;
// context.fill();
// }else if(context.fillStyle=="red"){
// context.fillStyle=blue;
// context.fill();
// }else if(context.fillStyle=="blue"){
// context.fillStyle=red;
// context.fill();
// }
// }, 1000);
}
<!-- On clicking button Hi How to apply two color one by one to the numbers inside the circle ? I tried it in bllk function but it didn't work for me. -->
<button onclick="bllk()">Hi</button>
<canvas id="canvas"></canvas>
The code needed a little upgrade:
decoupling variables from each other & the global space
adding some internal attributes & methods to the circle
Now it's possible to change the background color of the canvas, the outline and text of the circle, and the background of the circle separataley.
const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");
// for canvas size
const window_width = window.innerWidth;
const window_height = window.innerHeight;
canvas.width = window_width;
canvas.height = window_height;
// object is created using class
class Circle {
constructor(xpos, ypos, radius, speed, color, text) {
this.position_x = xpos;
this.position_y = ypos;
this.radius = radius;
this.speed = speed;
this.dx = 1 * this.speed;
this.dy = 1 * this.speed;
this.text = text;
this.color = color;
this.fillColor = "white" // added as a default value
this.hit_counter = 0
}
// outline & text in circle
drawOutline({
ctx
}) {
ctx.beginPath();
ctx.strokeStyle = this.color;
ctx.fillStyle = this.color
ctx.fillText(this.text, this.position_x, this.position_y);
ctx.textAlign = "center";
ctx.textBaseline = "middle"
ctx.font = "20px Arial";
ctx.lineWidth = 5;
ctx.arc(this.position_x, this.position_y, this.radius, 0, Math.PI * 2);
ctx.stroke();
ctx.closePath();
}
// background of the circle
drawFill({
ctx,
color
}) {
ctx.beginPath();
ctx.fillStyle = this.fillColor
ctx.arc(this.position_x, this.position_y, this.radius, 0, Math.PI * 2);
ctx.fill();
ctx.closePath();
}
// drawing the circle from two pieces
draw(ctx) {
this.drawFill({
ctx
})
this.drawOutline({
ctx
})
}
// color change function
setColor({
outline,
fill
}) {
this.color = outline
this.fillColor = fill
}
update(ctx) {
this.text = this.hit_counter;
ctx.clearRect(0, 0, window_width, window_height)
this.draw(context);
if ((this.position_x + this.radius) > window_width) {
this.dx = -this.dx;
this.hit_counter++;
}
if ((this.position_x - this.radius) < 0) {
this.dx = -this.dx;
this.hit_counter++;
}
if ((this.position_y - this.radius) < 0) {
this.dy = -this.dy;
this.hit_counter++;
}
if ((this.position_y + this.radius) > window_height) {
this.dy = -this.dy;
this.hit_counter++;
}
this.position_x += this.dx;
this.position_y += this.dy;
}
}
const my_circle = new Circle(100, 100, 50, 3, 'Black');
const updateCircle = function(ctx) {
requestAnimationFrame(() => updateCircle(ctx));
my_circle.update(ctx);
}
updateCircle(context);
// I tried it in bllk function but it didn't work for me.
function bllk1() {
canvas.style.background = "black";
my_circle.setColor({
outline: "red",
fill: "yellow"
})
}
function bllk() {
canvas.style.background = "black";
my_circle.setColor({
outline: "black",
fill: "blue"
})
setInterval(() => {
const fill = my_circle.fillColor === "blue" ? "red" : "blue"
my_circle.setColor({
outline: "black",
fill,
})
}, 1000);
}
<!-- On clicking button Hi How to apply two color one by one to the numbers inside the circle ? I tried it in bllk function but it didn't work for me. -->
<button onclick="bllk()">Hi</button>
<canvas id="canvas"></canvas>
I simplified your code to just focus on what you asked on the comments:
changing red to blue and blue to red color continuously
To focus on that specific problem we don't need the Circle moving or the collisions with the borders, in the future when you are asking a question you should do the same, provide a minimal example, remove everything else that is not specifically related to your problem.
To solve your issue we can pass a colors parameter to the draw function, that way we let it know what colors to use for the circle and the text, or anything you might want to add in the future.
See code sample below:
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
canvas.width = canvas.height = 100;
class Circle {
draw(xpos, ypos, radius, colors) {
context.beginPath();
context.arc(xpos, ypos, radius, 0, Math.PI * 2);
context.fillStyle = colors.circle;
context.fill();
context.beginPath();
context.font = "20px Arial";
context.fillStyle = colors.text;
context.fillText("0", xpos, ypos);
}
}
let my_circle = new Circle();
let colors = {text:"red", circle:"blue"};
let updateCircle = function() {
requestAnimationFrame(updateCircle);
context.clearRect(0, 0, canvas.width, canvas.height)
my_circle.draw(50, 50, 20, colors);
}
updateCircle();
setInterval(() => {
if (colors.text == "blue") {
colors = {text:"red", circle:"blue"};
} else {
colors = {text:"blue", circle:"red"};
}
}, 1000);
<canvas id="canvas"></canvas>

Display incrementing values

I have succeeded in making an animation with multiple circular progress bars, but now there is a problem to display; each percent of that values incrementing in the middle of my circles. I don't know how to do this. If you have ideas which help me to do that. I would like to display all of these values.
Here is my code:
class GreyCircle {
constructor(x, y, radius) {
this.posX = x;
this.posY = y;
this.radius = radius;
}
drawing1(context, startAngle, endAngle) {
/*grey circle*/
context.beginPath();
context.arc(this.posX, this.posY, this.radius, startAngle, endAngle, false);
context.strokeStyle = '#f3f3f3';
context.lineWidth = '20';
context.stroke();
}
}
class BlueCircle {
constructor(x, y, r) {
this.posX = x;
this.posY = y;
this.radius = r;
}
drawing2(context, percent) {
let unitValue = (Math.PI - 0.5 * Math.PI) / 25;
let startAngle = 0;
let endAngle = startAngle + (percent * unitValue);
let arcInterval = setInterval(() => {
startAngle += .1;
percentText.textContent = startAngle + unitValue;
/*blue circle*/
context.beginPath();
context.arc(this.posX, this.posY, this.radius, startAngle, startAngle + unitValue, false);
context.strokeStyle = '#f39c12';
context.lineWidth = '20';
context.stroke();
context.lineCap = 'round';
if (startAngle >= endAngle) {
clearInterval(arcInterval);
}
}, 50);
}
}
function setup() {
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
/*draw the grey circles*/
let greyCircle1 = new GreyCircle(150, 200, 100);
greyCircle1.drawing1(context, 0, 2 * Math.PI);
let greyCircle2 = new GreyCircle(400, 200, 100);
greyCircle2.drawing1(context, 0, 2 * Math.PI);
let greyCircle3 = new GreyCircle(650, 200, 100);
greyCircle3.drawing1(context, 0, 2 * Math.PI);
/*draw the blue circles*/
let blueCircle1 = new BlueCircle(150, 200, 100);
blueCircle1.drawing2(context, 80);
let blueCircle2 = new BlueCircle(400, 200, 100);
blueCircle2.drawing2(context, 76)
let blueCircle3 = new BlueCircle(650, 200, 100);
blueCircle3.drawing2(context, 44);
}
window.onload = function() {
setup();
}
#canvas {
position: relative;
margin: auto;
display: block;
}
#percentText {
position: absolute;
top: 50%;
left: 50;
}
<section id="skills">
<div class="load-container">
<canvas id="canvas" width="800" height="800"></canvas>
<span id="percentText">%</span>
</div>
</section>
Not exactly sure, what are you trying to accomplish, but if you want to print the text with fixed percentage, you could do something like this:
class GreyCircle
{
constructor(x, y, radius) {
this.posX = x;
this.posY = y;
this.radius = radius;
}
drawing1(context, startAngle, endAngle)
{
/*grey circle*/
context.beginPath();
context.arc(this.posX, this.posY, this.radius, startAngle, endAngle, false);
context.strokeStyle = '#f3f3f3';
context.lineWidth = '20';
context.stroke();
}
}
class BlueCircle
{
constructor(x, y, r)
{
this.posX = x;
this.posY = y;
this.radius = r;
}
drawing2(context, percent)
{
let unitValue = (Math.PI - 0.5 * Math.PI) / 25;
let startAngle = 0;
let endAngle = startAngle + (percent * unitValue);
var m = context.measureText(percent + "%");
context.save();
context.font = "20px Verdana"
context.fillText(percent + "%", this.posX - this.radius + (this.radius - m.width), this.posY + 10);
context.restore();
let arcInterval = setInterval(() => {
startAngle += .1;
/*blue circle*/
context.beginPath();
context.arc(this.posX, this.posY, this.radius, startAngle, startAngle + unitValue, false);
context.strokeStyle = 'blue';
context.lineWidth = '20';
context.stroke();
context.lineCap = 'round';
if (startAngle >= endAngle) {
clearInterval(arcInterval);
}
}, 50);
}
}
function setup()
{
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
let percentText = document.getElementById('percentText');
/*draw the grey circles*/
let greyCircle1 = new GreyCircle(150, 200, 100);
greyCircle1.drawing1(context, 0, 2 * Math.PI);
let greyCircle2 = new GreyCircle(400, 200, 100);
greyCircle2.drawing1(context, 0, 2 * Math.PI);
let greyCircle3 = new GreyCircle(650, 200, 100);
greyCircle3.drawing1(context, 0, 2 * Math.PI);
/*draw the blue circles*/
let blueCircle1 = new BlueCircle(150, 200, 100);
blueCircle1.drawing2(context, 80);
let blueCircle2 = new BlueCircle(400, 200, 100);
blueCircle2.drawing2(context, 76)
let blueCircle3 = new BlueCircle(650, 200, 100);
blueCircle3.drawing2(context, 44);
}
window.onload = function ()
{
setup();
}
<canvas id="canvas" width="1920" height="1080">
But if you wanted the percentage to update with the loading, you would have to put the printing of the text inside the loop. Something like this:
class GreyCircle
{
constructor(x, y, radius) {
this.posX = x;
this.posY = y;
this.radius = radius;
}
drawing1(context, startAngle, endAngle)
{
/*grey circle*/
context.beginPath();
context.arc(this.posX, this.posY, this.radius, startAngle, endAngle, false);
context.strokeStyle = '#f3f3f3';
context.lineWidth = '20';
context.stroke();
}
}
class BlueCircle
{
constructor(x, y, r)
{
this.posX = x;
this.posY = y;
this.radius = r;
}
drawing2(context, percent)
{
let unitValue = (Math.PI - 0.5 * Math.PI) / 25;
let startAngle = 0;
let endAngle = startAngle + (percent * unitValue);
let arcInterval = setInterval(() => {
startAngle += .1;
/*blue circle*/
context.beginPath();
context.arc(this.posX, this.posY, this.radius, startAngle, startAngle + unitValue, false);
context.strokeStyle = 'blue';
context.lineWidth = '20';
context.stroke();
context.lineCap = 'round';
var percentNow = Math.round(percent * startAngle/endAngle)
var m = context.measureText(percentNow + " %");
context.save();
context.clearRect(this.posX - this.radius + (this.radius - m.width), this.posY - 10, m.width * 3, 20)
context.font = "20px Verdana"
context.fillText(percentNow + " %", this.posX - this.radius + (this.radius - m.width), this.posY + 10);
context.restore();
if (startAngle >= endAngle) {
clearInterval(arcInterval);
}
}, 50);
}
}
function setup()
{
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
let percentText = document.getElementById('percentText');
/*draw the grey circles*/
let greyCircle1 = new GreyCircle(150, 200, 100);
greyCircle1.drawing1(context, 0, 2 * Math.PI);
let greyCircle2 = new GreyCircle(400, 200, 100);
greyCircle2.drawing1(context, 0, 2 * Math.PI);
let greyCircle3 = new GreyCircle(650, 200, 100);
greyCircle3.drawing1(context, 0, 2 * Math.PI);
/*draw the blue circles*/
let blueCircle1 = new BlueCircle(150, 200, 100);
blueCircle1.drawing2(context, 80);
let blueCircle2 = new BlueCircle(400, 200, 100);
blueCircle2.drawing2(context, 76)
let blueCircle3 = new BlueCircle(650, 200, 100);
blueCircle3.drawing2(context, 44);
}
window.onload = function ()
{
setup();
}
<canvas id="canvas" width="1920" height="1080">

Using Canvas via JavaScript, how can I draw a picture X number of times and within Y parameters?

I'm trying to draw a smiley face X number of times, and then the smiley face are Y radius from the center of the canvas. I also want to add a function where it allows the drawing to stay within the canvas, not outside as well as two functions to allow maximum number of smiley face in the circle and the maximum radius it can go up to. Eventually, I want my final product to end up looking something like this: https://imgur.com/VvDcFXq. I am new to Canvas and any help is greatly appreciated
<!DOCTYPE>
<html lang="en">
<meta charset="UTF-8">
<head>
<title>CPSC 1045 Assignment 7 - Smiley Rotator</title>
</head>
<body>
<h1>CPSC 1045 Assignment 7 - Simley Rotator</h1>
<p>Enter a number of smiles to draw<input type="number" min="0" max="9" id="NumberofSmiles"></p>
<p>Enter how far from the center of the canvas to draw them<input type="number" min="0" max="151" id="radius"></p>
<button id="draw">Draw</button><br>
<canvas id="myCanvas" height="400" width="400" style="border: 1px solid black">
<script>
let c, ctx, pos, centerX, centerY, radius, eyeRadius, eyeXOffset, eyeYOffset
document.getElementById("draw").onclick = checkNumber;
document.getElementById("draw").onclick = checkRadius;
function placement() {
c = document.getElementById("myCanvas");
ctx = c.getContext("2d");
centerX = c.width / 2;
centerY = c.height / 2;
radius = 70;
eyeRadius = 10;
eyeXOffset = 25;
eyeYOffset = 20;
reset();
}
function drawFace(){
// Draw the yellow circle
ctx.beginPath();
ctx.arc(centerX + pos.left, centerY + pos.top, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'yellow';
ctx.fill();
ctx.lineWidth = 5;
ctx.strokeStyle = 'black';
ctx.stroke();
ctx.closePath();
}
function drawEyes(){
// Draw the eyes
let eyeX = centerX + pos.left - eyeXOffset;
let eyeY = centerY + pos.top - eyeYOffset;
ctx.beginPath();
ctx.arc(eyeX, eyeY, eyeRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'black';
ctx.fill();
ctx.closePath();
ctx.beginPath();
eyeX = centerX + pos.left + eyeXOffset;
ctx.arc(eyeX, eyeY, eyeRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'black';
ctx.fill();
ctx.closePath();
}
function drawMouth(){
// Draw the mouth
ctx.beginPath();
ctx.arc(centerX + pos.left, centerY + pos.top, 50, 0, Math.PI, false);
ctx.stroke();
ctx.closePath();
}
function draw(x,y) {
clear();
drawFace();
drawEyes();
drawMouth();
}
function clear() {
ctx.clearRect(0, 0, c.width, c.height);
}
function checkNumber() {
var input = document.getElementById("NumberofSmiles").value;
if (input > 9) {
alert("You have enter an invalid number");
}
}
function checkRadius() {
var inputs = document.getElementById("radius").value;
if (inputs > 150) {
alert("You have entered an invalid radius");
}
}
function checkmyvalue() {
checkRadius();
checkNumber();
}
</script>
</body>
</html>
I've tried to save as much as I could from your code.
Since you want to rotate the smileys I draw them around the origin of the canvas and then I translate to the position and rotate the context:
ctx.translate(pos.left,pos.top)
ctx.rotate(Angle);
Another change I've made: I've changed the radius of the smiley because I thought it was too big but you can change it back at what you want. Everything else will scale proportionally.
I hope this is what you need.
const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
let center = {};
center.x = c.width / 2;
center.y = c.height / 2;
let face_radius = 30;
let eyeRadius = face_radius / 7;
let mouth_radius = face_radius * 0.7;
let eyeXOffset = face_radius * 0.36;
let eyeYOffset = face_radius * 0.28;
function drawFace() {
// Draw the yellow circle
ctx.beginPath();
ctx.arc(0, 0, face_radius, 0, 2 * Math.PI, false);
ctx.fillStyle = "yellow";
ctx.fill();
ctx.lineWidth = 5;
ctx.strokeStyle = "black";
ctx.stroke();
ctx.closePath();
}
function drawEyes() {
// Draw the eyes
let eyeX = - eyeXOffset;
let eyeY = - eyeYOffset;
ctx.beginPath();
ctx.arc(eyeX, eyeY, eyeRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = "black";
ctx.fill();
ctx.closePath();
ctx.beginPath();
eyeX = eyeXOffset;
ctx.arc(eyeX, eyeY, eyeRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = "black";
ctx.fill();
ctx.closePath();
}
function drawMouth() {
// Draw the mouth
ctx.beginPath();
ctx.arc(0, 0, mouth_radius, 0, Math.PI, false);
ctx.stroke();
ctx.closePath();
}
function clear() {
ctx.clearRect(0, 0, c.width, c.height);
}
function drawSmiley(pos,Angle) {
ctx.save();
ctx.translate(pos.left,pos.top)
ctx.rotate(Angle);
drawFace();
drawEyes();
drawMouth();
ctx.restore();
}
function checkNumber() {
let n = parseInt(NumberofSmiles.value);
if (n > 0 && n < 9) {
return n;
} else {
alert("You have enter an invalid number");
clear();
}
}
function checkRadius() {
let R = parseInt(_radius.value);
let maxR = c.width/2 - face_radius
if (R > 0 && R < maxR) {
return R;
} else {
alert("The radius has to be smaller than "+ maxR );
clear();
}
}
function checkmyvalue() {
let R = checkRadius();
let N = checkNumber();
let angle = 2 * Math.PI / N;
clear();
for (let i = 0; i < N; i++) {
let Angle = angle * i;
let pos = {};
pos.left = center.x + R * Math.cos(Angle);
pos.top = center.y + R * Math.sin(Angle);
drawSmiley(pos,Angle);
}
}
draw.addEventListener("click", checkmyvalue);
canvas{border:1px solid}
<h1>CPSC 1045 Assignment 7 - Simley Rotator</h1>
<p>Enter a number of smiles to draw<input type="number" min="0" max="9" id="NumberofSmiles"></p>
<p>Enter how far from the center of the canvas to draw them<input type="number" min="0" max="151" id="_radius"></p>
<button id="draw">Draw</button><br>
<canvas id="myCanvas" height="400" width="400" style="border: 1px solid black">

In Canvas via JavaScript, How Can I move an object to a different coordinate?

I have here A simple "game" with controls, and the reset button to reset the image drawn (smiley face) back to the center. I have tried this code with this an empty circle and I was able to move it around via the buttons without any problems. I proceeded to decorate the circle and now I am not able to move my drawn image. Any feedback or solution would be appreciated.
<!DOCTYPE>
<html lang="en">
<meta charset="UTF-8">
<body>
<button id="reset">Reset</button></br>
<canvas id="myCanvas" width="250" height="250" style="border:1px solid#000000;"></canvas></br>
<button id="left">Left</button>
<button id="up">Up</button>
<button id="down">Down</button>
<button id="right">Right</button>
<script>
let c, ctx, pos, centre = { x: 95, y: 50 }
window.onload = function drawSmile(){
let c = document.getElementById("myCanvas");
let ctx = c.getContext("2d");
let centerX = c.width / 2;
let centerY = c.height / 2;
let radius = 70;
let eyeRadius = 10;
let eyeXOffset = 25;
let eyeYOffset = 20;
// draw the yellow circle
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'yellow';
ctx.fill();
ctx.lineWidth = 5;
ctx.strokeStyle = 'black';
ctx.stroke();
// draw the eyes
ctx.beginPath();
var eyeX = centerX - eyeXOffset;
var eyeY = centerY - eyeXOffset;
ctx.arc(eyeX, eyeY, eyeRadius, 0, 2 * Math.PI, false);
var eyeX = centerX + eyeXOffset;
ctx.arc(eyeX, eyeY, eyeRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'black';
ctx.fill();
// draw the mouth
ctx.beginPath();
ctx.arc(centerX, centerY, 50, 0, Math.PI, false);
ctx.stroke();
reset();
}
function draw(){
clear();
ctx.beginPath();
ctx.arc(centre.x + pos.left, centre.y + pos.top, 40, 0, 2*Math.PI);
ctx.stroke();
}
function clear(){
ctx.clearRect(0, 0, 2000, 1000);
}
function reset() {
pos = { left: 0, top: 0 }
draw();
}
function up() {
ctx.clearRect(0, 0, 2000, 1000);
pos.top-= 20;
draw();
}
function down() {
pos.top+= 20;
draw();
}
function left() {
pos.left-= 20;
draw();
}
function right() {
pos.left+= 20;
draw();
}
document.getElementById("reset").onclick = reset;
document.getElementById("up").onclick = up;
document.getElementById("down").onclick = down;
document.getElementById("left").onclick = left;
document.getElementById("right").onclick = right;
</script>
</body>
</html>
Do check the below code. It is similar to the last drawing of empty circle, I have just included the correct position calculations, and included closePath() method at appropriate places.
let c
, ctx
, pos
, centerX
, centerY
, radius
, eyeRadius
, eyeXOffset
, eyeYOffset
window.onload = function() {
c = document.getElementById("myCanvas");
ctx = c.getContext("2d");
centerX = c.width / 2;
centerY = c.height / 2;
radius = 70;
eyeRadius = 10;
eyeXOffset = 25;
eyeYOffset = 20;
reset();
}
function drawFace(){
// Draw the yellow circle
ctx.beginPath();
ctx.arc(centerX + pos.left, centerY + pos.top, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'yellow';
ctx.fill();
ctx.lineWidth = 5;
ctx.strokeStyle = 'black';
ctx.stroke();
ctx.closePath();
}
function drawEyes(){
// Draw the eyes
var eyeX = centerX + pos.left - eyeXOffset;
var eyeY = centerY + pos.top - eyeYOffset;
ctx.beginPath();
ctx.arc(eyeX, eyeY, eyeRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'black';
ctx.fill();
ctx.closePath();
ctx.beginPath();
eyeX = centerX + pos.left + eyeXOffset;
ctx.arc(eyeX, eyeY, eyeRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'black';
ctx.fill();
ctx.closePath();
}
function drawMouth(){
// Draw the mouth
ctx.beginPath();
ctx.arc(centerX + pos.left, centerY + pos.top, 50, 0, Math.PI, false);
ctx.stroke();
ctx.closePath();
}
function draw() {
clear();
drawFace();
drawEyes();
drawMouth();
}
function clear() {
ctx.clearRect(0, 0, c.width, c.height);
}
function reset() {
pos = {
left: 0,
top: 0
}
draw();
}
function up() {
pos.top -= 20;
draw();
}
function down() {
pos.top += 20;
draw();
}
function left() {
pos.left -= 20;
draw();
}
function right() {
pos.left += 20;
draw();
}
document.getElementById("reset").onclick = reset;
document.getElementById("up").onclick = up;
document.getElementById("down").onclick = down;
document.getElementById("left").onclick = left;
document.getElementById("right").onclick = right;
<!DOCTYPE>
<html lang="en">
<meta charset="UTF-8">
<body>
<button id="reset">Reset</button><br>
<canvas id="myCanvas" width="250" height="250" style="border:1px solid#000000;"></canvas><br>
<button id="left">Left</button>
<button id="up">Up</button>
<button id="down">Down</button>
<button id="right">Right</button>
</body>
</html>

Circle won't be drawn on canvas

Hi I try to make an animation. A circle should run from right to left. Now the problem is that no circle become drawed in the canvas. I check in chromes developer tool the console log but there was no error. Have anyone a idea what the mistake is?
window.onload = window.onresize = function() {
var C = 1; // canvas width to viewport width ratio
var el = document.getElementById("myCanvas");
var viewportWidth = window.innerWidth;
var viewportHeight = window.innerHeight;
var canvasWidth = viewportWidth * C;
var canvasHeight = viewportHeight;
el.style.position = "fixed";
el.setAttribute("width", canvasWidth);
el.setAttribute("height", canvasHeight);
var x = canvasWidth / 100;
var y = canvasHeight / 100;
var ballx = canvasWidth / 100;
var n;
window.ctx = el.getContext("2d");
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// draw triangles
function init() {
ballx;
return setInterval(main_loop, 1000);
}
function drawcircles() {
function getRandomElement(array) {
if (array.length == 0) {
return undefined;
}
return array[Math.floor(Math.random() * array.length)];
}
var circles = [
'#FFFF00',
'#FF0000',
'#0000FF'
];
ctx.beginPath();
ctx.arc(ballx * 108, canvasHeight / 2, x * 5, 0, 2 * Math.PI, false);
ctx.fillStyle = JSON.stringify(getRandomElement(circles));
ctx.fill();
ctx.closePath;
}
function draw() {
var counterClockwise = false;
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
//first halfarc
ctx.beginPath();
ctx.arc(x * 80, y * 80, y * 10, 0 * Math.PI, 1 * Math.PI, counterClockwise);
ctx.lineWidth = y * 1;
ctx.strokeStyle = 'black';
ctx.stroke();
ctx.closePath;
//second halfarc
ctx.beginPath();
ctx.arc(x * 50, y * 80, y * 10, 0 * Math.PI, 1 * Math.PI, counterClockwise);
ctx.lineWidth = y * 1;
ctx.strokeStyle = 'black';
ctx.stroke();
ctx.closePath;
//third halfarc
ctx.beginPath();
ctx.arc(x * 20, y * 80, y * 10, 0 * Math.PI, 1 * Math.PI, counterClockwise);
ctx.lineWidth = y * 1;
ctx.strokeStyle = 'black';
ctx.stroke();
ctx.closePath;
// draw stop button
ctx.beginPath();
ctx.moveTo(x * 87, y * 2);
ctx.lineTo(x * 87, y * 10);
ctx.lineWidth = x;
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x * 95, y * 2);
ctx.lineTo(x * 95, y * 10);
ctx.lineWidth = x;
ctx.stroke();
ctx.closePath;
//circle
}
function update() {
ballx -= 0.1;
if (ballx < 0) {
ballx = -radius;
}
}
function main_loop() {
drawcircles();
draw();
update();
}
init();
function initi() {
console.log('init');
// Get a reference to our touch-sensitive element
var touchzone = document.getElementById("myCanvas");
// Add an event handler for the touchstart event
touchzone.addEventListener("mousedown", touchHandler, false);
}
function touchHandler(event) {
// Get a reference to our coordinates div
var can = document.getElementById("myCanvas");
// Write the coordinates of the touch to the div
if (event.pageX < x * 50 && event.pageY > y * 10) {
ballx += 1;
} else if (event.pageX > x * 50 && event.pageY > y * 10) {
ballx -= 1;
}
console.log(event, x, ballx);
draw();
}
initi();
draw();
}
<div id="gameArea">
<canvas id="myCanvas"></canvas>
</div>
Your call to draw() after calling drawcircles() has a ctx.clearRect - this clears the canvas (including the just drawn circles).
Moving drawcircles(); to after draw(); in main_loop will make the circle appear. Note that you have to wait for a bit for the circle to be drawn within the visible area.

Categories

Resources