Make image horizontally and vertically centered over canvas drawing with HTML, CSS, and JS

Sorry if the title is vague, it was hard to figure out what to call this problem. I have a canvas and an image overlaying each other like this:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

function newLine(){
  let value = (Math.floor(Math.random() * 100) + 1) * 0.06283185307179587;
  ctx.clearRect(0, 0, c.width, c.height);
  ctx.lineWidth = 10;
  ctx.strokeStyle = '#00FF00';
  
  ctx.beginPath();
  ctx.arc(100, 75, 55, 0, value);
  ctx.stroke();
}

setInterval(()=>{
newLine()
}, 100)
img{
  width: 100px;
  border-radius: 50px;
  position: absolute;
  left: 58px;
  top: 33px;
 }
<img src="https://media-exp1.licdn.com/dms/image/C4E0BAQHikN6EXPd23Q/company-logo_200_200/0/1595359131127?e=2159024400&v=beta&t=S5MNjBDjiH433VCWzjPeiopNDhxGwmfcMk4Zf1P_m_s"></img>
<canvas id="myCanvas"></canvas>

This works, but when I go to add multiple, or add a div above them, because of the image’s absolute position, the image ends up over the div, not the canvas. Here’s an example illustrating my issues:

var can = document.getElementsByClassName("canvas");

for (var i = 0; i < can.length; i++) {
let c = can.item(i)
var ctx = c.getContext("2d");

function newLine(){
  let value = (Math.floor(Math.random() * 100) + 1) * 0.06283185307179587;
  ctx.clearRect(0, 0, c.width, c.height);
  ctx.lineWidth = 10;
  ctx.strokeStyle = '#00FF00';
  
  ctx.beginPath();
  ctx.arc(100, 75, 55, 0, value);
  ctx.stroke();
  
  requestAnimationFrame(newLine)
}

newLine()
}
img{
  width: 100px;
  border-radius: 50px;
  position: absolute;
  left: 58px;
  top: 33px;
 }
 
 div{
  background-color: red;
 }
 
canvas{
  display: inline-block;
 }
<div class="top">
<h1>Some text</h1>
</div>

<img src="https://media-exp1.licdn.com/dms/image/C4E0BAQHikN6EXPd23Q/company-logo_200_200/0/1595359131127?e=2159024400&v=beta&t=S5MNjBDjiH433VCWzjPeiopNDhxGwmfcMk4Zf1P_m_s"></img>
<canvas class="canvas"></canvas>

<img src="https://media-exp1.licdn.com/dms/image/C4E0BAQHikN6EXPd23Q/company-logo_200_200/0/1595359131127?e=2159024400&v=beta&t=S5MNjBDjiH433VCWzjPeiopNDhxGwmfcMk4Zf1P_m_s"></img>
<canvas class="canvas"></canvas>

(If you could figure out why the first one doesn’t play, that would be amazing also)

The issues are:

  • The first canvas doesn’t play
  • The images (because it’s position is absolute) are stacked up and not over the second canvas

Is it possible to do this but with relative positioning? Please let me know if this was a confusing question. Thanks

1 thought on “Make image horizontally and vertically centered over canvas drawing with HTML, CSS, and JS”

  1. Avoid mixing images <img> and canvas, instead just draw the image inside the canvas with drawImage nothing special just a few more lines on JavaScript

    Here is an example:
    (And I also fixed your issue where the first one does not play)

    class Shape {
      constructor(ctx, width, height, image) {
        this.ctx = ctx;
        this.width = width;
        this.height = height;
        this.image = image;
        this.value = Math.random() * 5
        this.inc = 0.03
      }
    
      draw() {
        this.value += this.inc;
        if (this.value > 2 * Math.PI || this.value < 0.05) this.inc *= -1;
        this.ctx.clearRect(0, 0, this.width, this.height);
        // Draw centered round image 
        this.ctx.beginPath();    
        this.ctx.drawImage(this.image , 50, 24, 100, 100);
        this.ctx.lineWidth = 50;
        this.ctx.strokeStyle = 'white';
        this.ctx.arc(100, 75, 75, 0, 2 * Math.PI);
        this.ctx.stroke();
        // Draw green progress bar
        this.ctx.beginPath();
        this.ctx.lineWidth = 12;
        this.ctx.strokeStyle = '#00FF00';
        this.ctx.arc(100, 75, 55, 0, this.value);
        this.ctx.stroke();        
      }
    }
    
    var can = document.getElementsByClassName("canvas");
    var animations = []
    
    function loop() {
      animations.forEach(anim => anim.draw());
      requestAnimationFrame(loop)
    }
    
    var image = new Image();
    image.src = "https://media-exp1.licdn.com/dms/image/C4E0BAQHikN6EXPd23Q/company-logo_200_200/0/1595359131127?e=2159024400&v=beta&t=S5MNjBDjiH433VCWzjPeiopNDhxGwmfcMk4Zf1P_m_s";
    image.onload = imageLoaded;
    
    function imageLoaded() {
      for (var i = 0; i < can.length; i++) {
        let c = can.item(i)
        animations.push(new Shape(c.getContext("2d"), c.width, c.height, image));
      }
      loop()
    }
    div {
      background-color: red;
    }
    
    canvas {
      display: inline-block;
      border: 1px solid gray;
    }
    <div class="top">
      <h2>Some text</h2>
    </div>
    
    <canvas class="canvas" width=200></canvas>
    <canvas class="canvas" width=200></canvas>
    Reply

Leave a Comment