How to translate and make canvas responsive? - javascript

I am trying to move to translate the canvas to (100,100) but it is not moving.
And the canvas is not responsive, when I try to change the size of canvas using CSS the circles are shrinking.
How can I add a button to toggle the drawing on canvas by the circle (i.e.: when button pressed don't draw then the circle should not draw on canvas, when pressed draw it should draw)
requestAnimationFrame(animate);
var ctx = canvas1.getContext('2d');
ctx.translate(100,100);
canvas1.width = innerWidth;
canvas1.height = innerHeight;
const bgCan = copyCanvas(canvas1);
const redSize = 6, blueSize = 5; // circle sizes on pixels
const drawSpeed = 1; // when button down draw speed in pixels per frame
var X = 50, Y = 50;
var angle = 0;
var mouseButtonDown = false;
document.addEventListener('mousedown', () => mouseButtonDown = true);
document.addEventListener('mouseup', () => mouseButtonDown = false);
function copyCanvas(canvas) {
const can = Object.assign(document.createElement("canvas"), {
width: canvas.width, height: canvas.height
});
can.ctx = can.getContext("2d");
return can;
}
function circle(ctx){
ctx.fillStyle = 'black';
ctx.beginPath();
ctx.arc(X, Y, redSize, 0, Math.PI*2);
ctx.fill();
}
function direction(ctx){
const d = blueSize + redSize + 3;
ctx.fillStyle = 'blue';
ctx.beginPath();
ctx.arc(d * Math.sin(angle) + X, d * Math.cos(angle) + Y, blueSize, 0, Math.PI*2);
ctx.fill();
}
function animate(){
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(bgCan, 0, 0);
if (mouseButtonDown) {
circle(bgCan.ctx);
X += Math.sin(angle) * drawSpeed;
Y += Math.cos(angle) * drawSpeed;
} else {
angle += 0.1;
circle(ctx);
}
direction(ctx);
requestAnimationFrame(animate);
}
#canvas1{
position: absolute;
top:0;
left: 0;
width: 100%;
height: 100%;
border-width: 1px;
border-style: solid;
border-color: Black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas basics</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="canvas1"></canvas>
<input onclick="change()" type="button" value="Write" id="mybutton1"></input>
<script src="script.js"></script>
</body>
</html>

the translate(100, 100) gets reset by new width/height of the canvas. It just needs to be executed after width/height is set
The easiest way is to have a window resize listener and update canvas style width/height
I'm not sure why, but for some reason canvas has a higher z-index therefor button's onclick() never fired
In the code below I've added boundaries restriction, it's affected by translate(100, 100).
requestAnimationFrame(animate);
var ctx = canvas1.getContext('2d');
canvas1.width = innerWidth;
canvas1.height = innerHeight;
ctx.translate(100, 100);
const bgCan = copyCanvas(canvas1);
const redSize = 6,
blueSize = 5; // circle sizes on pixels
const drawSpeed = 1; // when button down draw speed in pixels per frame
const drawButton = document.getElementById("mybutton1");
var draw = true;
var X = 50,
Y = 50;
var angle = 0;
var mouseButtonDown = false;
document.addEventListener('mousedown', onMouseEvent);
document.addEventListener('mouseup', onMouseEvent);
function copyCanvas(canvas) {
const can = Object.assign(document.createElement("canvas"), {
width: canvas.width,
height: canvas.height
});
can.ctx = can.getContext("2d");
return can;
}
function circle(ctx, mousedown) {
if (mousedown && !draw)
return;
ctx.fillStyle = 'black';
ctx.beginPath();
ctx.arc(X, Y, redSize, 0, Math.PI * 2);
ctx.fill();
}
function direction(ctx) {
const d = blueSize + redSize + 3;
ctx.fillStyle = draw ? 'blue' : 'red';
ctx.beginPath();
ctx.arc(d * Math.sin(angle) + X, d * Math.cos(angle) + Y, blueSize, 0, Math.PI * 2);
ctx.fill();
}
function animate() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(bgCan, 0, 0);
if (mouseButtonDown) {
circle(bgCan.ctx, mouseButtonDown);
const x = X + Math.sin(angle) * drawSpeed,
y = Y + Math.cos(angle) * drawSpeed;
if (x > (blueSize + redSize) * 2 && x < canvas1.width - (blueSize + redSize) * 2 &&
y > (blueSize + redSize) * 2 && y < canvas1.height - (blueSize + redSize) * 2)
{
X = x;
Y = y;
}
} else {
angle += 0.1;
circle(ctx);
}
direction(ctx);
requestAnimationFrame(animate);
}
function onMouseEvent(e) {
if (e.target === drawButton) {
if (e.type == "mouseup")
{
draw = !draw;
document.getElementById("mybutton1").value = draw ? "Write" : "Move";
}
return;
}
mouseButtonDown = e.type == "mousedown";
}
window.addEventListener("resize", handleResize)
function handleResize ()
{
const ratio = canvas1.width / canvas1.height;
let h = window.innerHeight,
w = h * ratio;
if (w > window.innerWidth) {
w = window.innerWidth;
h = w / ratio;
}
canvas1.style.width = w + 'px';
canvas1.style.height = h + 'px';
};
handleResize(); // First draw
#canvas1 {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-width: 1px;
border-style: solid;
border-color: Black;
z-index: -1; /* let other elements receive events */
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas basics</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="canvas1" scaleMode='fill'></canvas>
<input type="button" value="Write" id="mybutton1" />
<script src="script.js"></script>
</body>
</html>

