Adjust the size of the canvas element based on changes to its parent's dimensions

I am working with an application that includes a div containing a canvas element to display an image. Additionally, there is a sidebar that can be hidden with the click of a button, causing all other elements to resize and adjust to the remaining space.

While this resizing behavior works well for elements with width/height set as percentages, it does not seem to apply to the canvas element itself.

The div structure I currently have is as follows:

<div id="background-img" class="image-div"></div>

.image-div {
  height: inherit;
  width: 100%;
  margin-top: 25px;
  position: absolute;
}

The initial height of the div is 305px but changes to 375px when the sidebar is hidden.

Below is the code used to create the canvas:

const imgDiv = document.getElementById('background-img');
if (imgDiv) {
  const blob = new Blob([svg], { type: 'image/svg+xml' });
  const url = URL.createObjectURL(blob);

  const canvas = document.createElement('canvas');
  canvas.className = 'canvas-background';
  canvas.id = 'canvas-id';
  const ctx = canvas.getContext('2d');

  canvas.width = imgDiv.clientWidth;
  canvas.height = imgDiv.clientHeight;

  const img = new Image();
  img.onload = function() {
    ctx.drawImage(img, 0, 0);
  };
  img.src = url;
  imgDiv.appendChild(canvas);
}

No additional CSS styles are applied to the canvas elsewhere in the code.

I'm seeking a way to enable the canvas to automatically resize itself whenever its parent's width and height change. This should include functionality for zooming in/out on the page, similar to how it behaves on Chrome with divs or img elements. Any guidance on achieving this would be greatly appreciated.

Answer №1

Currently, there isn't a straightforward solution to achieve this task. One might instinctively seek a resize event on an element, but such events are typically applicable only to the window, as elaborated in this MDN article.

After conducting thorough research and exploring various discussions, I have identified a few options for your consideration.

Continuous Loop Approach

You can render the image within a recursive function that continuously monitors the dimensions of the imgDiv as it draws itself.

CSS:

canvas {
    width: 100%;
    height: 100%;
}

JS:

function draw(ctx, imgDiv, img) {
    ctx.canvas.width = imgDiv.offsetWidth;
    ctx.canvas.height = imgDiv.offsetheight;
    ctx.drawImage(img, 0, 0);
    requestAnimationFrame(() => {
        draw(ctx, imgDiv, img);
    });
}

img.onload = function() {
    draw(ctx, imgDiv, img);
};

While this approach constantly processes updates, it may impact performance due to its resource-intensive nature. The use of requestAnimationFrame optimizes performance by syncing with the display's refresh rate, typically around 60 times per second.

ResizeObserver (Experimental)

This method introduces the novel concept of ResizeObserver, similar to other observer APIs like IntersectionObserver, PerformanceObserver, and MutationObserver. It tracks resizing changes in elements and triggers callbacks accordingly.

Implementation example:

const observer = new ResizeObserver(entries => {
    entries.forEach(entry => {
        // Update the canvas dimensions.
    });
});

// Observe the resizing of the image-div.
observer.observe(imgDiv);

Due to its experimental status, caution is advised when considering this approach, despite its applicability to your scenario. For details on browser support and usage guidelines, refer to resources such as Caniuse and Alligator.io.

Utilize the resize Event on window

This option primarily focuses on window or document width adjustments, requiring additional modifications for scenarios like sidebar expansions or contractions.

window.addEventListener('resize', (event) => {
    requestAnimationFrame(() => {
        // Update the canvas dimensions.
    });
});

For optimal performance, incorporating requestAnimationFrame here is crucial, considering that the resize event occurs for every pixel adjustment and may hinder efficiency.

Edit Note:

Although Artyomska has apparently resolved the issue, I am sharing my findings in case this discussion proves beneficial for future inquiries.

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

Guide on Adding Tawk.to Widget to Your Next.JS Website

I followed the instructions on their @tawk.to/tawk-messenger-react plugin documentation, but I am still facing issues. I created a component named /components/Chat.js import TawkMessengerReact from "@tawk.to/tawk-messenger-react"; export defaul ...

Utilizing SVG within Sproutcore allows for seamless access to DOM nodes and the ability to effortlessly bind Sproutcore events directly to the DOM

Exploring Sproutcore, I am delving into the world of SVG (Standard Vector Graphics) integration within the app. The goal is to utilize a canvas for drawing elements like lines, boxes, and images, all of which SVG offers. My approach involved incorporating ...

Can any function be used to define the path in ExpressJS when setting up GET routes?

I am currently working on developing a web application using node.js. However, I have encountered an issue when trying to use special characters in my navigation path, resulting in the error message "Cannot get /contest". In order to resolve this problem ...

The mouse movement event will not be triggered for every frame when a keyboard event occurs

