長方形を閉じる4つの点1
、、2
があります。3
4
ポイントは次のように配列されます。x1
y1
x2
y2
x3
y3
x4
y4
問題は、長方形を角度を変えて回転できることです。
元のポイント(灰色のアウトライン)と角度を計算するにはどうすればいいですか?
私はこの効果を javascript+css3-transform で再現しようとしているので、まず直線寸法を把握し、次に CSS を使用して回転する必要があります。
点を比較することで長方形が直線かどうかが分かります。y1==y2
if(x1==x4 && x2==x3 && y1==y2 && y4==y3){
rectangle.style.top = y1;
rectangle.style.left = x1;
rectangle.style.width = x2-x1;
rectangle.style.height = y4-y1;
rectangle.style.transform = "rotate(?deg)";
}
ベストアンサー1
回転角度を計算するには、同じ側の任意の座標ペアを使用できます。数学的な角度は通常、+ve X 軸の長さが 0 であると想定され、反時計回りに回転すると増加します (つまり、+ve Y 軸に沿って 90°、-ve X 軸に沿って 180° など)。
また、JavaScript の三角関数はラジアン単位で値を返しますが、CSS 変換で使用する前に度に変換する必要があります。
図形が 90° 以上回転していない場合、作業は非常に単純で、直角三角形の接線比を使用できます。
tan(angle) = length of opposite side / length of adjacent side
OPの場合、回転が第1象限で時計回りに保たれるように、使用する最適なコーナーは1と4です(CSS3 仕様草案)。JavaScript 用語では:
var rotationRadians = Math.atan((x1 - x4) / (y1 - y4));
度数に変換するには:
var RAD2DEG = 180 / Math.PI;
var rotationDegrees = rotationRadians * RAD2DEG;
回転が 90° を超える場合は、角度を調整する必要があります。たとえば、角度が 90° より大きく 180° 未満の場合、上記の結果から -ve が得られるため、180° を追加する必要があります。
rotationDegrees += 180;
また、ページ寸法を使用している場合、y 座標はページの下に行くほど増加します。これは通常の数学的な意味とは逆なので、y1 - y4
上記の意味を逆にする必要があります。
編集
OP のポイントの方向に基づいて、長方形の中心と時計回りの回転を度単位で返す一般的な関数を次に示します。必要なのはこれだけですが、必要に応じて、コーナーを自分で回転させて「水平」にすることもできます。三角関数を適用して新しいコーナーを計算したり、平均を計算したりすることもできます (Ian の回答と同様)。
/** General case solution for a rectangle
*
* Given coordinages of [x1, y1, x2, y2, x3, y3, x4, y4]
* where the corners are:
* top left : x1, y1
* top right : x2, y2
* bottom right: x3, y3
* bottom left : x4, y4
*
* The centre is the average top left and bottom right coords:
* center: (x1 + x3) / 2 and (y1 + y3) / 2
*
* Clockwise rotation: Math.atan((x1 - x4)/(y1 - y4)) with
* adjustment for the quadrant the angle is in.
*
* Note that if using page coordinates, y is +ve down the page which
* is the reverse of the mathematic sense so y page coordinages
* should be multiplied by -1 before being given to the function.
* (e.g. a page y of 400 should be -400).
*
* @see https://stackoverflow.com/a/13003782/938822
*/
function getRotation(coords) {
// Get center as average of top left and bottom right
var center = [(coords[0] + coords[4]) / 2,
(coords[1] + coords[5]) / 2];
// Get differences top left minus bottom left
var diffs = [coords[0] - coords[6], coords[1] - coords[7]];
// Get rotation in degrees
var rotation = Math.atan(diffs[0]/diffs[1]) * 180 / Math.PI;
// Adjust for 2nd & 3rd quadrants, i.e. diff y is -ve.
if (diffs[1] < 0) {
rotation += 180;
// Adjust for 4th quadrant
// i.e. diff x is -ve, diff y is +ve
} else if (diffs[0] < 0) {
rotation += 360;
}
// return array of [[centerX, centerY], rotation];
return [center, rotation];
}