Related

Why does my mousefollow method not work on different browsers

Here is a link to the code pen
https://codepen.io/shahman28/pen/mdXraRE
This is a part of a larger project that I am working on. I am attempting to place circles when the mouse is clicked. As you can see in the codepen above the mouse follows well and places the circles at the correct locations, but when I try to do it in browser the cursor has an offset from the mouse and the circles are placed incorrectly. In firefox it is completely arbitrary, but in chrome it places them in the location of the cursor(which is in the incorrect location). I am recycling some code from previous projects so that is why there is the border in the html and css.
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
points = [];
class Mouse {
constructor(c) {
this.x = 0;
this.y = 0;
this.easing = 0.05;
let rect = canvas.getBoundingClientRect();
canvas.onmousemove = e => {
this.x = e.clientX - rect.left;
this.y = e.clientY - rect.top;
}
}
}
class Point {
constructor(x, y, color) {
this.x = x;
this.y = y;
this.color = color;
}
draw() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, 5, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
}
}
function random_hex_color_code() {
let n = (Math.random() * 0xfffff * 1000000).toString(16);
return '#' + n.slice(0, 6);
};
canvas.addEventListener('click', function(e) {
let rect = canvas.getBoundingClientRect();
x = e.clientX - rect.left
y = e.clientY - rect.top;
point = new Point(x, y, '#FF0000');
points.push(point);
})
w = canvas.width = window.innerWidth,
h = canvas.height = window.innerHeight,
mousePosition = new Mouse(canvas);
function animate() {
ctx.fillStyle = '#4A7DB9';
ctx.beginPath();
ctx.arc(mousePosition.x, mousePosition.y, 5, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
}
function handlePoints() {
for (let i = 0; i < points.length; i++) {
points[i].draw();
}
}
function render() {
ctx.clearRect(0, 0, w, h);
handlePoints();
animate();
window.requestAnimationFrame(render);
}
render();
body {
background: black;
}
#canvas1 {
border: 1px solid black;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 900px;
height: 600px;
background: white;
}
<!DOCTYPE html>
<html lang="en">
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]> <html class="no-js"> <!--<![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device.width, initial-scale=1.0">
<title>Tower Defense</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<button onClick="start()">Start Combat</button>
<canvas id="canvas1"></canvas>
<script src="script.js"></script>
</body>
</html>
Does anyone know how to make it so that the the cursor and placed arcs are consistent?
The problem is that at one point the canvas is set to have fixed px dimensions and at another point it is set to have the dimensions of the viewport.
This snippet removes the settings in the stylesheet and just uses viewport dimensions. It seems to work fine (tested on Windows10 Edge/Chrome and Firefox).
You need to decide which setting you want and to stick with that rather than try to use both which leads to the inconsistency.
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
points = [];
class Mouse {
constructor(c) {
this.x = 0;
this.y = 0;
this.easing = 0.05;
let rect = canvas.getBoundingClientRect();
canvas.onmousemove = e => {
this.x = e.clientX - rect.left;
this.y = e.clientY - rect.top;
}
}
}
class Point {
constructor(x, y, color) {
this.x = x;
this.y = y;
this.color = color;
}
draw() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, 5, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
}
}
function random_hex_color_code() {
let n = (Math.random() * 0xfffff * 1000000).toString(16);
return '#' + n.slice(0, 6);
};
canvas.addEventListener('click', function(e) {
let rect = canvas.getBoundingClientRect();
x = e.clientX - rect.left
y = e.clientY - rect.top;
point = new Point(x, y, '#FF0000');
points.push(point);
})
w = canvas.width = window.innerWidth,
h = canvas.height = window.innerHeight,
mousePosition = new Mouse(canvas);
function animate() {
ctx.fillStyle = '#4A7DB9';
ctx.beginPath();
ctx.arc(mousePosition.x, mousePosition.y, 5, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
}
function handlePoints() {
for (let i = 0; i < points.length; i++) {
points[i].draw();
}
}
function render() {
ctx.clearRect(0, 0, w, h);
handlePoints();
animate();
window.requestAnimationFrame(render);
}
render();
body {
background: black;
}
#canvas1 {
border: 1px solid black;
position: absolute;
left 0;
top: 0;
/* removed
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 900px;
height: 600px;
*/
background: white;
}
<meta name="viewport" content="width=device.width, initial-scale=1.0">
<!--<button onClick = "start()">Start Combat</button>-->
<canvas id="canvas1"></canvas>

