0

I have a very wide image that exceeds mostly viewing widths and must be rendered using a <canvas> tag. How would I hide the overflow and also center the image?

In other words, I'm looking for the canvas equivalent to background-position: center.

Ideally, this would be done in a way which is responsive - so if the viewing window is resized, the image stays centered.

Here's an example:

window.onload = function() {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");
  var img = document.getElementById("image");
  ctx.drawImage(img, 0, 0);
};
.container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
}

canvas {
  overflow: hidden;
}

.canvasContainer {
  width: 100%;
  overflow-x: hidden;
}

img {
  display: none;
}
<div class="container">
  <div class="canvasContainer">
    <img id="image" src="http://via.placeholder.com/2400x800?text=center" />
    <canvas id="canvas" width="2400" height="800" />
  </div>
</div>

Note: There is a text Center present in the placeholder, but is currently not visible

Carl Binalla
  • 5,393
  • 5
  • 27
  • 46
friendofdog
  • 79
  • 12

3 Answers3

1

This code should do what you need. The image width should be set to the canvas.width to avoid the image overflowing the canvas. The image height is now relative to the image width so the ratio stays the same. I have included an event listener which will resize your canvas/image to the size of the window.

function init() {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");
  var img = document.getElementById("image");
  var canHeight = window.innerWidth / 4;
  canvas.width = window.innerWidth;
  canvas.height = canHeight;
  var width = canvas.width;
  ctx.drawImage(img, 0, 0, width, canHeight);
}

init();
  
  window.addEventListener('resize', function() {
   canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    init();
  });
LS1996
  • 26
  • 4
1

For the canvas you just draw the image where you want it. It will not add scroll bars. The example loads the image and centers it on the canvas. You can click to see the image scaled to fit (see all the image), fill (see full height, or full width whichever fits best to fill the canvas) and click again to see at full resolution centered.

const image = new Image();
image.src = "http://via.placeholder.com/2400x800";
image.onload = showImage;


  
addEventListener("resize",showImageFit)
function drawText(text){
  const ctx = canvas.getContext("2d");
  ctx.font = "28px arial";
  ctx.textAlign = "center";
  ctx.fillText(text,canvas.width / 2, 28);
}


function showImage(){
  canvas.width = innerWidth - 8;
  canvas.height = innerHeight - 8;
  const x = (canvas.width / 2 - image.naturalWidth / 2) | 0;
  const y = (canvas.height / 2 - image.naturalHeight / 2) | 0;
  canvas.getContext("2d").drawImage(image,x,y);
  drawText("Click to scale image to fit");
  canvas.onclick = showImageFit;
}

function showImageFit(){
  canvas.width = innerWidth - 8;
  canvas.height = innerHeight - 8;
  const scale = Math.min( canvas.width /image.naturalWidth , canvas.height / image.naturalHeight );
  const x = (canvas.width / 2 - (image.naturalWidth / 2) * scale) | 0;
  const y = (canvas.height / 2 - (image.naturalHeight / 2) * scale) | 0;
  canvas.getContext("2d").drawImage(image,x,y,image.naturalWidth  * scale, image.naturalHeight * scale);
  drawText("Click to scale image to fill");
  canvas.onclick = showImageFill;
}
function showImageFill(){
  canvas.width = innerWidth - 8;
  canvas.height = innerHeight - 8;
  const scale = Math.max( canvas.width /image.naturalWidth , canvas.height / image.naturalHeight );
  const x = (canvas.width / 2 - (image.naturalWidth / 2) * scale) | 0;
  const y = (canvas.height / 2 - (image.naturalHeight / 2) * scale) | 0;
  canvas.getContext("2d").drawImage(image,x,y,image.naturalWidth  * scale, image.naturalHeight * scale);
  
  drawText("Click to see image at full resolution and centered");
  canvas.onclick = showImage;
}
canvas {
   border : 2px solid black;
}
body {
   margin : 0px;
}
<canvas id="canvas"></canvas>
Blindman67
  • 51,134
  • 11
  • 73
  • 136
0

Thanks for the feedback - the suggested solutions work with solving the canvas problem.

I found another solution, which was to treat the canvas as I would any other oversized element and use CSS.

       +-------------------------------------------+
       | page container                            |
+---------------------------------------------------------+
|                                                         |
| canvas                                                  |
+---------------------------------------------------------+
       |                                           |
       +-------------------------------------------+

Solution (and illustration) taken from here: center oversized image in div

margin-left: 50%;
transform: translateX(-50%);
friendofdog
  • 79
  • 12