Maintaining aspect ratio of canvas while ensuring responsiveness

Currently, I am working on a drawing app and have come across an issue that has been challenging for me to resolve. The dilemma lies in resizing the canvas of sketches from the original resolution of 1280 x 720 to the maximum size possible upon opening the page. This resizing should maintain the 1280 x 720 aspect ratio, while also accounting for a toolbar located at the top of the page.

The goal is to center the canvas on the screen, with black stripes filling the remaining space based on the dimensions of the browser window. If the window's aspect ratio is less than that of the sketch, horizontal black stripes will be displayed (see fig 1). Conversely, if the aspect ratio is greater, vertical black stripes will be shown (refer to fig 2).

To tackle this challenge, I experimented with JavaScript by calculating the offsetWidth and offsetHeight of a div containing a programmatically generated invisible image matching the original sketch dimensions. However, relying solely on these properties proved to be unreliable as they were not consistently ready when the page loaded, necessitating the use of timers or mutation observers.

I have dedicated significant time to finding a robust solution to this problem, but each approach I discovered seemed either too hacky or prone to errors. Any assistance or suggestions would be greatly appreciated as I work within the Angular + Ionic 4 framework.

Answer №1

If my interpretation is correct, you are looking to dynamically adjust the size of your canvas based on the window's dimensions while maintaining a 1280 x 720 (1:0.5625) aspect ratio.

Here, I will present a solution that listens for window resizing even after it has loaded, requiring you to redraw all content on the canvas accordingly.

HTML

<body>
  <canvas id="canvas"></canvas>
</body>

CSS

body {
  background-color: black;
}

JavaScript:

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

startListening();

function startListening() {
  // Resize the canvas each time the window is adjusted
  window.addEventListener('resize', resizeCanvas, false);
  // Manually trigger the resizeCanvas() function when the page loads to set initial dimensions
  resizeCanvas();
}

function resizeCanvas() {
  // Adjust canvas height according to window width while maintaining 1:0.5625 aspect ratio
  if(canvas.height < window.innerHeight){
    canvas.width = window.innerWidth;
    canvas.height = canvas.width * 0.5625;
  }
  
  // When canvas height reaches maximum, keep it locked and maintain 0.5625 height ratio
  if(canvas.height >= window.innerHeight){
    canvas.height = canvas.width * 0.5625;
  }
  
  // If narrowing the width, readjust both width and height accordingly
  if(canvas.width > window.innerWidth){
    canvas.width = window.innerWidth;
    canvas.height = canvas.width * 0.5625;
  }
  // Redraw the canvas with updated dimensions
  redraw();
}

function redraw() {
  ctx.fillStyle = "#FF0000";
  // Draw the canvas in center of screen using dimensions from resizeCanvas()
  ctx.fillRect((window.innerWidth - canvas.width) / 2, (window.innerHeight - canvas.height) / 2, canvas.width, canvas.height);
}

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

Checkbox fails to trigger onChange when the checked value is controlled by state management

Currently, I am working with a material-ui Table and have been in the process of implementing multi-select functionality on it. The behavior I am aiming for my multi select to exhibit is as follows: Checkboxes should only appear at the beginning of a ro ...

Trouble with JavaScript confirm's OK button functionality in Internet Explorer 11

Having trouble with the OK button functionality on a JavaScript confirm popup in IE11. For one user, clicking OK doesn't work - nothing happens. It works for most other users though. Normally, clicking OK should close the popup and trigger the event h ...

Do I have to include the sizes attribute when using w-descriptors in srcset?

After reading several articles discussing the use of srcset for device-pixel-density adjustments and art direction, I have come to a few conclusions: The State of Responsive Images in 2015 by Paddi Macdonnell srcset Part 2: The W descriptor and sizes att ...

How can you transform a nested array into a flat JavaScript map?

