I am using canvas for a picture crop feature and I cannot figure out how to fill the empty spaces.
First, this is what I'm doing:
Canvas element:
<canvas
id="previewCanvas"
ref={previewCanvasRef}
style={{
border: '1px solid black',
objectFit: 'contain',
width: '300px',
height: '300px',
}}
/>
This is the function I use to draw the image:
const TO_RADIANS = Math.PI / 180;
export async function canvasPreview(image, canvas, crop, scale = 1, rotate = 0) {
const ctx = canvas.getContext('2d');
if (!ctx) {
throw new Error('No 2d context');
}
const scaleX = image.naturalWidth / image.width;
const scaleY = image.naturalHeight / image.height;
// devicePixelRatio slightly increases sharpness on retina devices
// at the expense of slightly slower render times and needing to
// size the image back down if you want to download/upload and be
// true to the images natural size.
const pixelRatio = window.devicePixelRatio;
// const pixelRatio = 1
canvas.width = Math.floor(crop.width * scaleX * pixelRatio);
canvas.height = Math.floor(crop.height * scaleY * pixelRatio);
ctx.scale(pixelRatio, pixelRatio);
ctx.imageSmoothingQuality = 'high';
const cropX = crop.x * scaleX;
const cropY = crop.y * scaleY;
const rotateRads = rotate * TO_RADIANS;
const centerX = image.naturalWidth / 2;
const centerY = image.naturalHeight / 2;
ctx.save();
// 5) Move the crop origin to the canvas origin (0,0)
ctx.translate(-cropX, -cropY);
// 4) Move the origin to the center of the original position
ctx.translate(centerX, centerY);
// 3) Rotate around the origin
ctx.rotate(rotateRads);
// 2) Scale the image
ctx.scale(scale, scale);
// 1) Move the center of the image to the origin (0,0)
ctx.translate(-centerX, -centerY);
ctx.drawImage(
image,
0,
0,
image.naturalWidth,
image.naturalHeight,
0,
0,
image.naturalWidth,
image.naturalHeight
);
ctx.restore();
}
This is how I see the canvas on the browser:
Now, when I convert the image to a blob, then to a file object, I get an image like this :
What I expect to happen is to get an image like this: (exactly like in the preview)
What am I doing wrong ?
you can follow the StackOverflow link: https://stackoverflow.com/questions/15457619/html-canvas-drawing-grid-below-a-plot
Related
I want to use a canvas thats max 1000px x 1000px. But if the screen is smaller, or the window becomes smaller to automatically adjust the width/height based on that while maintaining original aspect ratio. example: If width=500px then canvas = 500x500, not 500x1000. if height = 100, then canvas = 100x100. I dont mind using javascript, css, html to do this. thank you.
Scale to fit with fixed aspect ratio.
You can use CanvasRenderingContext2D.setTransform to scale and position the transform to fit and center content.
You will need a reference resolution which defines the original coordinate scale 1 and the aspect. Eg...
const refRes = {width: 1000, height: 1000};
Scale to fit
Then you can calculate the scale and origin to fit and center content to a given sized canvas. This is done by using the minimum scaled dimension to scale the content. Eg...
// Get the scale to fit content to the canvas
const scale = Math.min(canvas.width / refRes.width, canvas.height / refRes.height);
// set the origin so that the scaled content is centered on the canvas
const origin = {
x: (canvas.width - refRes.width * scale) / 2,
y: (canvas.height - refRes.height * scale) / 2
};
// Set the transform to scale and center on canvas
ctx.setTransform(scale, 0, 0, scale, origin.x, origin.y);
// Then render your content using the original coordinates.
ctx.fillRect(0, 0, 1000, 1000); // will fit any sized canvas
As this maintains the aspect there may be unused pixels left and right or above and below depending on the canvas aspect.
Scale to fill
You can scale to fill, which will crop the content but ensures that all pixels are use. Just use the maximum scaled dimension. Eg...
// Use max res to scale to fill
const scale = Math.max(canvas.width / refRes.width, canvas.height / refRes.height);
Demo
Demo shows content scaled to fit a canvas that has its size changed randomly. The content is rendered in the original coordinate systems and the 2D transform is used to scale to fit and center.
requestAnimationFrame(mainLoop);
const ctx = canvas.getContext("2d");
const size = 1000;
Math.TAU = Math.PI * 2;
Math.randI = (m, M) => Math.random() * (M - m) + m | 0; // for unsigned int32
Math.nearZero = val => Math.abs(val) < 1e-3;
const refRes = {width: size, height: size};
renderContent();
// State for canvas size changes
var xRes = canvas.width, yRes = canvas.height;
var xResC = xRes, yResC = yRes; // current resolution
var xResD = 0, yResD = 0; // resolution delta change
const rate = 0.2; // rate of canvas size change
// WARNING there is no bounds checking for canvas size.
// If rate < 0 || rate > 0.5 you MUST check that canvas size
// is safe before setting its width and height
function scaleToFit() {
const scale = Math.min(canvas.width / refRes.width, canvas.height / refRes.height);
ctx.setTransform(
scale, 0, 0, scale,
(canvas.width - refRes.width * scale) / 2,
(canvas.height - refRes.height * scale) / 2
);
}
function mainLoop() {
xResC += (xResD = (xResD += (xRes - xResC) * rate) * rate);
yResC += (yResD = (yResD += (yRes - yResC) * rate) * rate);
const w = xResC | 0;
const h = yResC | 0;
if (w !== canvas.width || h !== canvas.height) {
canvas.width = w;
canvas.height = h;
renderContent();
}
if(Math.nearZero(xResD) && Math.nearZero(yResD)) {
xRes = Math.randI(30, 300);
yRes = Math.randI(30, 200);
}
requestAnimationFrame(mainLoop);
}
function renderContent() {
scaleToFit();
ctx.fillStyle = "#Faa";
ctx.fillRect(0,0,size,size);
ctx.fillStyle = "#8aF";
ctx.beginPath();
ctx.arc(size / 2, size / 2, size / 2 - 4, 0, Math.TAU);
ctx.fill();
ctx.fillStyle = "#FF8";
ctx.fillRect(
(size - size * Math.SQRT1_2) / 2, (size - size * Math.SQRT1_2) / 2,
size * Math.SQRT1_2, size * Math.SQRT1_2
);
ctx.lineWidth = 10;
ctx.beginPath();
ctx.arc(size / 2, size / 2, size / 2 - 4, 0, Math.TAU);
ctx.rect(
(size - size * Math.SQRT1_2) / 2, (size - size * Math.SQRT1_2) / 2,
size * Math.SQRT1_2, size * Math.SQRT1_2
);
ctx.stroke();
}
canvas {
border: 1px solid black;
}
<canvas id="canvas"></canvas>
I have an image on Canvas.
After rendering an image, I rotate the canvas to 90 degrees clockwise and then have to scale to fit the canvas.
Scaling an image to fit on canvas
Resize image and rotate canvas 90 degrees
there is so many solutions available but unfortunately none of them worked for me yet
This is what I have right now.
width = 300; // after rotation
height = 400; // after rotation
var scale = width / img.height; // how much to scale the image to fit
console.log(scale);
canvas.width = width;
canvas.height = height;
ctx.setTransform(
0, scale, // x axis down the screen
-scale, 0, // y axis across the screen from right to left
width, // x origin is on the right side of the canvas
0 // y origin is at the top
);
ctx.drawImage(img, 0, 0);
ctx.setTransform(1, 0, 0, 1, 0, 0); // restore default
Currently, canvas is rotating fine but image is not fitting or scaling properly according to canvas width and height.
Original image is large, I want to scale it to fit 300x400 on canvas.
Original Image -
Actual result image looks like this which is not scaling full image -
To fit an image to a display area, use the min scale to fit height or fit width.
// size of canvas
const width = 100;
const height = 298;
// image is assumed loaded and ready to be drawn
// Get min scale to fit
var scale = Math.min(width / image.width , height / image.height);
// you can also scale to fill using max
// var scale = Math.max(width / image.width , height / image.height);
canvas.width = width;
canvas.height = height;
// // draw image from top left corner
ctx.setTransform(scale, 0, 0, scale, 0, 0);
ctx.drawImage(image, 0, 0);
ctx.setTransform(1, 0, 0, 1, 0, 0); // restore default
Update
Re comment
As you are having trouble, and I am still not sure what you what the image to do, here is a general purpose function to rotate image in 90 deg steps, and scales to fit, fill, and natural. (Demo version in bottom snippet a little less verbose)
// img image to draw
// rot 1 unit = 90 deg. scaleType fit or fill
function drawRotatedImage(img, rot = 1, scaleType = "fit") {
const w = img.naturalWidth;
const h = img.naturalHeight;
// direction of xAxis
var xAxisX = Math.cos(rot * Math.PI / 2);
var xAxisY = Math.sin(rot * Math.PI / 2);
// modified transform image width and height to match the xAxis
const tw = Math.abs(w * xAxisX - h * xAxisY);
const th = Math.abs(w * xAxisY + h * xAxisX);
var scale = 1;
if (scaleType === "fit") {
scale = Math.min(canvas.width / tw, canvas.height / th);
} else if (scaleType === "fill") {
scale = Math.max(canvas.width / tw, canvas.height / th);
}
xAxisX *= scale;
xAxisY *= scale;
// Rotate scale to match scaleType . Center on canvas
ctx.setTransform(xAxisX, xAxisY, -xAxisY, xAxisX, canvas.width / 2, canvas.height / 2);
// Image drawn offset so center is at canvas center
ctx.drawImage(img, -w / 2, -h / 2, w, h);
}
And to make sure the following is a tested runing example using your image.
const canWidth = 300;
const canHeight = 400;
const rot = 1;
const scaleType = "fit";
const PI90 = Math.PI / 2;
function drawRotatedImage(img, rot, scale) {
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
const w = img.naturalWidth, h = img.naturalHeight;
var xAX = Math.cos(rot *= PI90 ), xAY = Math.sin(rot);
const tw = Math.abs(w * xAX - h * xAY);
const th = Math.abs(w * xAY + h * xAX);
scale = Math[scale === "fit" ? "min" : "max" ](canvas.width / tw, canvas.height / th);
xAX *= scale;
xAY *= scale;
ctx.setTransform(xAX, xAY, -xAY, xAX, canvas.width / 2, canvas.height / 2);
ctx.drawImage(img, -w / 2, -h / 2, w, h);
}
// Stuff for demo and test. unrelated to answer.
const ctx = canvas.getContext("2d");
// size canvas
canvas.width = canWidth;
canvas.height = canHeight;
const img = new Image;
const tests = [[0,"fit"], [1,"fit"], [2,"fit"], [3,"fit"],[0,"fill"], [1,"fill"], [2,"fill"], [3,"fill"]];
tests.clicker = 0;
img.src = "https://i.stack.imgur.com/SQmuv.jpg";
img.addEventListener("load", () => {
info.textContent = ((rot % 4) * 90) + "deg CW scaled to " + scaleType.toUpperCase() + " click canvas to rotate and switch scales";
drawRotatedImage(img, rot, scaleType)
});
canvas.addEventListener("click",() => {
const test = tests[tests.clicker++ % tests.length];
info.textContent = ((test[0] % 4) * 90) + "deg CW scaled to " + test[1].toUpperCase();
drawRotatedImage(img, ...test)
});
body {
font-family: "arial black";
}
canvas {
border: 1px solid black;
position: absolute;
top: 30px;
left: 10px;
}
#info {
position: absolute;
top: 2px;
left: 10px;
}
<canvas id="canvas"></canvas>
<div id="info"></div>
I want to have an image follow the mouse around the canvas, which is fairly easy, but the catch is that I want my canvas to change with screen resolution (it is set using CSS to be 70vw).
When the resolution decreases and the window becomes smaller this means that using a normal method of using clientX doesn't work.
My code so far is this:
var mouseX = e.clientX/document.documentElement.clientWidth * 1920;
var mouseY = e.clientY/document.documentElement.clientHeight * 943;
This tries to convert the users clientX into the value it would be on a 1920x1080 monitor.
However, this isn't really accurate and doesn't work very well on even 1920x1080 monitors. Any help would be appreciated.
You can't scale the canvas using CSS in the way that you think. A canvas is basically a more advanced image. Scaling the canvas via CSS just stretches the canvas the same way an image would stretch. To change the canvas height and width, you need to change it's height and width attributes in the tag or via code. This will physically change the canvas to the size that you want without scaling and/or stretching.
That being said, we can use this to watch for window size changes and resize the canvas when the window changes.
window.addEventListener('resize', e => {
canvas.width = window.innerWidth
canvas.height = window.innerHeight
})
With some basic math, we can calculate what a 70% width would be, it would be done like this
window.addEventListener('resize', e => {
canvas.width = window.innerWidth * 0.7
canvas.height = window.innerHeight
})
The next thing we need to do is get the local position of the mouse on the canvas, which can be done using mousePosition - canvasOffset like this
let x = e.clientX - canvas.offsetLeft
let y = e.clientY - canvas.offsetTop
When all is said and done, we end up with something like this (To see it in action press run then click on Full Page and you will see the canvas resize):
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
// Set the inital height and width of the canvas
canvas.width = window.innerWidth
canvas.height = window.innerHeight
canvas.addEventListener('mousemove', e => {
ctx.clearRect(0, 0, canvas.width, canvas.height)
// Get the local x/y coordinates of the mouse on the canvas
let x = e.clientX - canvas.offsetLeft
let y = e.clientY - canvas.offsetTop
// Draw a dot where the mouse is
ctx.beginPath();
ctx.arc(x, y, 10, 0, 2 * Math.PI, false);
ctx.fillStyle = 'white';
ctx.fill();
})
// Update the height and width when the window size changes
window.addEventListener('resize', e => {
canvas.width = window.innerWidth
canvas.height = window.innerHeight
})
body {
padding: 0;
margin: 0;
}
canvas {
background-color: black;
display: block;
}
<canvas></canvas>
In this example below, we use a canvas that is 70% the width and height of the screen and center it with CSS. However, we never touch the height/width with css because it will mess up the canvas' coordinate system. This part is done with JavaScript.
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
// Set the inital height and width of the canvas
canvas.width = window.innerWidth * 0.7
canvas.height = window.innerHeight * 0.7
canvas.addEventListener('mousemove', e => {
ctx.clearRect(0, 0, canvas.width, canvas.height)
// Get the local x/y coordinates of the mouse on the canvas
let x = e.clientX - canvas.offsetLeft
let y = e.clientY - canvas.offsetTop
// Draw a dot where the mouse is
ctx.beginPath();
ctx.arc(x, y, 10, 0, 2 * Math.PI, false);
ctx.fillStyle = 'white';
ctx.fill();
})
// Update the height and width when the window size changes
window.addEventListener('resize', e => {
canvas.width = window.innerWidth * 0.7
canvas.height = window.innerHeight * 0.7
})
body {
padding: 0;
margin: 0;
}
canvas {
background-color: black;
display: block;
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
margin: auto;
}
<canvas></canvas>
I took my snippet from my answer to create a full screen canvas.
I added this for mouse movement:
let User = { x: 0, y: 0 };
//controles if the mouse is moving
window.addEventListener(
"mousemove",
e => {
User.x = e.clientX;
User.y = e.clientY;
},
false
);
Uncomment: cvs.ctx.drawImage(image, User.x, User.y); in the ShowImage() function to draw an image at the mouse x and y position.
Mind to replace the path of the image source: image.src = "Your/Path/To/Image.png";
/**
* #author RensvWalstijn. GitHub: https://github.com/RensvWalstijn
* Sets the canvas properties.
* #param {object} Cvs Give the html canvas Id.
* #param {boolean} Fullscreen Change the canvas fullscreen default false.
* #param {string} Dimension Change the canvas dimension default "2d".
* #return {object}
*/
function NewCanvas(cvs, fullscreen, dimension) {
if (!dimension) dimension = "2d";
var ctx = cvs.getContext(dimension);
if (fullscreen) {
cvs.style.position = "fixed";
cvs.style.left = cvs.x = 0;
cvs.style.top = cvs.y = 0;
} else {
var rect = cvs.getBoundingClientRect();
cvs.x = rect.left;
cvs.y = rect.top;
}
cvs.ctx = ctx;
cvs.dimension = dimension;
cvs.fullscreen = fullscreen;
return cvs;
}
/**
* #author RensvWalstijn. GitHub: https://github.com/RensvWalstijn
* Updates the canvas width and hight.
* #param {object} Cvs NewCanvas() object.
* #param {boolean} Clear Change the canvas clear default true.
*/
function UpdateCvs(cvs) {
if (cvs.fullscreen) {
//if the width is not the same resize the canvas width
if (window.innerWidth != cvs.width) {
cvs.width = window.innerWidth;
}
//if the height is not the same resize the canvas height
if (window.innerHeight != cvs.height) {
cvs.height = window.innerHeight;
}
} else {
let rect = cvs.getBoundingClientRect();
cvs.x = rect.left;
cvs.y = rect.top;
}
}
function ClearCvs(cvs) {
if (cvs.dimension == "2d")
// set fillRect to clearRect to clear all of the canvas
// fillRect is used here to show the full canvas
cvs.ctx.fillRect(0, 0, cvs.width, cvs.height);
}
/**
* #author RensvWalstijn. GitHub: https://github.com/RensvWalstijn
* get html element by id.
* #param {string} id give the html element id.
* #return {object} document.getElementById(id);
*/
function GetId(id) { return document.getElementById(id) }
// To create your canvas object.
var canvas = NewCanvas(GetId("yourCanvasId"), true);
// If you want to update your canvas size use this:
window.addEventListener("resize", function() {
UpdateCvs(canvas);
});
let User = { x: 0, y: 0 };
//controles if the mouse is moving
window.addEventListener(
"mousemove",
e => {
User.x = e.clientX;
User.y = e.clientY;
},
false
);
// Set it to current width
UpdateCvs(canvas);
ClearCvs(canvas);
// create an image
let image = new Image();
image.src = "Your/Path/To/Image.png";
function ShowImage(cvs) {
// Use this line to draw your image.
// cvs.ctx.drawImage(image, User.x, User.y);
// Shows where your image will be drawn.
cvs.ctx.clearRect(User.x, User.y, 100, 100);
}
function Update() {
ClearCvs(canvas);
ShowImage(canvas);
// keeps it looping
window.requestAnimationFrame(Update)
}
// Init the loop
Update();
<canvas id="yourCanvasId"></canvas>
There's quite a few topics here about rotating images with canvas on js. I read most of them, and couldn't figure out a solution for my problem.
I'm receiving an image (from an upload component) of whatever resolution. I'm resizing it to 1024x768 like:
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
if (img.width >= img.height) {
canvas.width = 1024;
canvas.height = 768;
} else {
canvas.width = 768;
canvas.height = 1024;
}
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
It works fine.
But on Safari/iOs, when I take a picture and upload, the image has ALWAYS a higher width value than height, so the code above doesn't work.
So I decided to use exif-js to detect the image's orientation. When the Orientation attribute is higher than 4, I need to rotate the image 90 degrees, and swap height and width values.
I tried to rotate the image like this:
canvas.width = 768; // swapping values
canvas.height = 1024;
ctx.translate(canvas.width/2, canvas.height/2); // translate to center
ctx.rotate(Math.PI/2); // rotate 90 degrees
ctx.drawImage(img, -img.width/2,-img.height/2); // not sure of the dx and dy values here...
The image is rotated. But it has taken just a small portion of the original image to display on the canvas, so it feels "zoomed in"... it seems that I'm using the wrong values on the drawImage method, but not sure how to fix.
How can I fix this rotation with fixed height and width values?
To rotate 90 deg clockwise on a new canvas.
const canvas = document.createElement("canvas");
canvas.width = image.height;
canvas.height = image.width;
const ctx = canvas.getContext("2d");
ctx.setTransform(
0,1, // x axis down the screen
-1,0, // y axis across the screen from right to left
image.height, // x origin is on the right side of the canvas
0 // y origin is at the top
);
ctx.drawImage(image,0,0);
ctx.setTransform(1,0,0,1,0,0); // restore default
If you need to scale the image to fit a size (assuming image will be rotated)
const width = 1024; // after rotation
const height = 768; // after rotation
const scale = width / image.height; // how much to scale the image to fit
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
ctx.setTransform(
0,scale, // x axis down the screen
-scale,0, // y axis across the screen from right to left
width, // x origin is on the right side of the canvas
0 // y origin is at the top
);
ctx.drawImage(image,0,0);
ctx.setTransform(1,0,0,1,0,0); // restore default
I have a form that allows a user to upload an image.
Once the image is loaded, we perform some scaling on it in order to reduce its filesize before we pass it back to the server.
To do this, we place it on the canvas and manipulate it there.
This code will render the scaled image on the canvas, with the canvas of size 320 x 240px:
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
... where canvas.width and canvas.height is the image height and width x a scaling factor based on the size of the original image.
But when I go to use the code:
ctx.drawImage(img, 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height
... I only get part of the image on the canvas, in this case the top left corner. I need the whole image 'scaled' to fit on the canvas, despite the actual image size being larger than the 320x240 canvas size.
So for the code above, the width and heights are 1142x856, as that is the final image size. I need to maintain that size to pass beck to the server when the form is submitted, but only want a smaller view of it to appear in the canvas for the user.
What am I missing here? Can anyone point me in the right direction please?
You made the error, for the second call, to set the size of source to the size of the target.
Anyway i bet that you want the same aspect ratio for the scaled image, so you need to compute it :
var hRatio = canvas.width / img.width ;
var vRatio = canvas.height / img.height ;
var ratio = Math.min ( hRatio, vRatio );
ctx.drawImage(img, 0,0, img.width, img.height, 0,0,img.width*ratio, img.height*ratio);
i also suppose you want to center the image, so the code would be :
function drawImageScaled(img, ctx) {
var canvas = ctx.canvas ;
var hRatio = canvas.width / img.width ;
var vRatio = canvas.height / img.height ;
var ratio = Math.min ( hRatio, vRatio );
var centerShift_x = ( canvas.width - img.width*ratio ) / 2;
var centerShift_y = ( canvas.height - img.height*ratio ) / 2;
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.drawImage(img, 0,0, img.width, img.height,
centerShift_x,centerShift_y,img.width*ratio, img.height*ratio);
}
you can see it in a jsbin here :
http://jsbin.com/funewofu/1/edit?js,output
Provide the source image (img) size as the first rectangle:
ctx.drawImage(img, 0, 0, img.width, img.height, // source rectangle
0, 0, canvas.width, canvas.height); // destination rectangle
The second rectangle will be the destination size (what source rectangle will be scaled to).
Update 2016/6: For aspect ratio and positioning (ala CSS' "cover" method), check out:
Simulation background-size: cover in canvas
I guess that you want the image to be scaled to a smaller size, without losing the ratio of the dimensions. I have a solution.
var ratio = image.naturalWidth / image.naturalHeight;
var width = canvas.width;
var height = width / ratio;
ctx.drawImage(image, 0, 0, width, height);
the ratio will be maintained. And the image drawn on the canvas will be of the same ratio. you can use the if loop if the height of the image is long, you can replace the canvas.width to some other width
You can call ctx.scale() before calling ctx.drawImage:
var factor = Math.min ( canvas.width / img.width, canvas.height / img.height );
ctx.scale(factor, factor);
ctx.drawImage(img, 0, 0);
ctx.scale(1 / factor, 1 / factor);
This should preserve the aspect ratio.
HTML:
<div id="root"></div>
JavaScript:
const images = [
'https://cdn.pixabay.com/photo/2022/07/25/15/18/cat-7344042_960_720.jpg',
'https://cdn.pixabay.com/photo/2022/06/27/08/37/monk-7287041_960_720.jpg',
'https://cdn.pixabay.com/photo/2022/07/18/19/57/dog-7330712_960_720.jpg',
'https://cdn.pixabay.com/photo/2022/05/22/18/25/spain-7214284_960_720.jpg',
];
const root = document.getElementById('root');
const image = new Image();
image.crossOrigin = 'anonumys';
image.src = images[3];
const canvas = document.createElement('canvas');
canvas.classList.add('track');
canvas.width = 600;
canvas.height = 400;
const ctx = canvas.getContext('2d');
const meta = {
ratio: image.width / image.height,
width: 0,
height: 0,
offsetX: 0,
offsetY: 0,
};
if (meta.ratio >= 1) {
meta.width = canvas.width > image.width ? image.width : canvas.width;
meta.height = meta.width / meta.ratio;
} else {
meta.height = canvas.height > image.height ? image.height : canvas.height;
meta.width = meta.height * meta.ratio;
}
meta.offsetX = canvas.width > meta.width ? (canvas.width - meta.width) / 2 : 0;
meta.offsetY = canvas.height > meta.height ? (canvas.height - meta.height) / 2 : 0;
image.addEventListener('load', () => {
ctx.drawImage(image, meta.offsetX, meta.offsetY, meta.width, meta.height);
root.append(canvas);
});
console.log(meta);