繁体   English   中英

缩放图像以适应 canvas

[英]Scaling an image to fit on canvas

我有一个允许用户上传图像的表单。

加载图像后,我们对其进行一些缩放,以便在将其传递回服务器之前减小其文件大小。

为此,我们将其放置在 canvas 上并在那里进行操作。

此代码将在 canvas 上渲染缩放图像,canvas 的大小为 320 x 240px:

ctx.drawImage(img, 0, 0, canvas.width, canvas.height)

... 其中 canvas.width 和 canvas.height 是基于原始图像大小的图像高度和宽度 xa 缩放因子。

但是当我 go 使用代码时:

ctx.drawImage(img, 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height

...我只得到 canvas 上的部分图像,在这种情况下是左上角。 尽管实际图像尺寸大于 320x240 canvas 尺寸,但我需要将整个图像“缩放”以适合 canvas。

所以对于上面的代码,宽度和高度都是 1142x856,因为这是最终的图像尺寸。 在提交表单时,我需要保持该大小以传递给服务器,但只希望在 canvas 中为用户显示一个较小的视图。

我在这里想念什么? 谁能指出我正确的方向?

提前谢谢了。

您在第二次调用中犯了错误,将源的大小设置为目标的大小。
无论如何,我敢打赌,您希望缩放后的图像具有相同的纵横比,因此您需要计算它:

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);

我还假设您想使图像居中,因此代码为:

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);  
}

您可以在此处的 jsbin 中看到它: http ://jsbin.com/funewofu/1/edit?js,output

提供源图像 (img) 大小作为第一个矩形:

ctx.drawImage(img, 0, 0, img.width,    img.height,     // source rectangle
                   0, 0, canvas.width, canvas.height); // destination rectangle

第二个矩形将是目标大小(将缩放到什么源矩形)。

2016/6 更新:对于纵横比和定位(ala CSS 的“覆盖”方法),请查看:
模拟背景尺寸:覆盖在画布中

我猜你希望图像被缩放到更小的尺寸,而不会丢失尺寸的比例。 我有一个解决方案。

var ratio = image.naturalWidth / image.naturalHeight;
var width = canvas.width;
var height = width / ratio;
ctx.drawImage(image, 0, 0, width, height);

该比例将保持不变。 在画布上绘制的图像将具有相同的比例。 如果图像的高度很长,您可以使用if循环,您可以将canvas.width替换为其他宽度

您可以在调用 ctx.drawImage 之前调用ctx.drawImage ctx.scale()

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);

这应该保持纵横比。

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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM