0

So I am kinda beginner here and decided to try and learn working with canvas a little bit. I followed some tutorials and managed to make a 'ball' to follow my mouse. And it works. However there is a delay. When i move my mouse the 'balls' follows my mouse but with delay. It is always late a little bit. So my question is... Is this is how it is supposed to be (that how canvas work and there is no way around it)m or I am doing something wrong.

Here is my javascript code:

let canvas = document.querySelector('canvas');
let c = canvas.getContext('2d');

canvas.width = innerWidth;
canvas.height = innerHeight;

let mouse = {
    x: innerWidth / 2,
    y: innerHeight / 2
};

addEventListener('mousemove', function (event) {
    mouse.x = event.clientX;
    mouse.y = event.clientY;
})

function Ball(x, y, radius, color) {
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.color = color;

    this.update = function() {
        // eventualy some other code here...
        this.draw();
    };

    this.draw = function() {
        c.beginPath();
        c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);  
        c.fillStyle = this.color;
        c.fill();
        c.closePath();
    };
};

let ball;
function init() {
    ball = new Ball(mouse.x, mouse.y, 30, 'red'); 
};

function animate() {
    requestAnimationFrame(animate);
    c.clearRect(0, 0, canvas.width, canvas.height);
    ball.x = mouse.x;
    ball.y = mouse.y;
    ball.update();
};

init();
animate();

My HTML:

<body>
    <canvas></canvas>
    <script src="javascript.js"></script>
</body>

let canvas = document.querySelector('canvas');
let c = canvas.getContext('2d');

canvas.width = innerWidth;
canvas.height = innerHeight;

let mouse = {
  x: innerWidth / 2,
  y: innerHeight / 2
};

addEventListener('mousemove', function(event) {
  mouse.x = event.clientX;
  mouse.y = event.clientY;
})

function Ball(x, y, radius, color) {
  this.x = x;
  this.y = y;
  this.radius = radius;
  this.color = color;

  this.update = function() {
    // eventualy some other code here...
    this.draw();
  };

  this.draw = function() {
    c.beginPath();
    c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
    c.fillStyle = this.color;
    c.fill();
    c.closePath();
  };
};

let ball;

function init() {
  ball = new Ball(mouse.x, mouse.y, 30, 'red');
};

function animate() {
  requestAnimationFrame(animate);
  c.clearRect(0, 0, canvas.width, canvas.height);
  ball.x = mouse.x;
  ball.y = mouse.y;
  ball.update();
};

init();
animate();
<canvas></canvas>

Any help would be greatly appreciated.

P.S. Updated as requested. This is my entire code.

Tamil Selvan C
  • 19,913
  • 12
  • 49
  • 70
Happy Coconut
  • 973
  • 4
  • 14
  • 33
  • Please post a [complete, working example that demonstrates the problem](https://stackoverflow.com/help/mcve). – ggorlen Nov 23 '18 at 04:19
  • 1
    Have you see this [answer](https://stackoverflow.com/questions/5258424/how-to-set-mousemove-update-speed)? – Starfight Nov 23 '18 at 10:44
  • 1
    Displaying the mouse position will always be one frame behind, there is nothing you can do to change that. You can however hide the mouse `element.style.cursor = "none"` when you drag an object and that removes the perceptual appearance of the delay. – Blindman67 Nov 23 '18 at 11:05
  • Ok my man, thanks for the response. – Happy Coconut Nov 23 '18 at 11:11

2 Answers2

1

The best you can do is remove the perceptual delay, which is only apparent because you have the mouse and the moving object visible at the same time. The delay is very small and without the cursor people just don't notice.

The example just hides the mouse when it is over the canvas.

Note that you should only hide the cursor is you have something else to represent the mouse position.

let canvas = document.querySelector('canvas');
let c = canvas.getContext('2d');

canvas.style.cursor = "none";

canvas.width = innerWidth-40;
canvas.height = innerHeight-40;

let mouse = {
  x: innerWidth / 2,
  y: innerHeight / 2
};

addEventListener('mousemove', function(event) {
  mouse.x = event.clientX;
  mouse.y = event.clientY;
})

function Ball(x, y, radius, color) {
  this.x = x;
  this.y = y;
  this.radius = radius;
  this.color = color;

  this.update = function() {
    // eventualy some other code here...
    this.draw();
  };

  this.draw = function() {
    c.beginPath();
    c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
    c.fillStyle = this.color;
    c.fill();
    c.closePath();
  };
};

let ball;

function init() {
  ball = new Ball(mouse.x, mouse.y, 30, 'red');
};

function animate() {
  requestAnimationFrame(animate);
  c.clearRect(0, 0, canvas.width, canvas.height);
  ball.x = mouse.x;
  ball.y = mouse.y;
  ball.update();
};

init();
animate();
<canvas></canvas>
Blindman67
  • 51,134
  • 11
  • 73
  • 136
0

If you still want the mouse displayed, the best way I could think of was to draw a fake mouse on the ball and hide the real one. Put this code just under where you draw the circle:

canvas.style.cursor = 'none'

c.fillStyle = '#fff'
c.strokeStyle = '#000'

c.save()
c.translate(mouse.x, mouse.y)
c.beginPath()
c.moveTo(0, 0)
c.lineTo(0, 15)
c.lineTo(4, 13)
c.lineTo(7, 18)
c.lineTo(9.5, 17)
c.lineTo(7, 12)
c.lineTo(12, 11)
c.closePath()
c.stroke()
c.fill()
c.restore()

Joachim
  • 178
  • 1
  • 13