Javascript Canvas Movement - javascript

I have this movement in my canvas:
Gif
I am trying to move everything but the black-gray square. I have tried many times but i dont know how to get the result i need, the rotation is made like this:
ctx.translate(x, y);
if (or == 'R') {
ctx.rotate(Math.PI / movementSpeed);
}
else if (or == 'L'){
ctx.rotate(-Math.PI / movementSpeed);
}
ctx.translate(-x, -y);
drawRect();
drawRect2();
drawCircle();
And the black-gray square i am trying to not move is made like this:
function drawRect() {
ctx.fillStyle = "#393939";
ctx.fillRect(x-35, y-30, 180, 60);
ctx.stroke();
ctx.fill();
ctx.restore();
}
Code snippet:
<!DOCTYPE html>
<html lang="en">
<head>
<style type="text/css">
#import url('https://fonts.googleapis.com/css2?family=Jost:wght#500&display=swap');
body
{
overflow: hidden;
}
div#cerradura {
position: absolute;
width: 100%;
left:5%;
text-align: center;
font-size: 18px;
}
</style>
</head>
<body>
<div onclick="" id="cerradura">
<canvas id="myCanvas" width="1600" height="800">
</canvas>
</div>
</body>
<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
let tensorAdentro = false;
let movimiento = 500;
let rotacion = 0;
let x = 1100;
let y = 400;
function dibujarGanzua() {
// Ganzúa
ctx.lineWidth = 7;
ctx.strokeStyle = "#595959";
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, y+190);
ctx.stroke();
ctx.restore();
}
function dibujarManija() {
// Rectangulo de la cerradura
ctx.fillStyle = "#393939";
ctx.fillRect(x-35, y-30, 180, 60);
ctx.stroke();
ctx.fill();
ctx.restore();
}
function dibujarCerradura() {
ctx.strokeStyle = "#000000";
// Circulo de la cerradura
ctx.fillStyle = '#909090';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(x, y, 20, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
ctx.restore();
// Hueco de la cerradura
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(x-10, y);
ctx.lineTo(x+10, y);
ctx.stroke();
ctx.restore();
}
function girarGanzua(or) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(x, y);
if (or == 'R') {
ctx.rotate(Math.PI / movimiento);
rotacion += (((Math.PI / movimiento)*180)/Math.PI);
}
else if (or == 'L'){
ctx.rotate(-Math.PI / movimiento);
rotacion += (-((Math.PI / movimiento)*180)/Math.PI);
}
ctx.translate(-x, -y);
dibujarManija();
dibujarCerradura();
dibujarGanzua();
}
window.addEventListener('mousedown', (e) => {
if (!tensorAdentro && e.button === 0) {
dibujarGanzua();
tensorAdentro = !tensorAdentro;
}
});
// Lee input de mouse
var direction = "",
oldx = 0,
mousemovemethod = function (e) {
dx = e.clientX - oldx;
if (dx < 0 && tensorAdentro) {
if (rotacion <= 90) {
girarGanzua('R')
}
}
else if (dx > 0 && tensorAdentro){
if (rotacion > 0) {
girarGanzua('L')
}
}
oldx = e.clientX;
}
document.addEventListener('mousemove', mousemovemethod);
dibujarManija();
dibujarCerradura();
</script>
</html>
How can i make this happen?
Thanks.

