tracking canvas x and y coordinates animation on mousemove event - javascript

I am trying to make a circle moving animation with mousemove event, each time the circle will moving from my mouse.x and mouse.ycoordinates on the screen. so I declare my mouse coordinates object and drawCricleobject constructor:
var mouse = {
x:canvas.width/2,
y:canvas.height/2
}
function Circle (x,y,r,dy){
this.x = x;
this.y = y;
this.r = r;
this.dy = dy;
this.update = function(){
ctx.beginPath();
ctx.arc(this.x,this.y,this.r,0,Math.PI*2);
ctx.fillStyle = 'blue';
ctx.fill();
this.y+=this.dy;
if(this.y<this.r || this.y+this.r>canvas.height){
this.dy=-this.dy;
}
}
}
and after i add the mousemoveevent so i am thinking i can assign the mouse x/y coordinate through my mouvemove eventListenter:
var myCircle = new Circle(mouse.x,mouse.y,30,2);
function animate(){
ctx.clearRect(0,0,canvas.width,canvas.height);
myCircle.update();
requestAnimationFrame(animate);
}
window.addEventListener("mousemove",function(e){
mouse.x = e.clientX;
mouse.y = e.clientY;
animate();
});
the problem is the mouse.xandmouse.yvalue won't change from the original canvas.width/2value, so i have tried to wrapper my animation()function inside the window.addEventListener instead just calling it within, just like:
window.addEventListener("mousemove",function(e){
mouse.x = e.clientX;
mouse.y = e.clientY;
var myCircle = new Circle(mouse.x,mouse.y,30,2);
function animate(){
ctx.clearRect(0,0,canvas.width,canvas.height);
myCircle.update();
requestAnimationFrame(animate);
}
animate();
});
this could work a bit but it looks really stupid and makes my browser comes huge laggy spikes, is there any other way to do this?