When the mouse is moving in a browser, ideally the mousemove event should fire every frame. However, if a key is pressed or released (or repeated), the mousemove event stops firing for a frame or two. To test this behavior, you can use the code snippet bel ...

What is the best way to pass a variable in an AJAX function call when making a POST request?

I am facing an issue with sending a variable through an ajax function. The scenario is as follows: <a href="next.php" onclick="sendajax()">reload</a> I need to send this variable via the POST method in my php page: <script> fu ...

Tips on extracting code differences from code inspector

Utilizing the Chrome code inspector is extremely valuable, but I often find it challenging to track the modifications made to CSS and HTML live. This becomes particularly cumbersome when there are multiple tags being modified. Are there any Chromium exten ...

Is there a way for me to access the user's gender and birthday following their login using their Google account details?

I have successfully implemented a Google sign-in button in my Angular application following the example provided in Display the Sign In With Google button: <div id="g_id_onload" class="mt-3" data-client_id="XXXXXXXXXXXX-XX ...

Reactjs Invariant Violation caused by the npm package (react-loader)

I'm currently attempting to integrate react-loader into my react component. This is the code snippet I'm using: /** @jsx React.DOM */ var Loader = require('react-loader'); var DisplayController = React.createClass({ // etc ...

The functionality of returning false on ajax response does not effectively prevent the form from submitting

I'm encountering an issue where the return false statement doesn't seem to work when using an AJAX call. The form is still getting submitted successfully despite trying to prevent it with a conditional check on the response from the AJAX request. ...

Having trouble retrieving data from the MongoDB database using Node.js

Having trouble with data retrieval from MongoDb Successfully connected to MongoDb, but when using the find command, it should return an empty collection, yet nothing is being returned. What could be causing this issue and how can it be monitored through ...

[.TextureUnitWarning] ALERT: Unit 1 is lacking a texture binding for rendering test.html:1

I've been attempting to incorporate texture into my project. var bumptexture = THREE.ImageUtils.loadTexture('grid.jpg'); var normaltexture = THREE.ImageUtils.loadTexture("normal.jpg"); var diffusetexture = THREE.ImageUtils.loadTexture ...

A detailed guide on sending Joomla form information to a controller function using Ajax communication

Within my Joomla 3.3 form, I have integrated an ajax script aimed at dynamically updating some form fields. The core of the script looks like this: formdata = new FormData(); jQuery.ajax({ type: "POST", dataType: "json", timeout: 6000, url: "index.php?opt ...

Using regular expressions, you can conveniently extract text that is contained within paragraph tags

I attempted to use RegExp in JavaScript to extract text between paragraph tags, but unfortunately it isn't working... Here is my pattern: <p>(.*?)</p> The text I am trying to extract from is: <p> My content. </p> <img sr ...

In Pure JavaScript, an HTML element is added every time the click event is triggered

Hey everyone, I'm facing a small issue and I could use some help fixing it. I need to implement an onclick event that adds HTML code every time it's clicked. I am hesitant to use innerHTML due to its potential risks. Here is the code snippet: bu ...

What is the best way to utilize bilinear color interpolation with JavaScript?

I'm grappling with the concept of bilinear interpolation, wondering if there's a more efficient method than what I've attempted below using the Culori library's interpolate() function. My uncertainty lies in whether it's correct t ...

Anticipating the arrival of an external JavaScript file in the child component

I am facing an issue with my parent component that dynamically loads an external js file (similar to what is explained here). The child component needs a variable inside the js file, but it throws an error every time the page is loaded because the child c ...

When running grunt-bower, I am encountering an error stating that _.object is not a function

I am attempting to execute the grunt-bower task in order to copy all of my bower components. Encountered an error while running "bower:dev" (bower) task TypeError: _.object is not a function at Object.exports.getDests (/Users/wonoh/cocApp/node_modules/g ...

Utilizing Navigate and useState for Conditional Routing in React

Looking for assistance with a React app. Here's the code snippet: function App() { const [walletConnected, setWalletConnected] = useState("") async function checkConnection() { const accounts = await window.ethereum.request({ method: 'e ...

Using Jquery .ajax to Populate Select Dropdown with JSON Data

I have put in a lot of effort but I'm not seeing any results. My JSON data, created with PHP, looks like this (with the header sent before the data): {"users":[ {"id":"3256","name":"Azad Kashmir"}, {"id":"3257","name":"Balochistan"}, {"id":"3258","na ...

Alert: Unauthorized hook call and Exception: Cannot access properties of null (reading 'useState')

I am currently working on a project using ASP.NET Core with React. To bundle my code, I have opted to use Webpack 5. Within the index.jsx file, I have the following code: import { useState } from "react"; function App() { const [value, setV ...