What is happening here is that the context is getting rotated on every mouse move without getting restored to the original state. It would be better to save the context before drawing and restore it when finished drawing. And, to rotate it by the correct angle, just rotate it by rotacion * Math.PI / 180 every time.
function girarGanzua(or) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save(); // Save the context
dibujarManija(); // Draw the large Rect before rotating
ctx.translate(x, y);
ctx.rotate(rotacion * Math.PI / 180);
if (or == 'R') {
rotacion += (((Math.PI / movimiento)*180)/Math.PI);
}
else if (or == 'L'){
rotacion += (-((Math.PI / movimiento)*180)/Math.PI);
}
ctx.translate(-x, -y);
dibujarCerradura();
dibujarGanzua();
ctx.restore(); // Restore the context
}
Also, there is no need to restore the context after drawing each entity.
Working Snippet:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
let tensorAdentro = false;
let movimiento = 500;
let rotacion = 0;
let x = 200;
let y = 200;
function dibujarGanzua() {
// Ganzúa
ctx.lineWidth = 7;
ctx.strokeStyle = "#595959";
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, y+190);
ctx.stroke();
//ctx.restore(); No Need
}
function dibujarManija() {
// Rectangulo de la cerradura
ctx.fillStyle = "#393939";
ctx.fillRect(x-35, y-30, 180, 60);
ctx.stroke();
ctx.fill();
//ctx.restore(); No Need
}
function dibujarCerradura() {
ctx.strokeStyle = "#000000";
// Circulo de la cerradura
ctx.fillStyle = '#909090';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(x, y, 20, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
//ctx.restore(); No Need
// Hueco de la cerradura
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(x-10, y);
ctx.lineTo(x+10, y);
ctx.stroke();
//ctx.restore(); No Need
}
function girarGanzua(or) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
dibujarManija();
ctx.translate(x, y);
ctx.rotate(rotacion * Math.PI / 180);
if (or == 'R') {
rotacion += (((Math.PI / movimiento)*180)/Math.PI);
}
else if (or == 'L'){
rotacion += (-((Math.PI / movimiento)*180)/Math.PI);
}
ctx.translate(-x, -y);
dibujarCerradura();
dibujarGanzua();
ctx.restore();
}
window.addEventListener('mousedown', (e) => {
if (!tensorAdentro && e.button === 0) {
dibujarGanzua();
tensorAdentro = !tensorAdentro;
}
});
// Lee input de mouse
var direction = "",
oldx = 0,
mousemovemethod = function (e) {
dx = e.clientX - oldx;
if (dx < 0 && tensorAdentro) {
if (rotacion <= 90) {
girarGanzua('R')
}
}
else if (dx > 0 && tensorAdentro){
if (rotacion > 0) {
girarGanzua('L')
}
}
oldx = e.clientX;
}
document.addEventListener('mousemove', mousemovemethod);
dibujarManija();
dibujarCerradura();
#import url('https://fonts.googleapis.com/css2?family=Jost:wght#500&display=swap');
body
{
overflow: hidden;
}
div#cerradura {
position: absolute;
width: 100%;
left:5%;
text-align: center;
font-size: 18px;
}
<div onclick="" id="cerradura">
<canvas id="myCanvas" width="1600" height="800"></canvas>
</div>

Related

Progress var using canvas and javascript