How to make a line follow mouse event arctanget with class javascript

Hi every one I'm trying to make a line follow the mouse move event. I can do this with the ctx.save and restore but i don't know how to do if i want use class and draw other object. In fact whit using save and restore It Work but if i want to have the same result whit class i dont know how to do many thanks
window.onload = function() {
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
width = canvas.width = window.innerWidth,
height = canvas.height = window.innerHeight,
arrowX = width / 2,
arrowY = height / 2,
dx, dy,
angle = 0,
a = 0;
render();
function render() {
arrowX = width / 2 + Math.cos(a) * height * .4;
arrowY = height / 2 + Math.sin(a) * height * .4;
context.clearRect(0, 0, width, height);
context.save();
context.translate(arrowX, arrowY);
context.rotate(angle);
context.beginPath();
context.moveTo(20, 0);
context.lineTo(-20, 0);
context.moveTo(20, 0);
context.lineTo(10, -10);
context.moveTo(20, 0);
context.lineTo(10, 10);
context.stroke();
context.restore();
requestAnimationFrame(render);
}
document.body.addEventListener("mousemove", function(event) {
dx = event.clientX - arrowX;
dy = event.clientY - arrowY;
angle = Math.atan2(dy, dx);
});
};
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body style="height: 100vh;">
<Canvas id="canvas"></Canvas>
<script src="main.js"></script>
</body>
</html>
If i want use class i start like thaïs on the following code
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var width = canvas.width = window.innerWidth;
var height = canvas.height = window.innerHeight;
var arrowX = width / 2;
var arrowY = height -20;
var dx;
var dy;
var angle = 0;
class Player{
constructor(x,y,radius,color)
{
this.x=x;
this.y=y;
this.radius=radius;
this.color=color;
}
draw(){
c.beginPath();
c.arc(this.x,this.y,this.radius, 0, Math.PI *2,false );
c.fillStyle=this.color;
c.fill();
}
}
class Shooter{
constructor(x,y,xEnd,yEnd,color){
this.x=x;
this.y=y;
this.xEnd=xEnd;
this.yEnd=yEnd;
this.color=color;
}
draw(){
c.beginPath();
c.moveTo(this.x, this.y);
c.lineTo(this.xEnd, this.yEnd);
c.strokeStyle=this.color;
c.stroke();
}
}
// const player= new Player(arrowX,arrowY,20,'white');
const shooter= new Shooter(arrowX,500,arrowX,arrowY,'white');
let animationId;
function animate(){
animationId=requestAnimationFrame(animate)
c.fillStyle='rgba(0, 0, 0, 0.5)';
c.fillRect(0,0,canvas.width,canvas.height);
//player.draw();
shooter.draw();
}
requestAnimationFrame(animate);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body style="height: 100vh;">
<Canvas id="canvas"></Canvas>
<script src="main.js"></script>
</body>
</html>
I can offer two methods for this. The first is to simply have the end of the vector the same coordinates as the mouse position. This will change the magnitude of the vector of course.
This method does not rotate or translate the context.
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var width = (canvas.width = window.innerWidth);
var height = (canvas.height = window.innerHeight);
let canvasBounds = canvas.getBoundingClientRect()
let mouse = {x: 0, y: 0}
class Shooter {
constructor(x, y, color) {
this.x = x;
this.y = y;
this.xEnd = mouse.x;
this.yEnd = mouse.y;
this.color = color;
}
draw() {
c.beginPath();
c.moveTo(this.x, this.y);
c.lineTo(this.xEnd, this.yEnd);
c.strokeStyle = this.color;
c.stroke();
}
update() {
this.xEnd = mouse.x;
this.yEnd = mouse.y;
}
}
const shooter = new Shooter(width/2, height/2, "white");
canvas.addEventListener("mousemove", e => {
mouse.x = e.x - canvasBounds.x;
mouse.y = e.y - canvasBounds.y;
});
function animate() {
animationId = requestAnimationFrame(animate);
c.fillStyle = "rgba(0, 0, 0, 0.5)";
c.fillRect(0, 0, canvas.width, canvas.height);
//player.draw();
shooter.draw();
shooter.update();
}
requestAnimationFrame(animate);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body style="height: 100vh;">
<Canvas id="canvas"></Canvas>
<script src="main.js"></script>
</body>
</html>
The second method draws the start point at (0, 0) but then you can use translate to position it where ever you want. This also rotates the context but allows you to keeps the magnitude the same.
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var width = (canvas.width = window.innerWidth);
var height = (canvas.height = window.innerHeight);
let canvasBounds = canvas.getBoundingClientRect()
let mouse = {x: 0, y: 0}
class Shooter {
constructor(x, y, color) {
this.x = 0;
this.y = 0;
this.xEnd = this.x + 50;
this.yEnd = this.y;
this.translate = {x: x, y: y}
this.color = color;
this.angle = 0;
}
draw() {
this.angle = Math.atan2(mouse.y - this.translate.y, mouse.x - this.translate.x)
c.save();
c.translate(this.translate.x, this.translate.y);
c.rotate(this.angle);
c.beginPath();
c.moveTo(this.x, this.y);
c.lineTo(this.xEnd, this.yEnd);
c.strokeStyle = this.color;
c.stroke();
c.restore()
}
update() {
}
}
const shooter = new Shooter(width/2, height/2, "white");
canvas.addEventListener("mousemove", e => {
mouse.x = e.x - canvasBounds.x;
mouse.y = e.y - canvasBounds.y;
});
function animate() {
requestAnimationFrame(animate);
c.fillStyle = "rgba(0, 0, 0, 0.5)";
c.fillRect(0, 0, canvas.width, canvas.height);
//player.draw();
shooter.draw();
}
requestAnimationFrame(animate);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body style="height: 100vh;">
<Canvas id="canvas"></Canvas>
<script src="main.js"></script>
</body>
</html>

