我有一個圍繞其中心旋轉的矩形,我正在嘗試使其更寬。但是,由于它圍繞其中心旋轉,因此使其更寬也會在視覺上“移動”矩形。
我正在尋找一種使其更寬的方法,然后相應地調整其 x 和 y 分量,以使其在視覺上不會移動。我在這里創建了問題的重現,因此您可以看到問題:
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
function rotateCanvas(x, y, a) {
ctx.translate(x, y);
ctx.rotate(a);
ctx.translate(-x, -y);
}
function drawRotateRectangle(x, y, w, h, a) {
rotateCanvas(x w / 2, y h / 2, a);
ctx.fillRect(x, y, w, h);
rotateCanvas(x w / 2, y h / 2, -a);
}
let which = true;
function render() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const rWidth = which ? 100 : 200;
drawRotateRectangle(30, 30, rWidth, 30, 0.5);
which = !which;
}
render();
setInterval(render, 1000);
<canvas></canvas>
如您所見,當它變寬時,它也會向上移動。實際上,我希望矩形的左上角在調整大小之前和之后位于同一點。
但是,我也希望它仍然圍繞其中心旋轉。也就是說,我正在尋找我必須移動多少矩形(更改其 x 和 y 坐標),以便在調整大小發生之前和之后有效地將其錨定到同一位置。
這可能嗎?如果是這樣,您將如何計算必須修改矩形的x和 的值y,以便在視覺上將其鎖定在當前位置?
我認識到如果我將矩形圍繞其左上角而不是其中心旋轉,則不會發生此問題,但出于我的應用程式的目的,該矩形必須圍繞其中心旋轉,所以我改為尋找多少我必須修改其x和y組件以保持其視覺位置。
因此,這個問題的答案不應該涉及以任何方式修改rotateCanvasordrawRotateRectangle函式。
我正在尋找的效果示例:
uj5u.com熱心網友回復:
沿旋轉軸移動。旋轉為“r”,距離為“d”。假設變換是均勻的(即在這種情況 1 上 x、y 比例相同,并且沒有傾斜)
dx沿 x 軸和dyy 軸移動的示例
var r = ?; // rotation in radians
var x = ?, y = ?; // in pixels. coordinate to move
var dx = ?; // distance in pixels along x axis
var dy = ?; // distance in pixels along y axis
const ax = Math.cos(r);
const ay = Math.sin(r);
x = dx * ax - dy * ay
y = dx * ay dy * ax;
演示
展開一個矩形。該函式rect.expand(left, right, top, bottom)改變矩形的大小,調整原點以保持不變的邊緣。
const ctx = canvas.getContext("2d");
requestAnimationFrame(renderLoop);
const W = canvas.width, H = canvas.height;
var expanding = 1, expandCount = 0;
const rect = {
x: W / 2,
y: H / 2,
r: 0,
w: 100,
h: 50,
expand(left, right, top, bottom) {
const ax = Math.cos(this.r) * 0.5;
const ay = Math.sin(this.r) * 0.5;
this.w = left right;
this.h = top bottom;
this.x = -left * ax right * ax top * ay - bottom * ay;
this.y = -left * ay right * ay - top * ax bottom * ax;
},
draw() {
const ax = Math.cos(this.r);
const ay = Math.sin(this.r);
ctx.setTransform(ax, ay, -ay, ax, this.x, this.y);
ctx.strokeRect(-this.w * 0.5, -this.h * 0.5, this.w, this.h);
}
};
function renderLoop() {
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0, 0, W, H);
if (expanding === 1) {
expandCount = 1;
expandCount === 50 && (expanding = -1);
} else if (expanding === -1) {
expandCount -= 1;
expandCount === 0 && (expanding = 1);
}
rect.r = 0.01;
rect.expand(0, expanding, 0, 0);
rect.draw();
requestAnimationFrame(renderLoop);
}
canvas {
border: 1px solid black;
}
<canvas id = "canvas" width="200" height="200"></canvas>
uj5u.com熱心網友回復:
其他答案很好,很優雅,但你說你想保留rotateCanvas,drawRotateRectangle對吧?
我們可以使用a 上的rotateCanvas一些矩陣變換DOMPoint來模仿函式中的變換:
const x = 60;
const y = 30;
const h = 30;
const a = 0.5;
const tx = rWidth / 2;
const ty = h / 2;
// (0, 0) is the upper left of the rectangle
const pt = new DOMPoint(0, 0);
// Create transformation matrix based on center of rectangle
const mtr = new DOMMatrix()
.translateSelf(-tx, -ty)
// Important: rotateSelf takes degrees, not radians
.rotateSelf(a * 180 / Math.PI)
.translateSelf(tx, ty);
// Apply the transform
const tPt = pt.matrixTransform(mtr);
// Now the new call looks like this:
drawRotateRectangle(tPt.x x, tPt.y y, rWidth, h, a);
這是一個演示。x我畫了一個額外的紅點,以表明您可以使用和控制要開始繪制矩形的位置y。
顯示代碼片段
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext("2d");
function rotateCanvas(x, y, a) {
ctx.translate(x, y);
ctx.rotate(a);
ctx.translate(-x, -y);
}
function drawRotateRectangle(x, y, w, h, a) {
rotateCanvas(x w / 2, y h / 2, a);
ctx.fillRect(x, y, w, h);
rotateCanvas(x w / 2, y h / 2, -a);
}
let which = false;
function render() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const rWidth = which ? 100 : 200;
const x = 30;
const y = 30;
const h = 30;
const a = Math.PI / 3;
const tx = rWidth / 2;
const ty = h / 2;
// Imitate the transform you use to calculate the offset point
const pt = new DOMPoint(0, 0);
const mtr = new DOMMatrix()
.translateSelf(-tx, -ty)
.rotateSelf(a * 180 / Math.PI)
.translateSelf(tx, ty);
const tPt = pt.matrixTransform(mtr);
drawRotateRectangle(tPt.x x, tPt.y y, rWidth, h, a);
// Just to show you can control the start point
ctx.fillStyle = 'red';
ctx.fillRect(x, y, 3, 3);
ctx.fillStyle = 'black';
which = !which;
}
render();
setInterval(render, 1000);
<canvas style="border: 1px solid black;"></canvas>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/466404.html
標籤:javascript 数学 几何学 html5-画布 三角学
