如何在画布中围绕另一个旋转矩形创建一个矩形?

问题描述 投票:0回答:1

如何在画布上的黑色矩形下方绘制红色矩形,使得旋转的黑色矩形的所有 4 个顶点都接触红色矩形的所有 4 个边?我使用以下代码添加黑色矩形:

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();
<canvas id="myCanvas1" width="600" height="250"></canvas>

javascript canvas html5-canvas
1个回答
0
投票

蛮力

暴力法计算旋转矩形的每个角的位置。然后要获取边界框,请获取左上角。

当矩形绕其中心旋转时,边界框的宽度和高度是距矩形中心距离的两倍。

函数

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

    // 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);
}
<canvas id="canvas" width="400" height="180"></canvas>

© www.soinside.com 2019 - 2024. All rights reserved.