英文:
How to create a rectangle around another rotated rectangle in canvas?
问题
在画布上绘制红色矩形在黑色矩形下方,使得旋转的黑色矩形的所有4个顶点接触红色矩形的4条边,可以使用以下代码:
// Rectangle properties
const redWidth = 60;
const redHeight = 220;
const redX = centerX - redWidth / 2;
const redY = centerY - redHeight / 2;
// Draw the red rectangle
ctx.fillStyle = 'red';
ctx.fillRect(redX, redY, redWidth, redHeight);
请将这段代码添加到您的现有代码中的合适位置。
英文:
How to draw the red rectangle below black rectangle on canvas such that all 4 vertices of the rotated black rectangle touch all 4 edges of the red rectangle? I am using the following code to add the black rectangle:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const canvas = document.getElementById('myCanvas1');
const ctx = canvas.getContext('2d');
// Rectangle properties
const width = 50;
const height = 200;
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
// Rotation angle in degrees
const degrees = -10; // Anti-clockwise rotation
const radians = (degrees * Math.PI) / 180;
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Save the canvas state
ctx.save();
// Translate to the center of the rectangle
ctx.translate(centerX, centerY);
// Rotate the canvas
ctx.rotate(radians);
// Draw the rotated rectangle
ctx.fillStyle = 'black';
ctx.fillRect(-width / 2, -height / 2, width, height);
// Restore the canvas state
ctx.restore();
<!-- language: lang-html -->
<canvas id="myCanvas1" width="600" height="250"></canvas>
<!-- end snippet -->
答案1
得分: 1
Brute force
暴力方法计算了旋转矩形的每个角的位置。然后,为了获取边界框,获取最左上角的角。
由于矩形围绕其中心旋转,边界框的宽度和高度是从矩形中心到两倍的距离。
函数 drawRect
绘制了旋转矩形并返回表示边界框的对象。
requestAnimationFrame(animLoop);
const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const width = Math.min(centerX, centerY) * 1.8;
const height = width * 0.25;
var rot = 0.0;
function drawRect(width, height, centerX, centerY, rotate) {
// 计算 x 轴向量
const xAx = Math.cos(rotate);
const xAy = Math.sin(rotate);
ctx.setTransform(xAx, xAy, -xAy, xAx, centerX, centerY);
ctx.fillStyle = "#000";
const hw = width * 0.5; // 半宽和半高
const hh = height * 0.5;
ctx.fillRect(-hw, -hh, width, height);
ctx.setTransform(1, 0, 0, 1, 0, 0); // 恢复默认
// 获取 4 个角
const topLeft = {x: -hw * xAx - -hh * xAy, y: -hw * xAy + -hh * xAx};
const botLeft = {x: -hw * xAx - hh * xAy, y: -hw * xAy + hh * xAx};
const topRight = {x: hw * xAx - -hh * xAy, y: hw * xAy + -hh * xAx};
const botRight = {x: hw * xAx - hh * xAy, y: hw * xAy + hh * xAx};
// 获取最左上角的角
const left = Math.min(topLeft.x, botLeft.x, topRight.x, botRight.x);
const top = Math.min(topLeft.y, botLeft.y, topRight.y, botRight.y);
// 返回边界框
return {
left: left + centerX,
top: top + centerY,
width: -left * 2,
height: -top * 2,
};
}
function animLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
rot += 0.01;
const bounding = drawRect(width, height, centerX, centerY, rot);
ctx.globalCompositeOperation = "destination-over";
ctx.fillStyle = "#F00";
ctx.fillRect(bounding.left, bounding.top, bounding.width, bounding.height);
ctx.globalCompositeOperation = "source-over";
requestAnimationFrame(animLoop);
}
<canvas id="canvas" width="400" height="180"></canvas>
英文:
Brute force
The brute force method calculates the position of each corner of the rotated rectangle. Then to get the bounding box get the left top most corner.
As the rectangle is rotated around its center the width and height of the bounding box is double the distance from the rectangle center.
The function drawRect
draws the rotated rectangle and returns an object representing the bounding box
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
requestAnimationFrame(animLoop);
const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const width = Math.min(centerX, centerY) * 1.8;
const height = width * 0.25
var rot = 0.0;
function drawRect(width, height, centerX, centerY, rotate) {
// compute the x axis vector
const xAx = Math.cos(rotate);
const xAy = Math.sin(rotate);
ctx.setTransform(xAx, xAy, -xAy, xAx, centerX, centerY);
ctx.fillStyle = "#000";
const hw = width * 0.5; // half width and height
const hh = height * 0.5;
ctx.fillRect(-hw, -hh, width, height);
ctx.setTransform(1, 0, 0, 1, 0, 0); // restore default
// Get 4 corners
const topLeft = {x: -hw * xAx - -hh * xAy, y: -hw * xAy + -hh * xAx};
const botLeft = {x: -hw * xAx - hh * xAy, y: -hw * xAy + hh * xAx};
const topRight = {x: hw * xAx - -hh * xAy, y: hw * xAy + -hh * xAx};
const botRight = {x: hw * xAx - hh * xAy, y: hw * xAy + hh * xAx};
// Get the left top most corner
const left = Math.min(topLeft.x, botLeft.x, topRight.x, botRight.x);
const top = Math.min(topLeft.y, botLeft.y, topRight.y, botRight.y);
// Return the bounding box
return {
left: left + centerX,
top: top + centerY,
width: -left * 2,
height: -top * 2,
};
}
function animLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
rot += 0.01;
const bounding = drawRect(width, height, centerX, centerY, rot);
ctx.globalCompositeOperation = "destination-over";
ctx.fillStyle = "#F00";
ctx.fillRect(bounding.left, bounding.top, bounding.width, bounding.height);
ctx.globalCompositeOperation = "source-over";
requestAnimationFrame(animLoop);
}
<!-- language: lang-html -->
<canvas id="canvas" width="400" height="180"></canvas>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论