我在画布上有一张图片。 渲染图像后,我将画布顺时针旋转90度,然后必须缩放以适合画布。
Scaling an image to fit on canvas Resize image and rotate canvas 90 degrees
有很多可用的解决方案,但不幸的是,它们中没有一个对我有用
这就是我现在所拥有的。
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
当前,画布旋转得很好,但是根据画布的宽度和高度,图像无法正确拟合或缩放。 原始图片很大,我想缩放它以适合画布上的300x400。
实际结果图片看起来像这样,无法缩放完整图片-
答案 0 :(得分:2)
要将图像适合显示区域,请使用最小比例以适合高度或宽度。
// 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
评论
当您遇到麻烦时,我仍然不确定要做什么图像,这是一个通用功能,可以使图像以90度为步长旋转,并缩放以适合,填充和自然。 (底部代码段中的演示版本略为冗长)
// 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);
}
并确保以下是使用图像的经过测试的运行示例。
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>