Adjust the dimensions of an HTML5 canvas to fit the page while maintaining a specific size for the image displayed

Currently, I am creating a specific sized image at 1200W x 300H and then sending it back to my server once it's done. The process is functional.

However, the issue arises when the created image of 1200x300 size appears too large for many users, especially on mobile devices. Is there a method available that would allow me to create the image at 1200x300 but visually display it on a smaller scale to fit the screen?

Presently, the best solution I have come up with involves using a DIV with overflow:hidden to maintain the correct sizing on the page. However, this approach does not scale down the actual image, resulting in most of the image being off-centered, only displaying the left part on the screen.

<div style="overflow:hidden;" >
  <canvas id="canvas" width="1200" height="300">
    Your browser does not support Canvas.
  </canvas>
</div>

Reducing the canvas size to fit the page subsequently reduces the image created to a smaller size, which is not the desired outcome to be sent back to the server.

Is there a way to achieve this objective?

============= UPDATE ================

<div style="overflow:hidden;" >
   <canvas id="displayCanvas" width="1200" height="300">
      Your browser does not support Canvas.
   </canvas>
   <canvas id="realCanvas" width="1200" height="300">
      Your browser does not support Canvas.
   </canvas>                            
</div> 

#CSS

#realCanvas {
  width:100vw;
  height: 25vw ;
}

#JS

function buildBanner () {
  Debugger.log("Drawing Canvas");
  
  if(!canvasSupport()) {
      return;
  }
  
  var wCanvas = 1200 ;
  var hCanvas = 300 ;
  var wImg = 400 ;
  var hImg = 100 ;
  
  var hRatio = wCanvas  / wImg    ;
  var vRatio =  hCanvas / hImg  ;
  var ratio  = Math.min ( hRatio, vRatio );
  var centerShift_x = ( wCanvas - wImg*ratio ) / 2;
  var centerShift_y = ( hCanvas - hImg*ratio ) / 2;    
  
  var displayCanvas = document.getElementById('displayCanvas') ;
  var displayContext = displayCanvas.getContext('2d');
  
  var realCanvas = document.getElementById('realCanvas');
  var realContext = realCanvas.getContext('2d');

...

Answer №1

To achieve this effect, one option is to monitor a resize event and adjust the CSS width & height properties accordingly. However, there's a simpler approach if your <canvas> element always remains the same size.

In order to comprehend the process, it's important to understand that the width & height defined by the canvas' attributes represent its 'true' resolution. The actual size displayed on screen can be managed through the CSS width & height properties.

The goal is to resize the canvas to occupy the entire vertical viewport of the browser while still preserving its original aspect ratio.

The first step involves calculating its aspect ratio: 300 / 1200 = 0.25, which indicates that its height is a quarter of its width. Put simply, we aim to set the canvas width to 100% of the viewport's width and its height to 25% of the viewport's width.

Fortunately, this directly translates to the CSS unit vw. For example, 100vw == 100% viewport width.

Therefore, all you need to do is establish the canvas' CSS width as 100vw and its height as 25vw.

Check out this illustration:

let image = new Image();
let canvas = document.getElementById('canvas');
let context = canvas.getContext('2d');
image.crossOrigin = 'anonymous';
image.onload = (e) => {
  context.drawImage(e.target, 0, 0, canvas.width, canvas.height);
}
image.src = 'https://picsum.photos/id/10/1200/300';
#canvas {
  background-color: black;
  width: 100vw;
  height: 25vw;
}
<div style="overflow:hidden;">
  <canvas id="canvas" width="1200" height="300">
    Your browser does not support Canvas.
  </canvas>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can you explain the meaning of this compound CSS selector?

.btnBlue.btnLtBlue Is this referring to an element that has both the classes btnBlue and btnLtBlue applied? ...

Tips for creating a dynamic animation of a ball following a curved trajectory with CSS3

Looking to create a cool animation where a ball moves along a curved path? Struggling to figure out how to do it with CSS3 since there's no built-in path animation feature? Wondering if it's possible to animate a ball on a curved background? Ca ...

Tips for avoiding whitespace in flexbox as you resize an item

My flex box setup is pretty straightforward: main { width: 660px; height: 100%; display: flex; justify-content: center; align-items: center; flex-direction: column; } When I look at my page, it appears like this: https://i.sstatic.net/JF8KC.j ...

Duplicate a form based on the selected option

My goal is to duplicate a form based on the numerical value selected from the drop-down menu. You can find the corresponding code in this JSFiddle. Here is the HTML code: <div class="travel_tour-info"> <h3>How many people are you booking for? ...

What is the method for adjusting the width of a v-card based on its height?

I have a changing number of v-cards that are displayed based on their quantity. My goal is to maintain an aspect ratio of 16/9, but only adjust the width. To achieve this, I believe I need to make the width dependent on the height, although I am unsure ho ...

Styling grids in Xamarin

My current project involves using CSS styles with Xamarin Forms. I have a grid with buttons that look like this: https://i.sstatic.net/awLWc.png StackLayout { background-color: #1e1e1e; color: #ffffff; } Button{ background-color: #2d2d30; ...

Angular: NaNa: Attempting to access a property of an undefined variable

I've encountered these errors although the values are displayed correctly in the browser. I'm unsure about how to resolve this issue. ERROR TypeError: Cannot read property 'length' of undefined ERROR TypeError: Cannot read property &ap ...

If someone installs our chat widget on their website using an <iframe> script, I would like the widget to be deactivated when our website is experiencing downtime

We utilize an iframe to create our Chat Widget. One issue we face is that when our main website is down, it causes errors on client websites where the widget is embedded. I am looking for a way to automatically disable the "Chat widget" when our website ...

Convert a relative path to an absolute path using the file:// protocol

When I scrape a website with similar html content, I come across the following code: <a href="/pages/1></a> In addition to this, I have access to the window.location object which contains: origin:"http://www.example.org" This allows me to ...

Making modifications to index.html that is being hosted on GitHub Pages

Need to make a minor change to a website hosted on Github pages, specifically updating the title in the index.html file. Considering modifying and committing the change directly in the Github code editor for ease. Upon checking the repository's Sett ...

The functionality of the page becomes disrupted when multiple timers are used after the setInterval function is executed in

My webpage fetches multiple data for a table, with one of the columns displaying date and time values from which countdown timers run. Each row has its own timer and functions correctly. However, when I added JavaScript code to refresh the table every 10 ...

Is it possible to achieve a smooth transition to the right using CSS

I'm attempting to create a sliding box effect from left to right using only transitions, similar to this: #box { width: 150px; height: 150px; background: red; position:absolute; transition: all 2s ease-out; right:auto; } .active{ bac ...

What is the best way to trigger ajax when the user clicks the back button to return to the previous webpage?

Check out my code snippet below: HTML Code <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div class="body"> <div class="dropdown_div"> <select id="q_type" class="dropdown" ...

Having difficulty with collapsing Bootstrap side navigation menu levels

I've been searching high and low for an example that matches my current issue, but so far, no luck. I'm attempting to design a collapsible side navigation with multiple levels in bootstrap using bootstrap.js. The problem I'm facing is that ...

Alignment text centrally in a button

I'm currently facing an issue with vertically aligning the text within a button to the center. We are using Bootstrap buttons across different devices and platforms, and everything seems to be working fine except for one specific device where the alig ...

Enhancing the background of a website with the power of CSS

I am looking to create a customized table without the balls/pots in it. The number of rows on the y-axis will vary depending on the number of names I have, and can be more or less. The values on the x-axis are determined by a parameter included in the URL ...

What is the way to restrict the length of input in a v-select component?

I am currently using the Vue-select feature in my project and I have encountered an issue with setting a maximum input length of 45 characters within a v-select element. Despite attempting to handle this limitation on the back-end, I am unable to prevent u ...

Why does LESS keep prompting me with missing elements?

I am currently working on my first project using Less and have been following a tutorial closely. However, when I try to compile with lessc, I encounter the following error: ParseError: Unrecognised input. Possibly missing something in C:\Path\t ...

Has the Blueprint CSS framework become obsolete?

Is the Blueprint CSS framework still being actively maintained? The last version was released over a year ago and there have been no recent commits in the Github repository. ...

Deactivate an option within an angularjs multi-select menu

Currently, I am utilizing an angularjs multiselect box which is displayed below: https://i.stack.imgur.com/w6ffN.png Here is the html code snippet: <select multiple ng-options="Language.LangID as Language.LangName for Language in AllLanguages " ng-mo ...