Mouse Follow with Ease

by kirupa | 14 December 2015

Earlier, we had a circle follow the mouse cursor around and learned all about how to make that example work. In this page, we are going to continue our look at having something follow the mouse cursor, but there is going to be a twist.


This is a companion discussion topic for the original entry at http://www.kirupa.com/canvas/mouse_follow_ease.htm

How can I make the circle shape have a starting position but instead of it moving with the mouse movement, I would like it to be draggable… so it is still until you click on it and drag it to any desired position.

This may be what you are looking for: https://www.kirupa.com/html5/drag.htm

Or…are you looking for it to be canvas specific? :slight_smile:

1 Like

I have a Canvas already made. I wanted to put a draggable circle in the lower right hand corner. I tried to combine the drag circle code to this code and it is not working for me :cry: .This is what I have so far:

<!DOCTYPE html>
<html>
<head> 
     <title>Help me find...</title>
	<style>
	 canvas {
	 border: #333 0px solid;
	 }
	</style> 
</head>
<body>	
      <canvas id="myCanvas" width="900" height="400"></canvas>
	<script>
	  var canvas = document.querySelector("#myCanvas");
	  var context = canvas.getContext("2d");
	  
	  // orange image
	  var myImage = new Image();
	  myImage.src = "https://www.kirupa.com/canvas/images/orange.svg";
	  myImage.addEventListener("load", loadImage, false);
	  
	  function loadImage(e) {
	  context.drawImage(myImage, 0, 300, 70, 70);
	  
	  // text
	  context.font = "bold italic 26px Helvetica, Arial, sans-serif";
	  context.fillStyle = "red";
	  context.fillText("Help me find......", 53, 30);
	  }
	  
	 //Triangle
				context.beginPath();
				context.moveTo(20,43);
				context.lineTo(50, 43);
				context.lineTo(10,0);
				context.closePath();
				context.lineWidth = 3; 
				context.strokeStyle = "#DCB001"; 
				context.stroke();   
				context.fillStyle = "yellow"; 
				context.fill();
		//line		
		context.beginPath();
        context.moveTo(20, 60);
        context.bezierCurveTo(0, 80, 100, 250, 50, 300);
        context.stroke();
        context.closePath();
	 
	</script>
    
</body>

</html>

Sadly, that won’t work since the canvas drawn content won’t react to the mouse click/drag in the same way a DOM element would. Let me fiddle with this later tonight and see what can be done.

1 Like

Yes… I got them to work on the same page but they are working separately and not together :confused:. Thank you! Please let me know if you can figure something out…

I got it to work! Kind of lol. The circle goes outside the canvas but it still interacts with stuff that is in.
The HTML:

<!DOCTYPE html>
<html>
<head> 
     <title>Help me find...</title>
	
	<link rel="stylesheet" type="text/css" href="myCanvas.css">
	
</head>
<body>	
      <canvas id="myCanvas" width="900" height="400"></canvas>
	 
	   <div id="item"></div>
	   <script>
	   var canvas = document.querySelector("#myCanvas");
       var context = canvas.getContext("2d");

var dragItem = document.querySelector("#item");
var dragItemCoord = dragItem.getBoundingClientRect()
console.log(dragItemCoord)
var active = false;
var currentX;
var currentY;
var initialX;
var initialY;
var xOffset = 0;
var yOffset = 0;
  
window.addEventListener("touchstart", dragStart, false);
window.addEventListener("touchend", dragEnd, false);
window.addEventListener("touchmove", drag, false);

window.addEventListener("mousedown", dragStart, false);
window.addEventListener("mouseup", dragEnd, false);
window.addEventListener("mousemove", drag, false);

// orange image
var myImage = new Image();
myImage.src = "https://www.kirupa.com/canvas/images/orange.svg";

myImage.addEventListener("load", loadImage, false);

function loadImage(e) { 
  context.drawImage(myImage, 0, 300, 70, 70); 
  // text 
  context.font = "bold italic 26px Helvetica, Arial, sans-serif";
  context.fillStyle = "red";
  context.fillText("Help me find...", 53, 30);
  
  //Triangle
  context.beginPath();
  context.moveTo(20,43);
  context.lineTo(50, 43);
  context.lineTo(10,0);
  context.closePath();
  context.lineWidth = 3;
  context.strokeStyle = "#DCB001";
  context.stroke();
  context.fillStyle = "yellow";
  context.fill();
  
  //line
  context.beginPath();
  context.moveTo(20, 60);
  context.bezierCurveTo(0, 80, 100, 250, 50, 300);
  context.stroke();
  context.closePath();
}

 // drag circle 
function dragStart(e) {
  if (e.type === "touchstart") {
    initialX = e.touches[0].clientX - xOffset;
    initialY = e.touches[0].clientY - yOffset;
  } else {
    initialX = e.clientX - xOffset;
    initialY = e.clientY - yOffset;
  }
  if (e.target === dragItem) {
     active = true;
  }
}
  
function dragEnd(e) {
  initialX = currentX;
  initialY = currentY;

  active = false;
}
  
function drag(e) {
  if (active) {
    e.preventDefault();
  
  if (e.type === "touchmove") {
    currentX = e.touches[0].clientX - initialX;
    currentY = e.touches[0].clientY - initialY;
  } else {
    currentX = e.clientX - initialX;
    currentY = e.clientY - initialY;
  }

  xOffset = currentX;
  yOffset = currentY;

  setTranslate(currentX, currentY, dragItem);
  }
}

function setTranslate(xPos, yPos, el) {
el.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0)";
}
	   </script>
</body>

</html>

The CSS:

#myCanvas {
border: solid 0px black;
}

#item {
position: absolute;
top: 300px;
left: 455px;
width: 25px;
height: 25px;
background-color: #FF6A6A;
border: 20px solid rgba(136, 136, 136, .5);
border-radius: 50%;
touch-action: none;
user-select: none;
}
#item:active {
background-color: rgba(255, 255, 255, 1.00);
}
#item:hover {
cursor: pointer;
border-width: 20px;