1

I cannot clear the cursor image (canvas.getBoundingClientRect) after the cursor moves across the canvas element! I am left with a trail of appended images on the canvas.

  • How can I clear the trail of appended images and still keep my customized cursor (canvas.getBoundingClientRect) visible each time the canvas is cleared?

See my code :

<script>
window.addEventListener("load", CanvasProperties, false);

//Global Variables
var canvas, context;     

// Canvase Element - 2D Properties
function CanvasProperties(){
   canvas = document.getElementById("canvas");        
   context = canvas.getContext("2d");        
   window.addEventListener("mousemove", CustomCursor, false);};

// Customized Cursor for Game's Canvas    
   function CustomCursor(e){
   var canvasRect = canvas.getBoundingClientRect(); 
   var xPosition = e.clientX - 5 - canvasRect.left;
   var yPosition = e.clientY - 5 - canvasRect.top;
   var img = new Image();
   img.src = "hero.png";
   context.drawImage(img, xPosition, yPosition, 80, 80);};

</script>
Cody Taylor
  • 77
  • 2
  • 8
  • This is one of the cases where you really should use DOM instead of canvas. You're reinventing the wheel here. – Tomáš Zato Nov 16 '15 at 15:19
  • Tomas, this wheel is worth reinventing. Instead of adding a DOM image element as the JavaScript - img.src, there has to be some way to draw and clear the img on the canvas if it is associated with the canvas.getBoundingClientRect. – Cody Taylor Nov 16 '15 at 15:25
  • You can easily clear you canvas by resetting its width and height. For example: `canvas.width = canvas.width` should clear your drawing context. – somethinghere Nov 16 '15 at 15:25
  • @somethinghere true, but that's kinda costly operation – Tomáš Zato Nov 16 '15 at 15:26
  • You could also use `context.save()` and `context.restore()` to constantly save and restore the context before drawing the cursor. – somethinghere Nov 16 '15 at 15:27
  • Possible duplicate of [How to clear the canvas for redrawing](http://stackoverflow.com/questions/2142535/how-to-clear-the-canvas-for-redrawing) – Tomáš Zato Nov 16 '15 at 15:35

3 Answers3

3

Yeah, this one was really hard to google. The answer I like the best: https://stackoverflow.com/a/2142549/607407

function CustomCursor(e){
   var canvasRect = canvas.getBoundingClientRect(); 

   var img = new Image();
   img.src = "https://crossorigin.me/https://www.gravatar.com/avatar/5a061a72feb5b6580dadd5dcbc92d3b5?s=64&d=identicon&r=PG";
   var xPosition = e.clientX - 5 - canvasRect.left-img.naturalWidth/2;
   var yPosition = e.clientY - 5 - canvasRect.top- img.naturalHeight/2;

   context.clearRect(0, 0, canvas.width, canvas.height);
   context.drawImage(img, xPosition, yPosition, 80, 80);
};

Snippet:

//Global Variables - which is wrong
var canvas, context;     

// Canvase Element - 2D Properties
function CanvasProperties(){
   canvas = document.getElementById("canvas");   
   canvas.width = window.innerWidth;
   canvas.height = window.innerHeight;
   context = canvas.getContext("2d");        
   window.addEventListener("mousemove", CustomCursor, false);
}
// Customized Cursor for Game's Canvas    
function CustomCursor(e){
   var canvasRect = canvas.getBoundingClientRect(); 

   var img = new Image();
   img.src = "https://crossorigin.me/https://www.gravatar.com/avatar/5a061a72feb5b6580dadd5dcbc92d3b5?s=64&d=identicon&r=PG";
   var xPosition = e.clientX - 5 - canvasRect.left-img.naturalWidth/2;
   var yPosition = e.clientY - 5 - canvasRect.top- img.naturalHeight/2;
   
   context.clearRect(0, 0, canvas.width, canvas.height);
   context.drawImage(img, xPosition, yPosition, 80, 80);
};

CanvasProperties();
<canvas width="300" height="300" id="canvas" />
Community
  • 1
  • 1
Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
  • Yeah, it is just that simple. alternatively, to save time drawing.you could save the last known location of the mouse and just draw over where the old location was, and then draw the new location. – Sean_A91 Nov 16 '15 at 15:31
  • Why would `clearRect` be more costly than resetting the width, btw? They both accomplish the same result - I can undertand its a DOM operation but the cost is not going to be very high, right? (But yes, `clearRect` is probably better but I am just wondering) – somethinghere Nov 16 '15 at 15:31
  • @somethinghere unless optimised, reseting the width causes repaint call and creates/destroys canvas data. I am just guessing, I did not see the implementation sourcecode. – Tomáš Zato Nov 16 '15 at 15:32
  • Resetting the width isn't all that bad if the canvas is in a fixed size container. otherwise the whole dom will have to adjust to the size change twice – Sean_A91 Nov 16 '15 at 15:33
  • All true, I guess one of the major advantages would also be that `clearRect` can clear just a little bit of canvas instead of wiping the whole thing. – somethinghere Nov 16 '15 at 15:34
  • Thanks, Tomas for the advice on repeating the CanvasProperties() function! – Cody Taylor Nov 16 '15 at 15:44
  • @CodyTaylor note that this only work if the canvas is already in the document. You might also consider `DOMContentLoaded` event, which fires before onload - just as soon as HTML is ready. – Tomáš Zato Nov 16 '15 at 15:49
1

Customized Canvas Cursor - Works! :)

<!DOCTYPE html>
<html>

<body id="body" style="background-color:gray;">

<canvas id="canvas" width="600" height="400" style="background-color:white;  
display:block; margin:1 auto;"> </canvas>


<script>
window.addEventListener("load", CanvasProperties, false);

//JavaScript Variables
  var canvas, context;     

// Canvase Element - 2D Properties
function CanvasProperties(){
   canvas = document.getElementById("canvas");   

   context = canvas.getContext("2d");        
   window.addEventListener("mousemove", CustomCursor, false);
}

// Customized Cursor for Game's Canvas    
function CustomCursor(e){
   var canvasRect = canvas.getBoundingClientRect(); 

  var img = new Image(); img.src = "hero.png";
   var xPosition = e.clientX - 5 - canvasRect.left;
   var yPosition = e.clientY - 5 - canvasRect.top;

  context.clearRect(0, 0, canvas.width, canvas.height);
  context.drawImage(img, xPosition, yPosition, 80, 80);
};

 CanvasProperties();
</script>

</body>
</html>
Cody Taylor
  • 77
  • 2
  • 8
0

You could just use css for this very easily, as the above stated in the comments, don't reinvent the wheel, javascript is still a lot slower than the native client the browser is running on. check out this https://davidwalsh.name/css-custom-cursor and you can use the canvas:hover to make it so it uses your custom cursor whenever the mouse is over it.

Sean_A91
  • 333
  • 4
  • 15
  • Although true, it does not solve the problem. If this was not related to drawing a cursor but drawing something else, this answer would be pointless. – somethinghere Nov 16 '15 at 15:28
  • You are completely correct! And thus, I would not have given that answer for other questions, In the same way I would not say 2 + 2 = fish... well at least to a teacher. – Sean_A91 Nov 16 '15 at 15:29