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>
Related
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();
}
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
// 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();
}
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
// drawing the circle from two pieces
draw(ctx) {
this.drawFill({
ctx
})
this.drawOutline({
ctx
})
}
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
// color change function
setColor({
outline,
fill
}) {
this.color = outline
this.fillColor = fill
}
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
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;
}
}
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
const my_circle = new Circle(100, 100, 50, 3, 'Black');
const updateCircle = function(ctx) {
requestAnimationFrame(() => updateCircle(ctx));
my_circle.update(ctx);
}
updateCircle(context);
document.getElementById("inc").addEventListener("click", increment);
function increment() {
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
}
document.getElementById("dec").addEventListener("click", decrement);
function decrement() {
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
}
document.getElementById("bri").addEventListener("click", briincrement);
function briincrement() {
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
}
document.getElementById("bridec").addEventListener("click", bridecrement);
function bridecrement() {
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
}
<button id="inc">Font +</button>
<button id="dec">Font -</button>
<button id="bri">Font brightness +</button>
<button id="bridec">Font brightness -</button>
<canvas id="canvas"></canvas>
As you can see from your own code, the size of text written onto a canvas is controlled by the .font property.
ctx.font = "20px Arial";
So in order to change the font size we need to alter the 20 inside the string. This can be done by making it a class variable of your circle class:
this.fontSize = 20;
and the drawOutline() method needs a little modification to take use of this variable:
ctx.font = this.fontSize + "px Arial";
Now all you have to do is vary the value of fontSize of a Circle instance using the corresponding buttons:
document.getElementById("inc").addEventListener("click", increment);
function increment() {
my_circle.fontSize++;
}
document.getElementById("dec").addEventListener("click", decrement);
function decrement() {
if (my_circle.fontSize - 1 >= 0) {
my_circle.fontSize--;
}
}
The brightness of the font can be controlled in a similar way. For simplicity let's use the CanvasRenderingContext2D .globalAlpha property, which controls the opacity of drawing operations. Let's give your class another propety:
this.textAlpha = 1.0;
Text is written using the .fillText() method. That means we need to modify the global alpha just before writing text and reset it to 1 afterwards:
ctx.globalAlpha = this.textAlpha;
ctx.fillText(this.text, this.position_x, this.position_y);
ctx.globalAlpha = 1;
After adding a similar logic for the brightness buttons we'll come up with this:
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.fontSize = 20;
this.textAlpha = 1.0;
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.globalAlpha = this.textAlpha;
ctx.fillText(this.text, this.position_x, this.position_y);
ctx.globalAlpha = 1;
ctx.textAlign = "center";
ctx.textBaseline = "middle"
ctx.font = this.fontSize + "px Arial";
ctx.lineWidth = 5;
ctx.arc(this.position_x, this.position_y, this.radius, 0, Math.PI * 2);
ctx.stroke();
ctx.closePath();
}
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
// 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();
}
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
// drawing the circle from two pieces
draw(ctx) {
this.drawFill({
ctx
})
this.drawOutline({
ctx
})
}
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
// color change function
setColor({
outline,
fill
}) {
this.color = outline
this.fillColor = fill
}
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
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;
}
}
//I want to increase and decrease the font size and brightness of number inside the circle. How to do that?
const my_circle = new Circle(100, 100, 50, 3, 'Black');
const updateCircle = function(ctx) {
requestAnimationFrame(() => updateCircle(ctx));
my_circle.update(ctx);
}
updateCircle(context);
document.getElementById("inc").addEventListener("click", increment);
function increment() {
my_circle.fontSize++;
}
document.getElementById("dec").addEventListener("click", decrement);
function decrement() {
if (my_circle.fontSize - 1 >= 0) {
my_circle.fontSize--;
}
}
document.getElementById("bri").addEventListener("click", briincrement);
function briincrement() {
if (my_circle.textAlpha + 0.1 <= 1) {
my_circle.textAlpha += 0.1;
}
}
document.getElementById("bridec").addEventListener("click", bridecrement);
function bridecrement() {
if (my_circle.textAlpha - 0.1 >= 0) {
my_circle.textAlpha -= 0.1;
}
}
<button id="inc">Font +</button>
<button id="dec">Font -</button>
<button id="bri">Font brightness +</button>
<button id="bridec">Font brightness -</button>
<canvas id="canvas"></canvas>
Here is my current HTML file
<!DOCTYPE html>
<html>
<head>
<title>Space Ship</title>
<style type="text/css">
canvas{
border: 1px solid black;
}
body{
margin: 0;
}
</style>
</head>
<body>
<canvas id="game"></canvas>
<script src="game.js"></script>
</body>
</html>
And here is my current JS file which is where I make all the changes to the canvas
(function () {
const canvas = document.getElementById('game');
const context = canvas.getContext('2d');
const SPACESHIP_SIZE = { width: 15, height: 25 };
const SPACESHIP_POSITION = { x: window.innerWidth/2, y: window.innerHeight/2};
const GRAVITY = 0;
//Update thrust constant
const THRUST = 15;
class SpaceShip {
constructor(size, position) {
this.color = 'yellow';
this.size = size;
this.position = position;
this.angle = 0;
this.engineOn = false;
this.rotatingLeft = false;
this.rotatingRight = false;
this.velocity = {
x: 0,
y: 0,
};
}
draw() {
const triangleCenterX = this.position.x + 0.5 * this.size.width;
const triangleCenterY = this.position.y + 0.5 * this.size.height;
context.save();
context.translate(triangleCenterX, triangleCenterY);
context.rotate(this.angle);
context.lineWidth = 5;
context.beginPath();
// Triangle
context.moveTo(0, -this.size.height / 2);
context.lineTo(-this.size.width / 2, this.size.height / 2);
context.lineTo(this.size.width / 2, this.size.height / 2);
context.closePath();
context.strokeStyle = this.color;
context.stroke();
context.fillStyle = "red";
context.fill();
// Flame for engine
if (this.engineOn) {
const fireYPos = this.size.height / 2 + 4;
const fireXPos = this.size.width * 0.25;
context.beginPath();
context.moveTo(-fireXPos, fireYPos);
context.lineTo(fireXPos, fireYPos);
context.lineTo(0, fireYPos + Math.random() * 100);
context.lineTo(-fireXPos, fireYPos);
context.closePath();
context.fillStyle = 'orange';
context.fill();
}
context.restore();
}
moveSpaceShip() {
// Angle has to be in radians
const degToRad = Math.PI / 180;
// Change the position based on velocity
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
// Move spaceship to other side when leaving screen
this.position.x = (canvas.width + this.position.x) % canvas.width;
this.position.y = (canvas.height + this.position.y) % canvas.height;
/*
Adding floating point numbers to the end of the
rotaion handling to make roation faster
*/
if (this.rotatingLeft) this.angle -= (degToRad+.1);
if (this.rotatingRight) this.angle += (degToRad+.1);
// Acceleration
if (this.engineOn) {
this.velocity.x += (THRUST / 100) * Math.sin(this.angle);
this.velocity.y -= (THRUST / 100) * Math.cos(this.angle);
}
// Update the velocity depending on gravity
this.velocity.y += GRAVITY / 2500;
}
}
const spaceShip = new SpaceShip(SPACESHIP_SIZE, SPACESHIP_POSITION);
function handleKeyInput(event) {
const { keyCode, type } = event;
const isKeyDown = type === 'keydown' ? true : false;
if (keyCode === 37) spaceShip.rotatingLeft = isKeyDown;
if (keyCode === 39) spaceShip.rotatingRight = isKeyDown;
if (keyCode === 38) spaceShip.engineOn = isKeyDown;
}
function draw() {
console.log('drawing');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Clear screen
context.fillStyle = 'rgb(0, 10, 60)';
context.fillRect(0, 0, window.innerWidth, canvas.height);
context.font = "30px Arial";
context.fillText("Hello World", window.innerWidth, window.innerHeight);
//Loading small stars
for (var i = 1; i<window.innerWidth; i+=100){
for(var j = 1; j<window.innerHeight; j+=100){
context.beginPath();
context.arc(i, j, 1, 0, Math.PI*2, false);
context.fillStyle = 'white';
context.fill();
context.stroke();
}
}
//loading medium stars
for (var i = 1; i<window.innerWidth; i+=150){
for(var j = 1; j<window.innerHeight; j+=150){
context.beginPath();
context.arc(i, j, 2, 0, Math.PI*2, false);
context.fillStyle = 'white';
context.fill();
context.stroke();
}
}
//loading larger stars
for (var i = 1; i<window.innerWidth; i+=225){
for(var j = 1; j<window.innerHeight; j+=225){
context.beginPath();
context.arc(i, j, 3, 0, Math.PI*2, false);
context.fillStyle = 'white';
context.fill();
context.stroke();
}
}
spaceShip.moveSpaceShip();
// Begin drawing
spaceShip.draw();
// Repeats
requestAnimationFrame(draw);
}
// Event Listeners
document.addEventListener('keydown', handleKeyInput);
document.addEventListener('keyup', handleKeyInput);
// Start the game
draw();
})();
The output works and looks like this...
Little rocket that flies around in space and it works perfectly fine
Now the issue I have is that I want to add elements that represent black holes which spin in a circular motion. When the spaceship which is controlled by the arrow keys hovers over one of these spinning "black hole" like objects, I want to prompt the user to click "enter" in order to go to a new area and space which means they will be redirected to a new canvas (which will just be a different version of the one you see here.
I have no ideas on how to go about adding one of these objects onto the canvas and then give it this function. Does anyone know how to?
Im sure its not as difficult as i'm making it seem, I just don't have that much experience using JavaScript and an HTML5 canvas. Thanks.
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth - 4;
canvas.height = window.innerHeight - 4;
ctx.font = "30px Arial";
ctx.shadowColor = "rgba(255,255,255,.6)";
// Constants in objects doesnt work cause objects passing as reference and will by modified!
// If you want constant constant, use primitives
const SPACESHIP_SIZE = { width: 15, height: 25 };
const SPACESHIP_POSITION = { x: window.innerWidth/2, y: window.innerHeight/2};
const GRAVITY = 0;
const HOVER_TICKS = 80;
//Update thrust constant
const THRUST = 15;
const Systems = {
'main': {
holes:[
{x: 100, y: 350, size: 20, dest: 'J204853'},
{x: 550, y: 50, size: 20, dest: 'J111000'},
{x: 400, y: 150, size: 30, dest: 'J235456'},
{x: 300, y: 100, size: 20, dest: 'Jita'},
{x: 200, y: 400, size: 10, dest: 'Amarr'},
{x: 450, y: 300, size: 20, dest: 'Thera'},
]
},
'J204853': {holes:[{x: 550, y: 50, size: 30, dest: 'main'}]},
'J235456': {holes:[{x: 350, y: 70, size: 20, dest: 'main'}]},
'J111000': {holes:[{x: 150, y: 150, size: 10, dest: 'main'}]},
'Amarr': {holes:[{x: 350, y: 270, size: 30, dest: 'main'}]},
'Thera': {holes:[{x: 250, y: 170, size: 40, dest: 'main'}]},
'Jita': {holes:[{x: 450, y: 250, size: 20, dest: 'main'}]},
};
let spaceShip;
let currentSystem = 'main';
const spaceObjects = [];
class SpaceObject {
constructor(size, position, color = 'black', angle = 0) {
this.color = color;
this.size = size;
this.position = position;
this.angle = angle;
spaceObjects.push(this);
}
tick() {
this.update();
this.draw();
}
update() {}
draw() {}
isAbove({x, y}) {
return Math.abs(this.position.x - x) < this.size && Math.abs(this.position.y - y) < this.size;
}
destroy() {
spaceObjects.splice(spaceObjects.indexOf(this), 1);
}
}
class SpaceShip extends SpaceObject {
constructor(size, position) {
super(size, position, 'yellow');
this.aboveHole = 0;
this.engineOn = false;
this.rotatingLeft = false;
this.rotatingRight = false;
this.velocity = {x: 0, y: 0};
}
draw() {
const triangleCenterX = this.position.x + 0.5 * this.size.width;
const triangleCenterY = this.position.y + 0.5 * this.size.height;
ctx.shadowBlur = 0;
ctx.save();
ctx.translate(triangleCenterX, triangleCenterY);
ctx.rotate(this.angle);
ctx.lineWidth = 5;
ctx.beginPath();
// Triangle
ctx.moveTo(0, -this.size.height / 2);
ctx.lineTo(-this.size.width / 2, this.size.height / 2);
ctx.lineTo(this.size.width / 2, this.size.height / 2);
ctx.closePath();
ctx.strokeStyle = this.color;
ctx.stroke();
ctx.fillStyle = "red";
ctx.fill();
// Flame for engine
if (this.engineOn) {
const fireYPos = this.size.height / 2 + 4;
const fireXPos = this.size.width * 0.25;
ctx.beginPath();
ctx.moveTo(-fireXPos, fireYPos);
ctx.lineTo(fireXPos, fireYPos);
ctx.lineTo(0, fireYPos + Math.random() * 100);
ctx.lineTo(-fireXPos, fireYPos);
ctx.closePath();
ctx.fillStyle = 'orange';
ctx.fill();
}
ctx.restore();
}
update() {
this.moveSpaceShip();
this.checkAboveHole();
}
moveSpaceShip() {
// Angle has to be in radians
const degToRad = Math.PI / 180;
// Change the position based on velocity
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
// Move spaceship to other side when leaving screen
this.position.x = (canvas.width + this.position.x) % canvas.width;
this.position.y = (canvas.height + this.position.y) % canvas.height;
/*
Adding floating point numbers to the end of the
rotaion handling to make roation faster
*/
if (this.rotatingLeft) this.angle -= (degToRad+.1);
if (this.rotatingRight) this.angle += (degToRad+.1);
// Acceleration
if (this.engineOn) {
this.velocity.x += (THRUST / 100) * Math.sin(this.angle);
this.velocity.y -= (THRUST / 100) * Math.cos(this.angle);
}
// Update the velocity depending on gravity
this.velocity.y += GRAVITY / 2500;
}
checkAboveHole() {
const hole = spaceObjects.find(spaceObject => spaceObject !== this && spaceObject.isAbove(this.position));
if(hole) {
this.aboveHole++;
if(this.aboveHole > HOVER_TICKS) {
confirm(`Jump to system ${hole.dest}?`) && jump(hole);
this.aboveHole = 0;
}
} else {
this.aboveHole = 0;
}
}
}
const circle = (ctx, x, y, radius, color = 'white') => {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI*2, false);
ctx.fillStyle = color;
ctx.fill();
ctx.stroke();
ctx.closePath();
};
class BlackHole extends SpaceObject {
constructor(size, position, dest) {
super(size, position);
this.dest = dest;
}
update() {
// Spin?
this.angle+=.01;
}
draw() {
// Shadow
ctx.shadowBlur = this.size >>> 2;
circle(ctx, this.position.x, this.position.y, this.size + 1, `rgba(255, 255, 255, .6)`);
// Hole
circle(ctx, this.position.x, this.position.y, this.size, this.color);
// Spinning view
circle(ctx, this.position.x + (this.size * Math.sin(this.angle) - 1), this.position.y + (this.size * Math.cos(this.angle) - 1), 2, 'gray');
circle(ctx, this.position.x - (this.size * Math.sin(this.angle) - 1), this.position.y - (this.size * Math.cos(this.angle) - 1), 2, 'gray');
}
}
function handleKeyInput(event) {
const { keyCode, type } = event;
const isKeyDown = type === 'keydown' ? true : false;
if (keyCode === 37) spaceShip.rotatingLeft = isKeyDown;
if (keyCode === 39) spaceShip.rotatingRight = isKeyDown;
if (keyCode === 38) spaceShip.engineOn = isKeyDown;
}
function jump({dest}) {
currentSystem = dest || 'main';
while(spaceObjects.length) spaceObjects[0].destroy();
Systems[currentSystem].holes.forEach(hole => new BlackHole(hole.size, {x: hole.x, y: hole.y}, hole.dest));
spaceShip = new SpaceShip(SPACESHIP_SIZE, SPACESHIP_POSITION);
}
function draw() {
// Clear screen
ctx.fillStyle = 'rgb(0, 10, 60)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'rgb(150, 150, 150)';
ctx.fillText(`You are in system ${currentSystem}`, 40, 40);
//Loading small stars
ctx.shadowBlur = 1;
for (var i = 1, j = 1; j<canvas.height; i+=100, i > canvas.width && (i=1, j+=100), circle(ctx, i, j, 1));
//loading medium stars
ctx.shadowBlur = 2;
for (var i = 1, j = 1; j<canvas.height; i+=150, i > canvas.width && (i=1, j+=150), circle(ctx, i, j, 2));
//loading larger stars
ctx.shadowBlur = 3;
for (var i = 1, j = 1; j<canvas.height; i+=225, i > canvas.width && (i=1, j+=225), circle(ctx, i, j, 3));
// tick all objects
spaceObjects.forEach(spaceObject => spaceObject.tick());
// Repeats
requestAnimationFrame(draw);
}
// Event Listeners
document.addEventListener('keydown', handleKeyInput);
document.addEventListener('keyup', handleKeyInput);
// Start the game
jump({dest: 'main'});
draw();
<!DOCTYPE html>
<html>
<head>
<title>Space Ship</title>
<style type="text/css">
canvas{
border: 1px solid black;
}
body{
margin: 0;
}
</style>
</head>
<body>
<canvas id="game"></canvas>
</body>
</html>
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">
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(); }
I have resizable rectangle, and I wish to have right-aligned text (day numbers) next to it.
what I have now:
(also when resizing the text does not really align vertically)
what I wish to have:
Is there a way to fill the text and align it inside a drawn rectangle? Other suggestions are welcome too.
js.do code
function dayRect(day) {
const days = ["I","II","III","IV","V","VI","VII"];
context.beginPath();
//maybe align the text inside this rect somehow
context.rect(0, day*h/7, 3*w/27, h/7);
context.stroke();
context.font = "0.5rem Arial";
context.fillStyle = "#fff";
context.fillText(days[day], 0, (day+1)*h/7);
}
I've changed a few things in your code since I wasn't able to see anything. You need to use context.textAlign="right" for your text and move it to a different position. I hope it helps.
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
var canvas = document.getElementById("posHourCanvas");
var context = canvas.getContext('2d');
canvas.width=600,canvas.height=300;
var boxes = [];
function init() {
context.clearRect(0, 0, canvas.width, canvas.height);
boxes.length = 0;
const strokeWidth = 0.6;
//canvas.width = $('#two')[0].clientWidth;
var cellSize = canvas.width/27;
canvas.height = 7/27 * canvas.width;
var x = y = 0;
draw(x,y,canvas.width,canvas.height,cellSize,strokeWidth);
}
function Box(x, y, day, hour) {
this.x = x;
this.y = y;
this.day = day;
this.hour = hour;
}
function draw(x, y, w, h, cellSize, strokeWidth) {
let onePixel = cellSize * strokeWidth;
cellSize = cellSize * (1 - strokeWidth);
context.beginPath();
context.lineWidth = 1;
context.strokeStyle = 'rgba(0, 0, 0, 1)';
const rectCoordinates = {
x: x+3*w/27,
y: y,
w: w-3*w/27,
h: h
}
context.rect(rectCoordinates.x, y, rectCoordinates.w, h);
context.fillStyle = 'white';
context.fill();
context.stroke();
let offX = rectCoordinates.w/24 + rectCoordinates.x;
let offY = h/7;
for (let i = 0; i < 7; i++) {
dayRect(i);
context.beginPath();
context.moveTo(0, offY);
context.lineTo(w, offY);
context.strokeStyle = "black";
context.stroke();
offY+=h/7;
}
for (let i = 0; i < 24; i++) {
context.beginPath();
context.moveTo(offX, 0);
context.lineTo(offX, h);
context.stroke();
offX+=rectCoordinates.w/24;
}
function dayRect(day) {
const days = ["I","II","III","IV","V","VI","VII"];
context.beginPath();
context.rect(0, day*h/7, 3*w/27, h/7);
context.stroke();
context.font = "0.5rem Arial";
context.fillStyle = "#fff";
context.textAlign="right";
context.fillText(days[day], 60, (day+1)*h/7);
}
}
init();
body {
margin: auto;
color: white;
background-color: black;
min-height: 100vh;
}
<div id="parent">
<div>text above</div>
<div id="two">
<canvas id="posHourCanvas" width="600" height="300"></canvas>
</div>
<div>text under</div>
</div>