You would also need to pass the mouse coordinates when calling the update function ...
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var mouse = {
x: canvas.width / 2,
y: canvas.height / 2
};
function Circle(x, y, r, dy) {
this.r = r;
this.dy = dy;
this.update = function(x, y) {
ctx.beginPath();
ctx.arc(x, y, this.r, 0, Math.PI * 2);
ctx.fillStyle = 'blue';
ctx.fill();
this.y += this.dy;
if (this.y < this.r || this.y + this.r > canvas.height) {
this.dy = -this.dy;
}
};
}
var myCircle = new Circle(mouse.x, mouse.y, 30, 2);
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
myCircle.update(mouse.x, mouse.y);
requestAnimationFrame(animate);
}
canvas.addEventListener("mousemove", function(e) {
mouse.x = e.offsetX;
mouse.y = e.offsetY;
});
animate();
body{margin:10px 0 0 0;overflow:hidden}canvas{border:1px solid #e4e6e8}
<canvas id="canvas" width="635" height="208"></canvas>

Related

Rotating and moving object (follow into mouse) - Javascript

everybody!
I want to make a small tank that will follow the mouse and turn its cannon towards the mouse.
I made a deal following the mouse, but there is no way I can turn the gun towards the mouse.
My code:
// canvas variable
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// browser window size
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
//set canvas size
canvas.width = windowWidth;
canvas.height = windowHeight;
var mouseX = 0;
var mouseY = 0;
var baseAngle = 1;
class Cannon {
constructor(x,y, angle, size, speed){
this.x = x;
this.y = y;
this.angle = angle;
this.size = size;
this.speed = speed;
}
draw() {
// bullet
ctx.setTransform(1, 0, 0, 1, this.x, this.y - (this.size/2));
ctx.translate(this.x, this.y);
ctx.rotate(baseAngle);
ctx.beginPath();
ctx.rect(this.x, this.y - (this.size/2), this.size*2, this.size);
ctx.fillStyle = 'rgb(192,192,192)';
ctx.fill();
ctx.lineWidth = 3;
ctx.strokeStyle = 'rgba(128,128,128)';
ctx.stroke();
ctx.closePath();
//body
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fillStyle = 'rgb(0,96,255)';
ctx.fill();
ctx.lineWidth = 3;
ctx.strokeStyle = 'rgba(128,128,128)';
ctx.stroke();
ctx.closePath();
}
update() {
// mooving
var dx = (mouseX - this.x)*.125;
var dy = (mouseY - this.y)*.125;
var dist = Math.sqrt(dx*dx + dy*dy);
if(dist > this.speed){
dx *= this.speed / dist;
dy *= this.speed / dist;
}
this.x += dx;
this.y += dy;
// rootating
baseAngle = Math.atan2(mouseY - this.y, mouseX - this.x);
}
}
const newCannon = new Cannon(80,60, 1, 20, 7);
onmousemove = function(e){
mouseX = e.clientX;
mouseY = e.clientY;
}
function gameUpdate() {
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform
ctx.clearRect(0, 0, canvas.width, canvas.height);
newCannon.draw();
newCannon.update();
requestAnimationFrame(gameUpdate);
}
gameUpdate();
<!DOCTYPE html>
<html>
<head>
<title>CRUSH DEMO</title>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
The cannon must be rotated in the direction of the mouse (the circle itself must not be rotated).
help me please fix the code!

How to add SVG image to javascript html5 canvas animation?

I currently have a rotating bouncing ball within an html5 canvas and I am looking to insert an SVG image inside the ball that moves and rotates with it
I have this code from researching this but unsure if this is correct
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
img.src = "";
Does anyone have any suggestion on how I might achieve this?
Here is my code
<canvas id="myCanvas"></canvas>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
// SPEED
var dx = 4;
var dy = -4;
var radius = 120;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fillStyle = "#9370DB";
ctx.fill();
ctx.closePath();
if (x + dx > canvas.width - radius) {
dx = -dx;
}
if (x + dx < radius) {
dx = -dx;
}
if (y + dy > canvas.height - radius) {
dy = -dy;
}
if (y + dy < radius) {
dy = -dy;
}
x += dx;
y += dy;
}
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resizeCanvas();
x = canvas.width / 2;
y = canvas.height / 2;
setInterval(draw, 10);
var img = new Image();
img.src = ""; // Put the path to you SVG image here.
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
This should work
One way of doing it would be putting the image hidden in the HTML. In this case the image is an svg as data uri and has an id="apple" and you can say:
var img = apple;
To draw the image inside the ball you need to use the center of the ball, for example like this:
ctx.drawImage(img, x-img.width/2,y-img.height/2)
Also instead of using setInterval I'm using requestAnimationFrame and the image is not getting out of the screen on resize. I hope you will find my answer useful.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var rid = null;// request animation id
// SPEED
var dx = 4;
var dy = -4;
var radius = 120;
var img = apple;// the image is the one with the id="apple"
function draw() {
rid = window.requestAnimationFrame(draw);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fillStyle = "#9370DB";
ctx.fill();
ctx.closePath();
//draw the image in the center of the ball
ctx.drawImage(img, x-img.width/2,y-img.height/2)
if (x + dx > canvas.width - radius) {
dx = -dx;
}
if (x + dx < radius) {
dx = -dx;
}
if (y + dy > canvas.height - radius) {
dy = -dy;
}
if (y + dy < radius) {
dy = -dy;
}
x += dx;
y += dy;
}
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
//stop the animation
if(rid){window.cancelAnimationFrame(rid); rid= null;}
//get the size of the canvas
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
x = canvas.width / 2;
y = canvas.height / 2;
//restart the animation
draw()
}
window.setTimeout(function() {
resizeCanvas();
window.addEventListener('resize', resizeCanvas, false);
}, 15);
<canvas id="myCanvas">
<img id="apple" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1' x='0px' y='0px' width='106px' height='122px' viewBox='41 54 106 122'%3E%3Cg%3E%3Cpath fill='%23FFFFFF' stroke='%23ED1D24' stroke-width='2' stroke-miterlimit='10' d='M143.099,93.757c0,0-14.173,8.549-13.724,23.173 c0.449,14.624,11.954,23.413,15.974,24.073c1.569,0.258-9.245,22.049-15.984,27.448c-6.74,5.4-13.714,6.524-24.513,2.25c-10.8-4.275-18.449,0.275-24.749,2.612c-6.299,2.337-13.949-0.137-24.298-14.987c-10.349-14.849-21.823-49.271-6.074-66.146c15.749-16.874,33.298-10.124,38.022-7.875c4.725,2.25,13.05,2.025,22.499-2.25C119.7,77.782,138.374,86.782,143.099,93.757z'/%3E%3C/g%3E%3Cg%3E%3Cpath fill='%23FFFFFF' stroke='%23ED1D24' stroke-width='2' stroke-miterlimit='10' d='M118.575,54.609c0,0,0.9,5.625-1.35,10.349 s-10.718,20.936-22.994,17.999c-0.308-0.073-2.102-5.506,0.532-11.027C98.48,64.138,108.171,55.399,118.575,54.609z'/%3E%3C/g%3E%3C/svg%3E" />
</canvas>
Please run the code on full page.