Why is my cube showing two times farther than the cursor?

I am an HTML beginner, and I am trying to make a game where you could control the player with your cursor. However, the below page seemingly shows it two times farther than the cursor. Is my code wrong? If yes, where is it wrong?
Thank you very much.
const canvas = document.getElementById('screen');
const ctx = canvas.getContext('2d');
var x = 0;
var y = 0;
canvas.style.top = 0;
canvas.style.left = 0;
function drawPlayer() {
ctx.fillStyle = "yellow";
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
ctx.fillRect(x, y, 10, 10);
ctx.fillStyle = "white";
ctx.strokeStyle = "white";
ctx.lineWidth = 0;
ctx.fillRect(x + 1, y + 1, 3, 3);
ctx.fillRect(x + 6, y + 1, 3, 3);
ctx.fillStyle = "black";
ctx.strokeStyle = "black";
ctx.lineWidth = 0;
ctx.fillRect(x + 2, y + 2, 2, 2);
ctx.fillRect(x + 7, y + 2, 2, 2);
ctx.fillStyle = "red";
ctx.strokeStyle = "red";
ctx.lineWidth = 0;
ctx.fillRect(x + 2, y + 6, 6, 2);
}
function handle(event) {
x = event.offsetX;
y = event.offsetY;
}
setInterval(function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawPlayer();
}, 10)
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cube Quest</title>
<style>
canvas {
width: 100%;
height: 100%;
position: absolute;
}
</style>
<script src="game.js"></script>
</head>
<body>
<canvas id="screen" onmousemove="handle(event)"></canvas>
</body>
</html>
That is because you will need to define the canvas width and height manually, otherwise it falls back to the default values of 300px for width and 150px for height, i.e.:
// Specify the dimensions of the canvas
ctx.canvas.width = canvas.clientWidth;
ctx.canvas.height = canvas.clientHeight;
You might also want to consider setting the canvas width and height when the viewport is resized. See working example here:
const canvas = document.getElementById('screen');
const ctx = canvas.getContext('2d');
var x = 0;
var y = 0;
canvas.style.top = '0px';
canvas.style.left = '0px';
function setCanvasSize() {
// Specify the dimensions of the canvas
ctx.canvas.width = canvas.clientWidth;
ctx.canvas.height = canvas.clientHeight;
}
// Set dimensions at runtime
setCanvasSize();
// Set dimensions when window is resized
window.addEventListener('resize', function () {
setCanvasSize();
});
function drawPlayer() {
ctx.fillStyle = "yellow";
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
ctx.fillRect(x, y, 10, 10);
ctx.fillStyle = "white";
ctx.strokeStyle = "white";
ctx.lineWidth = 0;
ctx.fillRect(x + 1, y + 1, 3, 3);
ctx.fillRect(x + 6, y + 1, 3, 3);
ctx.fillStyle = "black";
ctx.strokeStyle = "black";
ctx.lineWidth = 0;
ctx.fillRect(x + 2, y + 2, 2, 2);
ctx.fillRect(x + 7, y + 2, 2, 2);
ctx.fillStyle = "red";
ctx.strokeStyle = "red";
ctx.lineWidth = 0;
ctx.fillRect(x + 2, y + 6, 6, 2);
}
function handle(event) {
x = event.offsetX;
y = event.offsetY;
}
setInterval(function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawPlayer();
}, 10)
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cube Quest</title>
<style>
canvas {
width: 100%;
height: 100%;
position: absolute;
}
</style>
<script src="game.js"></script>
</head>
<body>
<canvas id="screen" onmousemove="handle(event)"></canvas>
</body>
</html>
Personally, though, I would not try to redraw the canvas using setInterval, because you only want to redraw when mousemove is detected. Your code can be further improved by simply listening to the mousemove event on the canvas element:
const canvas = document.getElementById('screen');
const ctx = canvas.getContext('2d');
var x = 0;
var y = 0;
canvas.style.top = '0px';
canvas.style.left = '0px';
function setCanvasSize() {
// Specify the dimensions of the canvas
ctx.canvas.width = canvas.clientWidth;
ctx.canvas.height = canvas.clientHeight;
}
// Set dimensions at runtime
setCanvasSize();
// Set dimensions when window is resized
window.addEventListener('resize', function () {
setCanvasSize();
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawPlayer();
});
function drawPlayer() {
ctx.fillStyle = "yellow";
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
ctx.fillRect(x, y, 10, 10);
ctx.fillStyle = "white";
ctx.strokeStyle = "white";
ctx.lineWidth = 0;
ctx.fillRect(x + 1, y + 1, 3, 3);
ctx.fillRect(x + 6, y + 1, 3, 3);
ctx.fillStyle = "black";
ctx.strokeStyle = "black";
ctx.lineWidth = 0;
ctx.fillRect(x + 2, y + 2, 2, 2);
ctx.fillRect(x + 7, y + 2, 2, 2);
ctx.fillStyle = "red";
ctx.strokeStyle = "red";
ctx.lineWidth = 0;
ctx.fillRect(x + 2, y + 6, 6, 2);
}
function handle(event) {
x = event.offsetX;
y = event.offsetY;
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawPlayer();
}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cube Quest</title>
<style>
canvas {
width: 100%;
height: 100%;
position: absolute;
}
</style>
</head>
<body>
<canvas id="screen" onmousemove="handle(event)"></canvas>
</body>
</html>