If we consider a JavaScript Map structured like this: [ { id: 1, name: "Foo", contents: [1,2,3], morecontents: ["a","b"], }, { id: 2, name: "Bar", c ...

Tips on obtaining a Firebase ID

Does anyone have a solution for retrieving the unique id from Firebase? I've attempted using name(), name, key, and key() without any success. Although I can view the data, I'm struggling to find a way to retrieve the id. This information is cru ...

Troubleshooting Electron Angular Application Connectivity Issues with API

While developing my ionic/angular app as an electron app, I encountered a problem when running it. After loading, I received the error message shown below: Refused to connect to 'https://xxxxxxxxxx.com/whpacking/v1/getlocations' because it violat ...

I'm receiving the error message "Fatal error: Call to a member function query() on a non-object," what could be causing this issue?

Need help with fixing an error on my private server realmeye. The error message I'm receiving is: Fatal error: Call to a member function query() on a non-object in /home/noxus/public_html/realmeye/index.php on line 112 =========================== ...

Executing a mousedown event in Ajax while simultaneously running another JavaScript function using JQuery

One issue I am facing involves a JavaScript method. There is a date slider for months that triggers an AJAX call when the month is changed (mouseup event). Within this AJAX call, there is another JavaScript code ($.blockUI) which seems to interfere with th ...

Guide on how to initialize a variable in Express.js within a conditional statement in Node.js

Trying to create a variable based on a conditional statement, but even with simple code I am unable to retrieve the new variable. Here is my code: exports.productPatch = (req, res, next) => { const id = req.params.productId; const image = req.body.p ...

Mouse hovering over the JS slider activates the sliding functionality, while removing the cursor

Hi there, I'm encountering some issues with the JS clients slider on my website. I need to pause it when the mouse is over and resume when the mouse leaves. I've double-checked the code but for some reason it's still not functioning properl ...

How to nullify the valueChanges pipe in Angular RxJS until the observable is resolved

A challenge I am facing is piping the valueChanges from a select element to trigger the appropriate API request and displaying a spinner until the response is received. Additionally, I am trying to utilize publish() and refCount() methods so that I can use ...

The AnimationRendererFactory ahead-of-time (AOT) compilation is encountering an issue where it is unable to access the property 'create

I am encountering an issue while trying to compile my Angular4 app AOT. The error message that I am stuck on is: TypeError: Cannot read property 'createRenderer' of undefined at AnimationRendererFactory.createRenderer (http://localhost:8080/cwp/ ...

Issue encountered while attempting to download npm for older versions

When utilizing nvm for windows, I typically run 'nvm install' in my VS Code terminal followed by 'nvm use'. However, I have encountered an issue where the command 'npm' is not recognized for older versions of Node. Specificall ...

Positioning two divs side by side, with two more below in the following row

I am attempting to align multiple div elements with a width relative to the screen size. However, when I try to float them next to each other, they shift to the right and display under each other. I have experimented with applying display: inline-block; a ...

Hide the div in PHP if the active variable is null

It looks like I'll need to implement Jquery for this task. I have a print button that should only appear if my array contains data. This is a simplified version of what I'm aiming to achieve: HTML <?include 'anotherpage.php'?> ...

I am currently working with an input element that is set to hidden. I am trying to change its type to text using JavaScript, but I can't seem to figure out how to do it or if it is even possible

I'm stuck trying to change the type of an input element from hidden to text using JavaScript. I can't seem to figure out if it's even possible. Can someone please help me with this? Thanks! ...

How to dynamically set a computed background image in Vue 2

I have several divs that I want to style with backgrounds from values stored in an array. My attempt to set the background overlay for each one by creating a computed property has not been successful: computed: { backgroundImage(url) { let ...

Changing a callback function into a promise in Node.js for OpenTok integration

MY FUNCTIONAL CODE (SUCCESSFULLY WORKING!) I have developed a function with callback to generate tokens and create sessions for OpenTok. This function is then exported to the application. The function //Dependencies var opentok = require('./ot&ap ...

Tips for ensuring long text wraps to the next line when it exceeds the width of the browser window

I'm struggling with CSS styles and properties. I want the text to wrap to the next line instead of overflowing off the browser screen. I've illustrated what's currently happening versus what I actually need. https://i.stack.imgur.com/mPGt8 ...

Unexpected JSON token error occurs in jQuery when valid input is provided

I encountered an error that I'm struggling to pinpoint. The issue seems to be related to the presence of the ' symbol in the JSON data. After thoroughly checking, I am positive that the PHP function json_encode is not responsible for adding this ...