typescript/javascript在画布上绘制矩形,给定相对于原始图像的平移坐标



在屏幕上,我有一个img元素,它有一个css转换:rotate(degree(,其中degree可以是0、90、180、270,但实际上它可以是任何度。

也就是说,原始图像实际上并没有旋转,只是被转换为看起来旋转了。

考虑到这一点,用户能够在TRANSFORMED图像上选择区域,并且接收到的输出将是相对于TRANSFORMED的图像的裁剪区域的细节,而不是原始的。

裁剪区域的输出将包括以下信息:

  • nativeImageWidth
  • nativeImageHeight
  • 位置X
  • 位置Y
  • 宽度
  • 高度
  • 角度(如果在选择裁剪区域之前没有进行旋转,则为0(

我需要做的是在用户选择的区域绘制一个矩形高亮显示,然后用高亮显示的选定区域的新src数据重新设置原始显示的img元素。

我认为最好的方法是将给定的裁剪区域的位置/宽度/高度转换为原始未旋转图像所需的大小,然后使用这些转换后的尺寸简单地将Rect填充到该区域,然后重新设置context.toDataURL 显示的img

我只是不确定坐标的平移公式会是什么样子。

一张图片来解释我上面所说的:图片说明

我确实环顾四周,但似乎找不到像我要求的那样的解决方案。我在其他帖子中发现的大多数内容都涉及到使用context.rerotate((和context.translate((,但我也无法让它像那样工作

本质上,我要找的是这样的东西:

function getTranslatedRect(x, y, w, h, angle, nativeImageWidth, nativeImageHeight) {
let newX = x;
let newY = y;
let newWidth = w;
let newHeight = h;
let newCanvasWidth = nativeImageWidth;
let newCanvasHeight = nativeImageHeight;

// do cool math stuff that i am far to un-educated to do (sin? cos? :D)....

newX = 35;
newY = 320;
newWidth = 65;
newHeight = 120;

return {
newX, newY, newWidth, newHeight, newCanvasWidth, newCanvasHeight
};
}
let img = document.getElementById('translatedImage');
let translatedRect = getTranslatedRect(60, 35, 120, 65, 90, 350, 500);
let canvas = document.createElement('canvas');
canvas.width = translatedRect.newCanvasWidth;
canvas.height = translatedRect.newCanvasHeight;
let ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'rgba(255, 165, 0, 1)';
ctx.fillRect(translatedRect.newX, translatedRect.newY, translatedRect.newWidth, translatedRect.newHeight);
img.src = canvas.toDataURL('image/jpg', 1.0);
.canvas {
width: 500px;
height: 500px;
text-align: center;
}
.rotated {
transform: rotate(90deg);
}
translated image with "user highlighted area"
<div class="canvas">
<img id="translatedImage" class="rotated" src="https://i.ibb.co/fNDs6qQ/Untitled.png" crossorigin="anonymous">
</div>
original image
<div class="canvas">

<img id="originalImage" src="https://i.ibb.co/fNDs6qQ/Untitled.png" crossorigin="anonymous">  
</div>

建议您利用内置的CSS矩阵运算来执行计算。为此,下面的代码片段是通过Javascript使用CSS转换的一个小示例。

(stackoverflow代码片段功能没有正确呈现以下代码,因此您需要将其复制并粘贴为HTML文件,然后在浏览器中打开以查看其运行情况。(

关于代码的几个注意事项:

  • "方框1";被认为是主框,所以只是简单地旋转
  • "方框2";被认为是一个"盒子";附";到box1,如果简单地旋转,将在其自身的中心上旋转。因此,在旋转";箱2";,它必须首先相对于"0"的中心移动;box1";,然后围绕";方框1";中心,然后向后移动

因此,为了回答您的特定问题,如果您有较小方框的坐标";附";到较大的长方体,并知道较大长方体的变换(即xy移动、旋转等(,然后在内部您可以创建一个表示较小长方体的DOM对象,应用较大长方体已知旋转的反向,然后了解较小长方体如何在坐标方面与较大长方体相关联。。。

<html><head>
</head><body>
<div id="box1" style="position:absolute; left:50; width:65; top:100; height:120; background: black"></div>
<div id="box2" style="position:absolute; left:55; width:30; top:110; height:60; background: red"></div>
<input id="rotateInput" value="45"></input>
<button onclick="rotate( parseFloat( document.getElementById('rotateInput').value ) )">Rotate</button>
<script>
var currentAngle = 0;
function rotate( rotDeg ) {
currentAngle += rotDeg;

// Rotating the large box is easy...
let dom1 = document.getElementById( 'box1' );
dom1.style.transform = `rotateZ( ${currentAngle}deg )`;
// Rotating the smaller box is a bit more involved...
let dom2 = document.getElementById( 'box2' );

console.log( `box2 before rotate: ( L:${box2.offsetLeft}, T:${box2.offsetTop}, W:${box2.offsetWidth}, H:${box2.offsetHeight} )` );
console.log( box2.getBoundingClientRect() );

dx = ( box2.offsetLeft + box2.offsetWidth / 2 ) - ( box1.offsetLeft + box1.offsetWidth / 2);
dy = ( box2.offsetTop + box2.offsetHeight / 2 ) - ( box1.offsetTop + box1.offsetHeight / 2);

dom2.style.transform = `
translateX( ${-dx}px )
translateY( ${-dy}px )
rotateZ( ${currentAngle}deg )
translateY( ${+dy}px )       
translateX( ${+dx}px )
`;

console.log( `box2 after rotate: ( L:${box2.offsetLeft}, T:${box2.offsetTop}, W:${box2.offsetWidth}, H:${box2.offsetHeight} )` );
console.log( box2.getBoundingClientRect() );

}
</script>
</body></html>

最新更新