I'm trying to make a circle progress bar circle to show my skills but since I put a setInterval function, It doesn't work. I think the ligne context.arc() doesn't take the values and so it shows nothing, but I can't get throught this problem, how can i do ? Thank you in advance
HTML :
<section id="skills">
<div class="load-container">
<canvas id="canvas" width="800" height="800"></canvas>
<span id="percent"></span>
</div>
</section>
JavaScript :
<script>
class Circle
{
constructor(x, y, percent)
{
this.posX = x;
this.posY = y;
this.percent = percent;
this.radius = 100;
}
drawing(context)
{
let unitValue = (Math.PI - 0.5 * Math.PI) / 25;
let startAngle = 0;
let endAngle = startAngle + (this.percent * unitValue);
let arcInterval = setInterval (function()
{
startAngle += 1;
/*grey circle*/
context.beginPath();
context.arc(this.posX, this.posY, this.radius, startAngle, (2 * Math.PI), false);
context.strokeStyle = '#b1b1b1';
context.lineWidth = '10';
context.stroke();
/*blue circle*/
context.beginPath();
context.arc(this.posX, this.posY, this.radius, startAngle, endAngle, false);
context.strokeStyle = '#3949AB';
context.lineWidth = '10';
context.stroke();
if (startAngle >= endAngle)
{
clearInterval(arcInterval);
}
}, 500);
}
}
function setup()
{
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
/*draw the circles*/
let circle = new Circle(150, 200, 86);
circle.drawing(context);
let circle2 = new Circle(400, 200, 76);
circle2.drawing(context);
let circle3 = new Circle(650, 200, 44);
circle3.drawing(context);
let circle4 = new Circle(150, 450, 35);
circle4.drawing(context);
}
window.onload = function()
{
setup();
}
</script>
Here is how I would do it...
Keep your class Circle code as small as possible, and do the loop (setInterval) in the setup, that way you can clear the entire canvas there, I think that is a better way.
class Circle {
constructor(x, y) {
this.posX = x;
this.posY = y;
}
drawing(context, radius, startAngle, endAngle) {
context.beginPath();
context.arc(this.posX, this.posY, radius, startAngle, endAngle, false);
context.stroke();
}
}
function setup() {
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
let startAngle = 0;
let endAngle = 2 * Math.PI
/*draw the circles*/
let circle = new Circle(30, 30);
let circ2 = new Circle(60, 80);
let circ3 = new Circle(80, 40);
let arcInterval = setInterval(function() {
startAngle += 0.1;
context.clearRect(0, 0, 180, 180);
circle.drawing(context, 20, startAngle, endAngle - 1);
circ2.drawing(context, 20, startAngle - 1, endAngle);
circ3.drawing(context, 15 - startAngle * 2, 0, 2 * Math.PI);
if (startAngle > endAngle) {
clearInterval(arcInterval);
}
}, 100);
}
window.onload = function() {
setup();
}
<canvas id="canvas" width="180" height="180"></canvas>
As you can see I'm passing multiple parameters to the drawing function:
drawing(context, radius, startAngle, endAngle)
that way we can control those parameters from the loop, and with a bit of math you can make the progress animation more fun, but I let you to fine-tune that.
Try this. I've just changed the step count. You may change it from 5 to what ever you want.
<script>
class Circle {
constructor(x, y, percent) {
this.posX = x;
this.posY = y;
this.percent = percent;
this.radius = 100;
this.arcInterval = null; // Changed
}
drawCallback(ctx, start, end) { // Added
let inc = 1;
return () => {
inc += 1;
console.log(inc);
drawArc(ctx, this.posX, this.posY, this.radius, '#3949AB', start, end * inc / 5);
if (inc > 5) {
clearInterval(this.arcInterval);
}
}
}
drawing(context) { // Added
let unitValue = 0.5 * Math.PI / 25; // Changed
const startAngle = 0; // Changed
const endAngle = startAngle + (this.percent * unitValue); // Changed
/* grey circle */
drawArc(context, this.posX, this.posY, this.radius, '#b1b1b1', startAngle, 2 * Math.PI); // Changed
/* blue circle */
this.arcInterval = setInterval(this.drawCallback(context, startAngle, endAngle), 500); // Changed
}
}
function drawArc(ctx, posX, posY, radius, color, startAngle, endAngle) { // Added
ctx.beginPath();
ctx.arc(posX, posY, radius, startAngle, endAngle, false);
ctx.strokeStyle = color;
ctx.lineWidth = '10';
ctx.stroke();
}
function setup() {
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
/*draw the circles*/
let circle = new Circle(150, 200, 86);
circle.drawing(context);
let circle2 = new Circle(400, 200, 76);
circle2.drawing(context);
let circle3 = new Circle(650, 200, 44);
circle3.drawing(context);
let circle4 = new Circle(150, 450, 35);
circle4.drawing(context);
}
window.onload = function () {
setup();
}
</script>
<!doctype html>
<html>
<body>
<section id="skills">
<div class="load-container">
<canvas id="canvas" width="800" height="800"></canvas>
<span id="percent"></span>
</div>
</section>
<script>
class Circle
{
constructor(x, y, percent) {
this.posX = x;
this.posY = y;
this.percent = percent;
this.radius = 100;
this.startAngle = 0; // <---
this.unitValue = (Math.PI - 0.5 * Math.PI) / 25; //
this.endAngle = this.startAngle + (this.percent * this.unitValue);
}
drawing(context) {
this.arcInterval = setInterval (function(ctx,that) {
that.startAngle += 1;
/*grey circle*/
ctx.beginPath();
ctx.arc(that.posX, that.posY, that.radius, that.startAngle, (2 * Math.PI), false);
ctx.strokeStyle = '#b1b1b1';
ctx.lineWidth = '10';
ctx.stroke();
/*blue circle*/
ctx.beginPath();
ctx.arc(that.posX, that.posY, that.radius, that.startAngle, that.endAngle, false);
ctx.strokeStyle = '#3949AB';
ctx.lineWidth = '10';
ctx.stroke();
// Why stop ?
// if (that.startAngle >= that.endAngle) { clearInterval(that.arcInterval); }
}, 500,context, this); // <------ this -> that and context -> ctx
}
}
function setup() {
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
/*create circles*/
window.myCircles = [new Circle(150, 200, 86),
new Circle(400, 200, 76),
new Circle(650, 200, 44),
new Circle(150, 450, 35)];
for (let o of window.myCircles) { o.drawing(context); }
}
window.onload = function() { setup(); }
</script>
</body>
</html>
You can try the funny way ->
class Circle
{
constructor(x, y, percent) {
this.posX = x;
this.posY = y;
this.percent = percent;
this.radius = 100;
this.startAngle = 0; // <---
this.unitValue = (Math.PI - 0.5 * Math.PI) / 25; //
this.endAngle = this.startAngle + (this.percent * this.unitValue);
}
drawing(context) {
this.arcInterval = setInterval (function(ctx,that) {
that.startAngle += 1;
/*grey circle*/
ctx.beginPath();
ctx.arc(that.posX, that.posY, that.radius, that.startAngle, (2 * Math.PI), false);
ctx.strokeStyle = '#b1b1b1';
ctx.lineWidth = '10';
ctx.stroke();
/*blue circle*/
ctx.beginPath();
ctx.arc(that.posX, that.posY, that.radius, that.startAngle, that.endAngle, false);
ctx.strokeStyle = '#3949AB';
ctx.lineWidth = '10';
ctx.stroke();
// Why stop ?
// if (that.startAngle >= that.endAngle) { clearInterval(that.arcInterval); }
}, 500,context, this); // <------ this -> that and context -> ctx
}
}
function setup() {
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
/*create circles*/
window.myCircles = [new Circle(150, 200, 86),
new Circle(400, 200, 76),
new Circle(650, 200, 44),
new Circle(150, 450, 35)];
for (let o of window.myCircles) { o.drawing(context); }
}
window.onload = function() { setup(); }