move player object towards cursor direction in canvas (slither.io style)

I've found similar questions but not exact. I can do this with mouse onclick but I'm not sure how to handle it with just 'mousemove' event.
my current situation JSFiddle for example
I'm trying to make it so the screen is translated towards the mouse while moving my player, not only on mousemove. But I'm not sure how else to go about this.
I have a player object that updates when mouse is moved.
function Player (x,y) {
this.x = x;
this.y = y;
this.draw = function () {
ctx.beginPath();
ctx.arc(this.x,this.y,30,0,Math.PI * 2, false);
ctx.fillStyle = 'black';
ctx.fill();
}
this.update = function () {
this.x = playerX;
this.y = playerY;
this.draw();
}
}
this update function doesn't allow contstant movment, but when I try to implement something it ends up creating large amounts of lag - clearly I'm taking a wrong approach.
At the moment, I'm just detection where the mouse is in compared to the center of the screen.
document.addEventListener('mousemove', (event) => {
moveWorld(event);
});
function moveWorld(e){
var x = e.clientX;
var y = e.clientY;
// playerSpeed is 3
var centerX = window.innerWidth / 2
var centerY = window.innerHeight / 2
// move south
if (y < centerY) {
ctx.translate (0,playerSpeed);
playerY -= playerSpeed;
}
// move e
if (x < centerX) {
ctx.translate (playerSpeed,0);
playerX -=playerSpeed;
}
// move north
if (y > centerY) {
ctx.translate (0,-playerSpeed);
playerY += playerSpeed;
}
// move west
if (x > centerX) {
ctx.translate (-playerSpeed,0);
playerX +=playerSpeed;
}
drawWorld();
}
and finally to render it all.
function drawWorld(){
requestAnimationFrame(drawWorld); // refresh world
// CLEAR
ctx.clearRect(0,0,innerHeight,innerHeight);
// world
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 50, 50);
ctx.fillRect(110, 30, 50, 50);
// player
player.update();
}
document.addEventListener('mousemove', (event) => {
moveWorld(event);
});
drawWorld();
Assume mouse is at center of screen
On mousemove, update the mouse coordinates
Run moveWorld in a loop using the last known mouse coordinates for directions.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var playerX = canvas.width / 2;
var playerY = canvas.height / 2;
$(window).on("resize", function () {
$("#login,#game,#canvas").width( $(this).width());
$("#login,#game,#canvas").height( $(this).height());
playerX = canvas.width / 2;
playerY = canvas.height / 2;
}).resize();
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var playerSpeed = 3;
var mouseX = centerX;
var mouseY = centerY;
function mouseUpdate(e) {
mouseX = e.clientX;
mouseY = e.clientY;
}
function moveWorld(){
var x = mouseX;
var y = mouseY;
var centerX = window.innerWidth / 2
var centerY = window.innerHeight / 2
// move south
if (y < centerY) {
ctx.translate (0,playerSpeed);
playerY -= playerSpeed;
}
// move e
if (x < centerX) {
ctx.translate (playerSpeed,0);
playerX -=playerSpeed;
}
// move north
if (y > centerY) {
ctx.translate (0,-playerSpeed);
playerY += playerSpeed;
}
// move west
if (x > centerX) {
ctx.translate (-playerSpeed,0);
playerX +=playerSpeed;
}
drawWorld();
requestAnimationFrame(moveWorld);
}
var player = new Player (playerX, playerY);
var counter = 0;
function drawWorld() {
// CLEAR
ctx.clearRect(0,0,innerHeight,innerHeight);
// world
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 50, 50);
ctx.fillRect(110, 30, 50, 50);
// player
player.update();
}
document.addEventListener('mousemove', (event) => {
mouseUpdate(event);
});
requestAnimationFrame(moveWorld);
function Player (x,y) {
this.x = x;
this.y = y;
this.draw = function () {
ctx.beginPath();
ctx.arc(this.x,this.y,30,0,Math.PI * 2, false);
ctx.fillStyle = 'black';
ctx.fill();
}
this.update = function () {
this.x = playerX;
this.y = playerY;
this.draw();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas"></canvas>
Updated
As you are trying to develop a Slither.io system, I assume that you are looking for Slither.io Clone made by Loonride available on Github
Are you trying to achieve something like the following ? Phaser 3 : pointer - move event
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: {
preload: preload,
create: create
}
};
var game = new Phaser.Game(config);
var player = null;
function preload ()
{
this.load.spritesheet('balls', 'https://labs.phaser.io/assets/sprites/balls.png', { frameWidth: 17, frameHeight: 17 });
}
function create ()
{
player = this.add.image(0,0, 'balls', Phaser.Math.Between(0, 5));
this.input.on('pointermove', function (pointer) {
player.x = pointer.x;
player.y = pointer.y;
}, this);
}
<script src="//cdn.jsdelivr.net/npm/phaser#3.15.1/dist/phaser.min.js"></script>
<div id="phaser-example" style="overflow: hidden;"></div>
The right way to do this kind of thing is to let the browser handle the 'frame tick' by using window.requestAnimationFrame.
Here's my fiddle:
https://jsfiddle.net/r5e2ht1v/4/
var mouseX, mouseY;
document.addEventListener('mousemove', (event) => {
mouseX = event.clientX;
mouseY = event.clientY;
});
function drawWorld(){
// CLEAR
ctx.clearRect(0,0,innerHeight,innerHeight);
// world
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 50, 50);
ctx.fillRect(110, 30, 50, 50);
// player
player.update();
moveWorld();
window.requestAnimationFrame(drawWorld);
}
window.requestAnimationFrame(drawWorld);
There are some more performance optimisations you can use here:
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas

Create a collision region on canvas elements That interacts with mouse Events

I want to create a collision region around a canvas element that enables me to interact with that element using mouse events width vanilla javascript.
To elaborate more on my problem here is the following:
at first I make an arc segment constructor with x, y, radius, beginAngle, endAngle, and a color arguments
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
/* arc class constructor */
function ArcSegment(x, y, radius, beginAngle, endAngle, segColor) {
this.x = x;
this.y = y;
this.radius = radius;
this.beginAngle = beginAngle;
this.endAngle = endAngle;
this.segColor = segColor;
this.update = function() {
this.draw();
}
this.draw = function(){
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, this.beginAngle, this.endAngle, false);
ctx.lineWidth = 20;
ctx.strokeStyle = this.segColor;
ctx.stroke();
}
}
Secondly, i add some value to create those arc segments
/* x, y, radius, startAngle, endAngle and color */
var centerX = canvas.width/2;
var centerY = canvas.height/2;
var radiuses = [
100,
120
];
var pi = Math.PI;
var segmentStart = [
pi/2,
0
];
var segmentRotation = [
1.4*pi,
0.2*pi
];
var segmentColors = [
"#133046",
"#15959F"
];
Then, i draw Them on the canvas.
var segment1 = new ArcSegment(centerX, centerY, radiuses[0], segmentStart[0], segmentStart[0]+segmentRotation[0], segmentColors[0]);
segment1.update();
var segment2 = new ArcSegment(centerX, centerY, radiuses[1], segmentStart[1], segmentStart[1]+segmentRotation[1], segmentColors[1]);
segment2.update();
and here is the result:
What i want now is a way to create a collision detection on top of each arc segment created, so when a mouse is clicked or moved on top of that specific arc segment
a sequence of events can occur (like a rotation animation for example or so...).
all the research i've done suggest to get the x and y value of a rectangle and calculate the distance of mouse position (mouse.x, mouse.y) and the length of the rectangle, but that method doesn't work with an arc segment with a lineWidth property.
Any help on the subject would be very appreciated.
Below is a pure mathematical approach, the key here is the code isPointInside
// Classes
function Arc(x, y, angle, arc, radius, colour, highlightColour) {
this.x = x;
this.y = y;
this.angle = angle;
this.arc = arc;
this.radius = radius;
this.colour = colour;
this.highlightColour = highlightColour;
this.highlighted = false;
this.lineWidth = 20;
}
Arc.prototype = {
isPointInside: function(x, y) {
var _x = x - this.x;
var _y = y - this.y;
var distance = Math.sqrt(_x * _x + _y * _y);
var invDistance = 1.0 / distance;
var angle = Math.acos(
_x * Math.cos(this.angle) * invDistance +
_y * Math.sin(this.angle) * invDistance
);
return distance > (this.radius - this.lineWidth/2) &&
distance < (this.radius + this.lineWidth/2) &&
angle < this.arc/2;
},
render: function(ctx) {
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.highlighted ? this.highlightColour : this.colour;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, this.angle - this.arc/2, this.angle + this.arc/2, false );
ctx.stroke();
}
};
// Variables
var canvas = null;
var ctx = null;
var arcs = [];
// Functions
function draw() {
ctx.fillStyle = "gray";
ctx.fillRect(0, 0, 999, 999);
for (var i = 0; i < arcs.length; ++i) {
arcs[i].render(ctx);
}
}
// Event Listeners
function onMouseMove(e) {
var bounds = canvas.getBoundingClientRect();
var x = e.clientX - bounds.left;
var y = e.clientY - bounds.top;
for (var i = 0; i < arcs.length; ++i) {
arcs[i].highlighted = arcs[i].isPointInside(x, y);
}
draw();
}
// Entry Point
onload = function() {
canvas = document.getElementById("canvas");
canvas.onmousemove = onMouseMove;
ctx = canvas.getContext("2d");
arcs.push(new Arc(190, 75, 0.2, 1.8, 60, "blue", "lime"));
arcs.push(new Arc(90, 75, 3.5, 4.2, 60, "red", "lime"));
draw();
}
<canvas id="canvas"></canvas>

