我與矩陣頭疼,所以我用的比例這樣做。
如果你看到從上面(因此看到它發生在兩個維度的旋轉),你看到它在XZ平面段的股利,座標(-250, 0) (250, 0)
,或一般(-w/2, 0) (w/2, 0)
後在y軸旋轉,座標將成爲類似,你說什麼
(-Math.cos(angle) * w/2, -Math.sin(angle) * w/2)
(Math.cos(angle) * w/2, Math.sin(angle) * w/2)
,作爲逆時針旋轉,與該div的中心爲原點,和angle
弧度。
使用透視意味着這些座標不會僅僅通過丟棄z來顯示,而是首先根據它們與觀察者之間的距離來投影。
現在,投影平面是未旋轉的東西所在的位置,z = 0。我從這樣一個事實推斷出這一點,即當未旋轉的div投影時,它們保持相同的大小。 如果您從z平面上獲取距離爲p
(透視值)的點,則用xz座標(0,-p)繪製一條直線,並從該點到旋轉線段的頂點繪製直線,直到它穿過投影計劃,得到的點是產生div最終大小的新段座標。
隨着和(0, -p) (0, sin*w/2) (cos*w/2, sin*w/2)
三角形之間的比例(0, -p) (0, 0) (x, 0)
,你得到
p : x = (p + sin*w/2) : cos*w/2
x = (p * cos*w/2)/(p + sin*w/2)
這一般意味着,當你的項目點(x, y, z)
到計劃你
x * p/(p + z)
y * p/(p + z)
0
因此,最終的div座標(在xz上,相對於div的中心)將是
(-Math.cos(angle) * w/2 * p/(p + -Math.sin(angle) * w/2), 0)
(Math.cos(angle) * w/2 * p/(p + Math.sin(angle) * w/2), 0)
從中你可以計算出它的寬度,也可以計算它的位置 - 這是非平凡的,因爲它最接近觀察者的一半會比另一半大。
請看下面的測試更多細節(它,當你太靠近物體,我不知道爲什麼失敗,可能是一些變量溢出)
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
var WIDTH = 500;
var P = 300;
jQuery(function(){
function test(width, angle, p) {
$('body').
append($('<div id="info" />')).
append($('<div id="container" />').
css({
margin: '50px 0px',
border: '1px solid black',
width: width+'px',
'-webkit-perspective': p
}).
append($('<div id="real" />').addClass('the_div').css({ 'width': width+'px' }))).
append($('<div id="fake" />').addClass('the_div'));
setInterval(function() {
angle += 1;
$('#real').css({ '-webkit-transform': 'rotateY('+angle+'deg)' }).html(width);
// initial coordinates
var A = 0;
var B = width;
// translate the center (assuming -perspective-origin at 50%)
A -= width/2;
B -= width/2;
// new coordinates
A = calc(A, angle*Math.PI/180, p);
B = calc(B, angle*Math.PI/180, p);
// translate back
A += width/2;
B += width/2;
if(B < A) { var tmp = A; A = B; B = tmp; } // swap
var realwidth = B-A;
$('#fake').html(width+'<br/>'+A+', '+B).css({
'width': realwidth+'px',
'margin-left': A+'px'
});
// shows debug information
var debug = function(values) { return values.map(function(i){ return i+': '+eval(i); }).join('<br />'); }
$('#info').html($('<div />').html(debug(['width', 'p', 'angle', 'A', 'B', 'realwidth'])));
}, 40);
}
function calc(oldx, angle, p) {
var x = Math.cos(angle) * oldx;
var z = Math.sin(angle) * oldx;
return x * p/(p+z);
}
test(WIDTH, 0, P);
});
</script>
<style type="text/css">
* { margin: 0px; padding: 0px; }
body { padding: 40px 100px; }
.the_div { height: 100px; border: 2px solid black; background-color: rgba(255, 192, 0, 0.5); }
</style>
</head>
<body></body>
</html>
請注意,如果你是沒有給出一個視角值,結果將是相等的,因爲它具有無限的價值。
這是一個很好的問題 - 我從未很清楚透視值的工作原理。 – 2011-12-27 22:15:25
我添加了來自W3C的透視函數的官方定義。仍然不知道如何計算。 – Elias 2011-12-28 11:06:43
儘管已經完成了數學學位並瞭解了矩陣如何與線性代數相關,但我仍然不確定如何在3D圖形中使用它。如果您知道某些要求,則可以選擇垃圾選項,並以不同的角度測量寬度,然後將其放入電子表格中,然後手動調整曲線。無論如何可能會比完整的計算更快,並且會有足夠的準確性(對於像素來說,無論如何你都必須四捨五入到最接近的一個,所以小於0.5的誤差並不會產生影響) – 2011-12-28 12:05:44