How to move an object on a canvas continuously in one direction for as long as the mouse button is down?

I have a red circle with a blue circle circling around it. I am trying to move the red circle in the direction of the blue circle when the mouse button is pressed.
But it currently only moves once.
I would like to have it moving continually while I press the mouse button, so that it keeps moving towards the direction of where the blue circle happens to be, keeping the blue circle ahead of it (and not circling) for as long as the mouse button is down.
Here is my code. Click the mouse button to see the reaction of the red circle:
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let positionX = 100;
let positionY = 100;
let X = 50;
let Y = 50;
let angle = 0;
canvas.addEventListener('mousedown', function(){
X += positionX;
Y += positionY;
})
function circle(){
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(X, Y, 20, 0, Math.PI*2);
ctx.closePath();
ctx.fill();
}
function direction(){
ctx.fillStyle = 'blue';
ctx.beginPath();
ctx.arc(positionX + X, positionY + Y, 10, 0, Math.PI*2);
ctx.closePath();
positionX = 35 * Math.sin(angle);
positionY = 35 * Math.cos(angle);
angle += 0.1;
ctx.fill();
}
function animate(){
ctx.clearRect(0,0, canvas.width, canvas.height);
circle();
direction();
requestAnimationFrame(animate);
}
animate();
#canvas1{
position: absolute;
top:0;
left: 0;
width: 100%;
height: 100%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="canvas1"></canvas>
<script src="script.js"></script>
</body>
</html>
If you want to continually have the red circle move towards the blue one, for as long as the mouse button is down, then you need to maintain the state of the mouse button. You can do that by keeping a global flag updated with a handler for the mousedown and the mouseup event.
Then move the code that updates X and Y into the animation loop: make that update when the flag is true (when the mouse button is down). On the other hand, only update the angle (for the blue circle) when the mouse button is not down:
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let positionX = 100;
let positionY = 100;
let X = 50;
let Y = 50;
let angle = 0;
let mouseButtonDown = false;
document.addEventListener('mousedown', () => mouseButtonDown = true);
document.addEventListener('mouseup', () => mouseButtonDown = false);
function circle(){
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(X, Y, 20, 0, Math.PI*2);
ctx.closePath();
ctx.fill();
}
function direction(){
ctx.fillStyle = 'blue';
ctx.beginPath();
ctx.arc(positionX + X, positionY + Y, 10, 0, Math.PI*2);
ctx.closePath();
positionX = 35 * Math.sin(angle);
positionY = 35 * Math.cos(angle);
ctx.fill();
}
function animate(){
if (mouseButtonDown) {
X += positionX / 10;
Y += positionY / 10;
} else {
angle += 0.1;
}
ctx.clearRect(0,0, canvas.width, canvas.height);
circle();
direction();
requestAnimationFrame(animate);
}
animate();
#canvas1{
position: absolute;
top:0;
left: 0;
width: 100%;
height: 100%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="canvas1"></canvas>
<script src="script.js"></script>
</body>
</html>

Why can't I move my circle inside the canvas?

I'm trying to move two circles separately, but I can't seem to make the two circles move despite searching over w3school or youtube, I know how to move one circle but when I try to move two circle by creating a constructor it fails.
I'm sure this is a dumb question but I just can't help but ask.
let canvas = document.querySelector("#canvas");
let ctx = canvas.getContext("2d");
let ball = new drawCircle(50, 50, 20);
let ballTwo = new drawCircle(100, 100, 20);
function drawCircle(x, y, r) {
this.x = x;
this.y = y;
this.r = r;
this.draw = function() {
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI *2);
ctx.fillStyle = "lightskyblue";
ctx.fill();
}
}
function draw() {
ball.x += 1;
ball.draw();
ballTwo.x += 1;
ballTwo.draw();
if (x + r > canvas.width || x < r) {
dx = -dx;
}
if (y + r > canvas.width || y < r) {
dy = -dy;
}
requestAnimationFrame(draw)
}
draw();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Círculo</title>
<style>
body {
margin: 0;
display: flex;
justify-content: center;
}
#canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvas" width="300" height="300"></canvas>
</body>
<script src="/js/canvasTwo.js"></script>
</html>

Categories

Resources