setTransform和Scale以适合给定图像的Canvas [英] setTransform and Scale to fit Canvas for the given image

查看:98
本文介绍了setTransform和Scale以适合给定图像的Canvas的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在画布上有一张图片。
渲染图像后,我将画布顺时针旋转90度,然后必须缩放以适合画布。





实际结果图像如下所示:



解决方案

要将图像适合显示区域,请使用最小比例以适合高度或适合宽度。

  //画布大小
const width = 100;
常量高度= 298;

//假定图像已加载并准备绘制

//获取最小刻度以适合
var scale = Math.min(width / image.width ,height / image.height);

//您也可以缩放以使用max
// var scale = Math.max(width / image.width,height / image.height);

canvas.width =宽度;
canvas.height =高度;

// //从左上角绘制图像
ctx.setTransform(scale,0,0,scale,0,0);
ctx.drawImage(image,0,0);
ctx.setTransform(1,0,0,1,0,0); //恢复默认值



更新



Re评论



当您遇到麻烦时,我仍然不确定要做什么图像,这是一个通用功能,可以将图像旋转90度,并缩放以适合,填充和自然。 (底部代码段中的演示版本稍微冗长一些)

  // img图像绘制
//腐烂1个单位= 90度scaleType适合或填充
函数drawRotatedImage(img,rot = 1,scaleType = fit){
const w = img.naturalWidth;
const h = img.naturalHeight;

// xAxis的方向
var xAxisX = Math.cos(rot * Math.PI / 2);
var xAxisY = Math.sin(rot * Math.PI / 2);

//修改变换图像的宽度和高度以匹配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);
}否则if(scaleType === fill){
scale = Math.max(canvas.width / tw,canvas.height / th);
}

xAxisX * =比例尺;
xAxisY * =比例;

//旋转比例尺以匹配scaleType。在画布
上居中ctx.setTransform(xAxisX,xAxisY,-xAxisY,xAxisX,canvas.width / 2,canvas.height / 2);

//绘制的偏移量,因此中心位于画布中心
ctx.drawImage(img,-w / 2,-h / 2,w,h);
}

并确保以下是使用图像的经过测试的运行示例。 / p>

  const canWidth = 300; const canHeight = 400; const腐烂= 1; const scaleType = fit; const PI90 = Math.PI / 2;函数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 * =比例; xAY * =比例; ctx.setTransform(xAX,xAY,-xAY,xAX,canvas.width / 2,canvas.height / 2); ctx.drawImage(img,-w / 2,-h / 2,w,h);} //用于演示和测试的资料。与answer.const ctx = canvas.getContext( 2d)无关; // size canvascanvas.width = canWidth; canvas.height = canHeight; const img =新图片; const测试= [[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)+度CW缩放到 + scaleType.toUpperCase()+单击画布以旋转和切换比例尺; drawRotatedImage(img,rot,scaleType)}); canvas.addEventListener( click,()=> {const test = tests [tests .clicker ++%tests.length]; info.textContent =((test [0]%4)* 90)+ deg CW缩放为 + test [1] .toUpperCase(); drawRotatedImage(img,... test) });  

  body {font-family: arial black ;}画布{边框:1px纯黑色;位置:绝对;顶部:30px;左:10px; } #info {位置:绝对;顶部:2px;左:10像素;}  

 < canvas id = canvas >< / canvas>< div id = info>< / div>  


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>

这篇关于setTransform和Scale以适合给定图像的Canvas的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