DEV Community

Cover image for Canvas Draggable Ball
Avinash Kumar
Avinash Kumar

Posted on

Canvas Draggable Ball

Well do you know what canvas is? Well only recently, did I figure out about customisation using it.
It is an HTML5 element that allows you to draw fun shapes, lines, and points and manipulate them using animations.
In this post I will walk you though how I created a drag-gable ball using it.

Here is a preview of what will be the final output -

1. HTML file

Firstly we create our HTML file and use the canvas tag.

<body>
    <canvas id="canvas">your browser does not support canvas</canvas>
    <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
    <script src="app.js"></script>
</body>
Enter fullscreen mode Exit fullscreen mode

1. CSS file

We then start creating and designing our workspace or the ball. We use basic css here,nothing fancy.

#canvas{
    position: absolute;
    width: 100vmin;
    height: 99%;
    background-color: rgb(64, 83, 189);
    border: 1px solid rgb(255, 255, 255);
    border-radius: 10px solid rgb(12, 0, 2);
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
  }
Enter fullscreen mode Exit fullscreen mode

3. JS File

Here is where all the magic happens, we add the animations, define the ball constraints, allow for the ball to be draggable. We use simple flags to determine it.

const canvas = $("#canvas")[0];
const ctx = canvas.getContext("2d");

var widthclientX = canvas.clientWidth;
var widthclientY = canvas.clientHeight;
var width = (canvas.width = 500);
var height = (canvas.height = 500);

var differenceX = width - widthclientX;
var differenceY = height - widthclientY;
$(window).resize(() => {
  widthclientX = canvas.clientWidth;
  widthclientY = canvas.clientHeight;
  differenceX = width - widthclientX;
  differenceY = height - widthclientY;
});
var currentBallX = 250;
var currentBallY = 250;

// Dragabble Ball Code
var dragable = false;

$("#canvas").bind("mouseup touchend", (e) => {
  dragable = false;
});
$("#canvas").bind("mousedown", (e) => {
  if (
    e.offsetX < currentBallX + 40 &&
    e.offsetX > currentBallX - 40 &&
    e.offsetY > currentBallY - 40 &&
    e.offsetY < currentBallY + 40
  ) {
    dragable = true;
  } else {
    dragable = false;
  }
  //   console.log(e.offsetX, e.offsetY);
});
$("#canvas").on("touchstart", (e) => {
  var bcr = e.target.getBoundingClientRect();
  var x = e.targetTouches[0].clientX - bcr.x;
  var y = e.targetTouches[0].clientY - bcr.y;
  console.log(x, y);
  var xPrecentage = (x * 100) / widthclientX;
  var yPrecentage = (y * 100) / widthclientY;
  if (
    x < currentBallX - (differenceX * xPrecentage) / 100 + 20 &&
    x > currentBallX - (differenceX * xPrecentage) / 100 - 20 &&
    y > currentBallY - (differenceY * yPrecentage) / 100 - 20 &&
    y < currentBallY - (differenceY * yPrecentage) / 100 + 20
  ) {
    console.log("true");
    dragable = true;
  } else {
    console.log("false");
    dragable = false;
  }
});
$("#canvas").on("touchmove", (e) => {
  var bcr = e.target.getBoundingClientRect();
  var x = e.targetTouches[0].clientX - bcr.x;
  var y = e.targetTouches[0].clientY - bcr.y;
  var xPrecentage = (x * 100) / widthclientX;
  var yPrecentage = (y * 100) / widthclientY;
  if (dragable) {
    currentBallX = x + (differenceX * xPrecentage) / 100;
    currentBallY = y + (differenceY * yPrecentage) / 100;
  }
});
$("#canvas").bind("mouseout", (e) => {
  dragable = false;
});
$("#canvas").bind("mousemove", (e) => {
  if (dragable) {
    currentBallX = e.offsetX;
    currentBallY = e.offsetY;
  }
});

function animate() {
  ctx.clearRect(0, 0, width, height);
  ctx.beginPath();
  ctx.arc(currentBallX, currentBallY, 40, 0, 2 * 3.14);
  ctx.stroke();
  ctx.fill();
  requestAnimationFrame(animate);
}
animate();

Enter fullscreen mode Exit fullscreen mode

The goal of this post was to motivate and instigate a spark in someone who is trying to dive into canvas.In my opinion it is an amazing tool and really does wonders.
Hope it helps! Happy learning!

Top comments (1)

Collapse
 
msarabi profile image
Mohammad Sarabi

Nice. I generally prefer vanilla JavaScript over JQuery as I feel like it limits me in some places.