In JavaScript Canvas, How do I keep my drawing inside my canvas after shifting it with a function?

I am trying to move my drawing with "up", "down", "left", "right" and "reset". However, I would like to keep it inside of the canvas at all times, so when I click any of the buttons and move the drawing, it would touch the borders but not go outside of the border. Here is what I have so far...
HTML
<canvas id="myCanvas" width="250" height="250" style="border:1px solid #000000;"></canvas></br>
<button id="up">Up</button><br>
<button id="left">Left</button>
<button id="right">Right</button>
<button id="reset">Reset</button></br>
<button id="down">Down</button>
JavaScript
let c, ctx, pos, centerX, centerY, radius, eyeRadius, eyeXOffset, eyeYOffset
window.onload = function() {
c = document.getElementById("myCanvas");
ctx = c.getContext("2d");
centerX = c.width / 2;
centerY = c.height / 2;
radius = 70;
eyeRadius = 10;
eyeXOffset = 25;
eyeYOffset = 20;
reset();
}
function drawFace(){
//my drawObject() from last assignment - separated into 3 different parts
// Draw the yellow circle
ctx.beginPath();
ctx.arc(centerX + pos.left, centerY + pos.top, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'yellow';
ctx.fill();
ctx.lineWidth = 5;
ctx.strokeStyle = 'black';
ctx.stroke();
ctx.closePath();
}
function drawEyes(){
//my drawObject() from last assignment - separated into 3 different parts
// Draw the eyes
let eyeX = centerX + pos.left - eyeXOffset;
let eyeY = centerY + pos.top - eyeYOffset;
ctx.beginPath();
ctx.arc(eyeX, eyeY, eyeRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'black';
ctx.fill();
ctx.closePath();
ctx.beginPath();
eyeX = centerX + pos.left + eyeXOffset;
ctx.arc(eyeX, eyeY, eyeRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'black';
ctx.fill();
ctx.closePath();
}
function drawMouth(){
//my drawObject() from last assignment - separated into 3 different parts
// Draw the mouth
ctx.beginPath();
ctx.arc(centerX + pos.left, centerY + pos.top, 50, 0, Math.PI, false);
ctx.stroke();
ctx.closePath();
}
function draw() {
clear();
drawFace();
drawEyes();
drawMouth();
}
function clear() {
ctx.clearRect(0, 0, c.width, c.height);
}
function reset() {
pos = {
left: 0,
top: 0
}
draw();
}
function up() {
pos.top -= 20;
draw();
}
function down() {
pos.top += 20;
draw();
}
function left() {
pos.left -= 20;
draw();
}
function right() {
pos.left += 20;
draw();
}
document.getElementById("reset").onclick = reset;
document.getElementById("up").onclick = up;
document.getElementById("down").onclick = down;
document.getElementById("left").onclick = left;
document.getElementById("right").onclick = right;

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

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

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

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

line rotation in class javascript canvas

I try to create a class with a function which might be use to change the angle of a line already drawn.
With what I write, the line doesn't move. When I press the right or left key, I have this error :
TypeError: this.changeAngle is not a function
Indeed, I don't have "function" keyword in my code ... I don't know what to use instead.
Could you help me ?
Thank you very much.
window.onload = init;
let canvas, ctx;
let mousePos;
let angle = 0;
class Lanceur {
constructor() {
this.changeAngle(this.angle);
}
update(ctx) {
this.drawAiguille(ctx);
}
drawSocleLanceur(ctx) {
ctx.save();
ctx.beginPath();
ctx.lineWidth = 2;
ctx.arc(w/2, h, 20, 0, 2 * Math.PI);
ctx.stroke();
ctx.restore();
}
drawAiguille(ctx) {
ctx.save();
ctx.rotate(this.angle);
ctx.strokeStyle = "rgb(255, 0, 0)";
ctx.lineWidth=3;
ctx.beginPath();
ctx.moveTo(w/2, h-h*0.12);
ctx.lineTo(w/2, h-h*0.035);
ctx.stroke();
ctx.restore();
}
changeAngle(a) {
this.angle = a;
}
getAngle() {
return this.angle;
}
}
function init() {
canvas = document.querySelector("#jeu");
ctx = canvas.getContext("2d");
w = canvas.width;
h = canvas.height;
a = new Lanceur();
requestAnimationFrame(mainloop);
}
function mainloop() {
ctx.clearRect(0, 0, w, h);
a.update(ctx);
requestAnimationFrame(mainloop);
}
document.addEventListener('keypress', function(event){
gereTouches(event);
});
function gereTouches(event) {
if(event.key == "ArrowRight") {
this.changeAngle(this.getAngle - 1);
console.log("ça bouge : " + this.angle);
}else if(event.key == "ArrowLeft") {
this.changeAngle(this.getAngle + 1);
}
}
Main changes:
added this.angle to thr constructor()
using keydown event
the function gereTouches(event) uses a instead of this and a.getAngle() instead of a.getAngle
also 1 for the the angle is way too big (those are radians). I'm using .01 instead.
I hope it helps.
window.onload = init;
let canvas, ctx;
let mousePos;
let angle = 0;
class Lanceur {
constructor() {
this.angle = 0;
this.changeAngle(this.angle);
}
update(ctx) {
this.drawAiguille(ctx);
}
drawSocleLanceur(ctx) {
ctx.save();
ctx.beginPath();
ctx.lineWidth = 2;
ctx.arc(w/2, h, 20, 0, 2 * Math.PI);
ctx.stroke();
ctx.restore();
}
drawAiguille(ctx) {
ctx.save();
ctx.rotate(this.angle);
ctx.strokeStyle = "rgb(255, 0, 0)";
ctx.lineWidth=3;
ctx.beginPath();
ctx.moveTo(w/2, h-h*0.12);
ctx.lineTo(w/2, h-h*0.035);
ctx.stroke();
ctx.restore();
}
changeAngle(a) {
this.angle = a;
}
getAngle() {
return this.angle;
}
}
function init() {
canvas = document.querySelector("#jeu");
ctx = canvas.getContext("2d");
w = canvas.width = 500;
h = canvas.height = 500;
a = new Lanceur();
requestAnimationFrame(mainloop);
}
function mainloop() {
ctx.clearRect(0, 0, w, h);
a.update(ctx);
requestAnimationFrame(mainloop);
}
document.addEventListener('keydown', function(event){
gereTouches(event);
});
function gereTouches(event) {
if(event.key == "ArrowRight") {
a.changeAngle(a.getAngle() - .01);
console.log("ça bouge : " + a.angle);
}else if(event.key == "ArrowLeft") {
a.changeAngle(a.getAngle() + .01);
}
}
canvas{border:1px solid}
<canvas id="jeu"></canvas>

Categories

Resources