How to use a function to change the property of another function?

I'm quite new to JS and have gone through courses online but, very frustratingly, I just seem to have such a hard time on my own so I'm sorry if this question has an obvious answer. Basically, this program bounces a colored ball around within a box. I want that color to change every time it hits a wall. I figured out a way to do so by putting all information under one function but the tutorial I'm using is saying (for tidy code purposes) that 2 functions will be better and so I really just want to understand how to do what I want to do when info is available in different functions since I know I will have to do that in the future. I will comment important code lines. Thank you so much to anyone who can help.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width/2;
var y = canvas.height-30;
var dx = 4;
var dy = -4;
var ballRadius = 30;
function drawBall() { \\draws the ball
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#ff0000";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
x += dx;
y += dy;
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) { \\says when to bounce
dx = -dx;
drawBall.ctx.fillStyle = "#ff0000"; \\this line and next line are lines I wrote
drawBall.ctx.fill(); \\that are obviously incorrect (same goes for
} \\ if statement below). What am I doing wrong?
if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
dy = -dy;
drawBall.ctx.fillStyle = "#0095DD";
drawBall.ctx.fill();
}
}
setInterval(draw, 10);
what you can do is pass parameters that will alter the behavior of the function.
in this case you will be passing the color you want.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width/2;
var y = canvas.height-30;
var dx = 4;
var dy = -4;
var ballRadius = 30;
function drawBall(color) { // draws the ball
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fillStyle = color;
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
x += dx;
y += dy;
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) { // says when to bounce
dx = -dx;
drawBall("#ff0000");
}
if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
dy = -dy;
drawBall("#0095DD");
}
}
It seems that you mix some concepts of JavaScript. So for reasons of readability and design, I would create a 'class' for the ball. Something like this:
function Ball(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
}
You can create an instance of your ball with this:
var ball = new Ball(x, y, radius, color);
and access the properties in Java-style:
ball.color = "#0095DD";
You can also add some methods to your ball:
function Ball(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.draw = function(ctx) {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
}
You can extend your code with this class and code. I think, you get it.

Categories

Resources