Related
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 have the rectangle pointing at the mouse. What I want: when I lift the mouse and click and drag that the rectangle rotates further.
Or that I can click on any corner to rotate the rectangle. Just like you would with your finger and a sheet of paper.
let angle = 0;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
push();
translate(150, 150);
rotate(angle);
stroke(0);
strokeWeight(2);
rect(-100, -75, 200, 150);
stroke(255, 0, 0);
strokeWeight(5);
line(-100, -75, 100, -75);
stroke(0, 255, 0);
point(0, 0);
pop();
}
function mouseDragged() {
m_angle = atan2(mouseY - 150, mouseX - 150);
angle = /* MAGIC FORMULA HERE */ m_angle;
}
https://editor.p5js.org/jwglazebrook/sketches/p2pnhPSZE
The Problem:
The issue with your code is that you need to store the offset from the initial mouse click to the new dragged point.
The Solution:
To fix the jerky behavior we just have to store the previous mouse angle and box angle and compare the difference with the dragged mouse angle.
The Code:
let angle = 0;
function setup() {
angleMode(DEGREES);
createCanvas(400, 400);
}
function draw() {
background(220);
push();
translate(150, 150);
rotate(angle);
stroke(0);
strokeWeight(2);
rect(-100, -75, 200, 150);
stroke(255, 0, 0);
strokeWeight(5);
line(-100, -75, 100, -75);
stroke(0, 255, 0);
point(0, 0);
pop();
}
let c_angle = 0;
let q_angle = 0;
function mousePressed() {
c_angle = atan2(mouseY - 150, mouseX - 150); //The initial mouse rotation
q_angle = angle; //Initial box rotation
}
function mouseDragged() {
m_angle = atan2(mouseY - 150, mouseX - 150);
let dangle = m_angle - c_angle; //How much the box needs to be rotated
if (dangle>=360) dangle-=360; //clamping
if (dangle<0) dangle+=360; //clamping
angle = q_angle + dangle; //Apply the rotation
if (angle>=360) angle -= 360; //clamping
}
I have a small issue on canvas, when mouse is over element (object) it should change cursor to pointer, when leaves - back to default, but my code doesn't work that way, I've ran out of ideas.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var rectList = [];
var cursors = ['default', 'pointer'],
currentCursor = 0;
function createRectangle( id, x, y, width, height, fillColor ) {
var newRectangle = {
x,
y,
id,
width,
height,
fillColor,
mouseX: null,
mouseY: null,
isHighlighted: false,
isClicked: false,
cursor: 0, // 0 default, 1 pointer
draw( ) {
drawRect( this.x, this.y, this.width, this.height, this.fillColor )
},
highlight( ) {
crosshair( this.x, this.y, this.width, this.height, 20, 25, 6, 1, 2, 2, 2, 2, 2, '#E15258', '#E15258', '#C25975' );
},
isPointInside( ) {
return (this.mouseX >= this.x && this.mouseX <= this.x + this.width && this.mouseY >= this.y && this.mouseY <= this.y + this.height);
}
}
rectList.push( newRectangle );
}
function crosshair( x, y, width, height, radius1, radius2, endLineWidth, circle1Width, circle2Width, topLineWidth, rightLineWidth, bottomLineWidth, leftLineWidth, circle1Color, circle2Color, linesColor) {
drawCircle(x + width/2, y + height/2, radius1, circle1Width, circle1Color);
drawCircle(x + width/2, y + height/2, radius2, circle2Width, circle2Color);
drawLine(x + radius1 + width/2, y + height/2, x + (radius2 + endLineWidth) + width/2, y + height/2, linesColor, leftLineWidth);
drawLine(x - radius1 + width/2, y + height/2, x - (radius2 + endLineWidth) + width/2, y + height/2, linesColor, rightLineWidth);
drawLine(x + width/2, y + radius1 + height/2, x + width/2, y + (radius2 + endLineWidth) + height/2, linesColor, bottomLineWidth);
drawLine(x + width/2, y - radius1 + height/2, x + width/2, y - (radius2 + endLineWidth) + height/2, linesColor, topLineWidth);
}
function drawLine(startX, startY, endX, endY, color, width) {
ctx.save();
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.beginPath();
ctx.moveTo(startX,startY);
ctx.lineTo(endX,endY);
ctx.stroke();
ctx.restore();
}
function drawCircle( x, y, radius, lineWidth, strokeColor ) {
ctx.save();
ctx.beginPath();
ctx.arc( x, y, radius, 0, 2 * Math.PI, false);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = strokeColor;
ctx.stroke();
ctx.restore();
}
function drawBorder( x, y, width, height, lineWidth, strokeColor ) {
ctx.save();
ctx.lineWidth = lineWidth;
ctx.strokeStyle = strokeColor;
ctx.strokeRect( x, y, width, height);
ctx.restore();
}
function drawRect( x, y, width, height, fillColor ) {
ctx.save();
ctx.fillStyle = fillColor;
ctx.fillRect( x, y, width, height );
ctx.restore();
}
document.onmousemove = function( mouse ) {
var mouseX = parseInt(mouse.clientX - offsetX);
var mouseY = parseInt(mouse.clientY - offsetY);
rectList.forEach( rect => {
rect.mouseX = mouseX;
rect.mouseY = mouseY;
if(rect.isPointInside()) {
currentCursor = 1;
if(rect.isClicked) {
rect.isHighlighted = false;
} else {
rect.isHighlighted = true;
}
} else {
rect.isHighlighted = false;
currentCursor = 0;
}
});
canvas.style.cursor = cursors[currentCursor];
}
document.onclick = function( mouse ) {
var mouseX = parseInt(mouse.clientX - offsetX);
var mouseY = parseInt(mouse.clientY - offsetY);
rectList.forEach( rect => {
rect.mouseX = mouseX;
rect.mouseY = mouseY;
if(rect.isPointInside()) {
if(rect.isHighlighted) {
rect.isHighlighted = false;
rect.isClicked = true;
} else {
rect.isClicked = false;
}
} else {
rect.isClicked = false;
}
});
}
function update() {
ctx.clearRect( 0, 0, canvas.width, canvas.height);
rectList.forEach( rect => {
if( rect.isHighlighted ) {
rect.draw();
rect.highlight();
} else {
rect.draw();
}
if( rect.isClicked ) {
rect.draw();
rect.highlight();
} else {
rect.draw();
}
});
requestAnimationFrame(update);
}
function startNewGame() {
createRectangle( 'orange', 25, 25, 30/2, 30/2, 'orange' );
createRectangle( 'green', 50, 50, 30/2, 30/2, 'green' );
createRectangle( 'blue', 75, 75, 30/2, 30/2, 'blue' );
createRectangle( 'yellow', 100, 100, 30/2, 30/2, 'yellow' );
createRectangle( 'lightgreen', 125, 125, 30/2, 30/2, 'lightgreen' );
requestAnimationFrame(update);
}
startNewGame();
canvas {
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<canvas id="canvas" width="400" height="200"></canvas>
I hope this is a small issue and won't cause you a headache. Thanks in advance!
When the mouse is over any other then the last rectangle you set currentCursor directly back to 0 in the next iteration of the ForEach in the onmousemove function.
I fixed it by setting currentCursor to 0 before the loop.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var rectList = [];
var cursors = ['default', 'pointer'];
function createRectangle( id, x, y, width, height, fillColor ) {
var newRectangle = {
x,
y,
id,
width,
height,
fillColor,
mouseX: null,
mouseY: null,
isHighlighted: false,
isClicked: false,
cursor: 0, // 0 default, 1 pointer
draw( ) {
drawRect( this.x, this.y, this.width, this.height, this.fillColor )
},
highlight( ) {
crosshair( this.x, this.y, this.width, this.height, 20, 25, 6, 1, 2, 2, 2, 2, 2, '#E15258', '#E15258', '#C25975' );
},
isPointInside( ) {
return (this.mouseX >= this.x && this.mouseX <= this.x + this.width && this.mouseY >= this.y && this.mouseY <= this.y + this.height);
}
}
rectList.push( newRectangle );
}
function crosshair( x, y, width, height, radius1, radius2, endLineWidth, circle1Width, circle2Width, topLineWidth, rightLineWidth, bottomLineWidth, leftLineWidth, circle1Color, circle2Color, linesColor) {
drawCircle(x + width/2, y + height/2, radius1, circle1Width, circle1Color);
drawCircle(x + width/2, y + height/2, radius2, circle2Width, circle2Color);
drawLine(x + radius1 + width/2, y + height/2, x + (radius2 + endLineWidth) + width/2, y + height/2, linesColor, leftLineWidth);
drawLine(x - radius1 + width/2, y + height/2, x - (radius2 + endLineWidth) + width/2, y + height/2, linesColor, rightLineWidth);
drawLine(x + width/2, y + radius1 + height/2, x + width/2, y + (radius2 + endLineWidth) + height/2, linesColor, bottomLineWidth);
drawLine(x + width/2, y - radius1 + height/2, x + width/2, y - (radius2 + endLineWidth) + height/2, linesColor, topLineWidth);
}
function drawLine(startX, startY, endX, endY, color, width) {
ctx.save();
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.beginPath();
ctx.moveTo(startX,startY);
ctx.lineTo(endX,endY);
ctx.stroke();
ctx.restore();
}
function drawCircle( x, y, radius, lineWidth, strokeColor ) {
ctx.save();
ctx.beginPath();
ctx.arc( x, y, radius, 0, 2 * Math.PI, false);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = strokeColor;
ctx.stroke();
ctx.restore();
}
function drawBorder( x, y, width, height, lineWidth, strokeColor ) {
ctx.save();
ctx.lineWidth = lineWidth;
ctx.strokeStyle = strokeColor;
ctx.strokeRect( x, y, width, height);
ctx.restore();
}
function drawRect( x, y, width, height, fillColor ) {
ctx.save();
ctx.fillStyle = fillColor;
ctx.fillRect( x, y, width, height );
ctx.restore();
}
document.onmousemove = function( mouse ) {
var mouseX = parseInt(mouse.clientX - offsetX);
var mouseY = parseInt(mouse.clientY - offsetY);
var currentCursor = 0;
rectList.forEach(rect => {
rect.mouseX = mouseX;
rect.mouseY = mouseY;
if(rect.isPointInside()) {
currentCursor = 1;
if(rect.isClicked) {
rect.isHighlighted = false;
} else {
rect.isHighlighted = true;
}
} else {
rect.isHighlighted = false;
}
});
canvas.style.cursor = cursors[currentCursor];
}
document.onclick = function( mouse ) {
var mouseX = parseInt(mouse.clientX - offsetX);
var mouseY = parseInt(mouse.clientY - offsetY);
rectList.forEach( rect => {
rect.mouseX = mouseX;
rect.mouseY = mouseY;
if(rect.isPointInside()) {
if(rect.isHighlighted) {
rect.isHighlighted = false;
rect.isClicked = true;
} else {
rect.isClicked = false;
}
} else {
rect.isClicked = false;
}
});
}
function update() {
ctx.clearRect( 0, 0, canvas.width, canvas.height);
rectList.forEach( rect => {
if( rect.isHighlighted ) {
rect.draw();
rect.highlight();
} else {
rect.draw();
}
if( rect.isClicked ) {
rect.draw();
rect.highlight();
} else {
rect.draw();
}
});
requestAnimationFrame(update);
}
function startNewGame() {
createRectangle( 'orange', 25, 25, 30/2, 30/2, 'orange' );
createRectangle( 'green', 50, 50, 30/2, 30/2, 'green' );
createRectangle( 'blue', 75, 75, 30/2, 30/2, 'blue' );
createRectangle( 'yellow', 100, 100, 30/2, 30/2, 'yellow' );
createRectangle( 'lightgreen', 125, 125, 30/2, 30/2, 'lightgreen' );
requestAnimationFrame(update);
}
startNewGame();
canvas {
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<canvas id="canvas" width="400" height="200"></canvas>
[I am making lines over a circle, but i am unable to change my line color to black. Its continuously showing me white lines.
One more thing, i want my line to half dotted and half normal like the image i have attached.
var canvas = document.getElementById("canvas");
var e = canvas.getContext("2d");
function circle(e, color, x, y, radius, startAngle, endAngle, clockwise) {
if (arguments.length < 9) return alert("Not enough arguments.\nThe function \"circle\" requires 9 arguments\nYou provided only " + arguments.length + ".");
e.beginPath();
e.arc(x, y, radius, startAngle, endAngle, clockwise);
e.strokeStyle = color;
e.stroke();
}
function draw(e, radius) {
var deg360 = Math.PI * 2;
circle(e, "#00688B", 225, 225, 165, deg360, 0, deg360, true);
e.fillStyle = '#00688B';
e.fill();
circle(e, "#0099CC", 225, 225, 140, deg360, 0, deg360, true);
e.fillStyle = '#0099CC';
e.fill();
circle(e, "#33A1DE", 225, 225, 115, deg360, 0, deg360, true);
e.fillStyle = '#33A1DE';
e.fill();
circle(e, "#7EC0EE", 225, 225, 90, deg360, 0, deg360, true);
e.fillStyle = '#7EC0EE';
e.fill();
circle(e, "#98CCE6", 225, 225, 65, deg360, 0, deg360, true);
e.fillStyle = '#98CCE6';
e.fill();
e.closePath();
{
e.closePath();
e.stroke();
e.strokestyle = "Black";
e.beginPath();
e.linewidth = "17";
e.moveTo(225, 225);
e.lineTo(320, 175);
e.strokestyle = "Black";
e.stroke();
e.beginPath();
e.setLineDash([2]);
e.lineto(111, 322)
e.stroke();
circle(e, "#E6E8FA", 225, 225, 45, deg360, 0, deg360, true);
e.fillStyle = '#E6E8FA';
e.fill();
e.fill();
e.fillStyle = "black"; // font color to write the text with
e.font = radius * 0.18 + "px arial";
e.textBaseline = "middle";
e.textAlign = "center";
e.fillText(0, radius, e);
for (num = 0; num < 25; num++) {
ang = num * Math.PI / 12;
e.translate(225, 225);
e.rotate(ang);
e.translate(0, -radius);
e.rotate(-ang);
e.fillText(num.toString(), 0, 0);
e.rotate(ang);
e.translate(0, +radius);
e.rotate(-ang);
e.setTransform(1, 0, 0, 1, 0, 0);
}
}
for stroke color.you are using e.strokestyle but it should be e.strokeStyle .
var canvas = document.getElementById("canvas");
var e = canvas.getContext("2d");
draw(e, 50);
function circle(e, color, x, y, radius, startAngle, endAngle, clockwise) {
if (arguments.length < 9) return alert("Not enough arguments.\nThe function \"circle\" requires 9 arguments\nYou provided only " + arguments.length + ".");
e.beginPath();
e.arc(x, y, radius, startAngle, endAngle, clockwise);
e.strokeStyle = color;
e.stroke();
}
function draw(e, radius) {
var deg360 = Math.PI * 2;
circle(e, "#00688B", 225, 225, 165, deg360, 0, deg360, true);
e.fillStyle = '#00688B';
e.fill();
circle(e, "#0099CC", 225, 225, 140, deg360, 0, deg360, true);
e.fillStyle = '#0099CC';
e.fill();
circle(e, "#33A1DE", 225, 225, 115, deg360, 0, deg360, true);
e.fillStyle = '#33A1DE';
e.fill();
circle(e, "#7EC0EE", 225, 225, 90, deg360, 0, deg360, true);
e.fillStyle = '#7EC0EE';
e.fill();
circle(e, "#98CCE6", 225, 225, 65, deg360, 0, deg360, true);
e.fillStyle = '#98CCE6';
e.fill();
e.closePath(); {
e.beginPath();
e.strokeStyle = "black";
e.linewidth = "17";
e.moveTo(225, 225);
e.lineTo(320, 175);
e.strokeSstyle = "black";
e.stroke();
e.beginPath();
e.setLineDash([2]);
e.lineto(111, 322);
e.stroke();
circle(e, "#E6E8FA", 225, 225, 45, deg360, 0, deg360, true);
e.fillStyle = '#E6E8FA';
e.fill();
e.fill();
e.fillStyle = "black"; // font color to write the text with
e.font = radius * 0.18 + "px arial";
e.textBaseline = "middle";
e.textAlign = "center";
e.fillText(0, radius, e);
for (num = 0; num < 25; num++) {
ang = num * Math.PI / 12;
e.translate(225, 225);
e.rotate(ang);
e.translate(0, -radius);
e.rotate(-ang);
e.fillText(num.toString(), 0, 0);
e.rotate(ang);
e.translate(0, +radius);
e.rotate(-ang);
e.setTransform(1, 0, 0, 1, 0, 0);
}
}
}
<canvas id="canvas" width="400" height="500" class="playable-canvas"></canvas>
for half dotted line, you have find the midpoint of the line and draw one half with normal stroke and another half by setting setLineDash.
see the example
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
halfDotLine(0, 0, 100, 100, ctx);
function halfDotLine(x1, y1, x2, y2, ctx) {
ctx.lineWidth = 3;
ctx.strokeStyle = "#FF0000";
ctx.beginPath();
// calculate the midpoint of the line and draw half line with normal stroke from midpoint to end
ctx.moveTo((x1 + x2) / 2, (y1 + y2) / 2);
ctx.lineTo(x2, y2);
ctx.stroke();
// for dotted line draw the line by setting linedash array from start to midpoint.
ctx.setLineDash([3, 3]);
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo((x1 + x2) / 2, (y1 + y2) / 2);
ctx.stroke();
}
<canvas id="canvas" width="400" height="200" class="playable-canvas"></canvas>
strokeStyle is case sensitive !
When you write e.strokestyle = "Black";, Javascript does not complain. But you get nothing. Just change to e.strokeStyle = "Black";.