【发布时间】:2018-05-09 12:19:11
【问题描述】:
我目前正在尝试找出一种方法来相对于用户而不是相对于对象沿轴旋转对象。我正在使用 Javascript (jQuery) 和 CSS 转换旋转来执行此操作。
我已经构建了一个代码笔来测试它。
var bX = 0; //bufferX (user scroll input)
var bY = 0; //bufferY (user scroll input)
var cX = 0; //currentX (effective X rotation)
var cY = 0; //currentY (effective Y rotation)
var bBX = 0; // same second rotation properties
var bBY = 0;
var cBX = 0;
var cBY = 0;
var cBZ = 0; // currentZ (effective Z rotation)
var pi = 3.1416
// Fidget animation
function fidget() {
if (!(bX + bY == 0)) {
var dX = bX * 0.1; // how much we rotate this frame
var dY = bY * 0.1;
cX = (cX + dX) % (2 * pi); // set rotation value
cY = (cY + dY) % (2 * pi);
bX -= dX; // update buffer
bY -= dY;
}
$('#one').css('transform', 'rotateX(' + cX + 'rad) rotateY(' + cY + 'rad)');
window.requestAnimationFrame(fidget);
}
function fidgetB() {
if (!(bBX + bBY == 0)) {
var dBX = bBX * 0.1;
cBX = (cBX + dBX) % (2 * pi);
var rBY = Math.cos(cBX); //Y ratio
var rBZ = Math.sin(cBX); //Z ratio
var dBY = bBY * 0.1; // deltaY
var dBZ = bBY * 0.1;
cBY = (cBY + rBY * dBY) % (2 * pi); // current
cBZ = (cBZ - rBZ * dBZ) % (2 * pi);
bBX -= dBX; // buffer
bBY -= (dBY);
}
$('#two').css('transform', 'rotateX(' + cBX + 'rad) rotateY(' + cBY + 'rad) rotateZ(' + cBZ + 'rad)');
window.requestAnimationFrame(fidgetB);
}
var init = function () {
// Fidget
requestAnimationFrame(fidget);
requestAnimationFrame(fidgetB);
// scroll detection script
!function(window,document){var prefix="",_addEventListener,support;function _addWheelListener(elem,eventName,callback,useCapture){elem[_addEventListener](prefix+eventName,"wheel"==support?callback:function(originalEvent){!originalEvent&&(originalEvent=window.event);var event={originalEvent:originalEvent,target:originalEvent.target||originalEvent.srcElement,type:"wheel",deltaMode:"MozMousePixelScroll"==originalEvent.type?0:1,deltaX:0,deltaY:0,deltaZ:0,preventDefault:function(){originalEvent.preventDefault?originalEvent.preventDefault():originalEvent.returnValue=!1}};return"mousewheel"==support?(event.deltaY=-.025*originalEvent.wheelDelta,originalEvent.wheelDeltaX&&(event.deltaX=-.025*originalEvent.wheelDeltaX)):event.deltaY=originalEvent.deltaY||originalEvent.detail,callback(event)},useCapture||!1)}window.addEventListener?_addEventListener="addEventListener":(_addEventListener="attachEvent",prefix="on"),support="onwheel"in document.createElement("div")?"wheel":void 0!==document.onmousewheel?"mousewheel":"DOMMouseScroll",window.addWheelListener=function(elem,callback,useCapture){_addWheelListener(elem,support,callback,useCapture),"DOMMouseScroll"==support&&_addWheelListener(elem,"MozMousePixelScroll",callback,useCapture)}}(window,document);
window.addWheelListener(window, function (e) {
e.preventDefault();
bY -= e.deltaX / window.innerWidth;
bX += e.deltaY / window.innerWidth;
bBY -= e.deltaX / window.innerWidth;
bBX += e.deltaY / window.innerWidth;
});
};
jQuery(document).ready(function ($) {
init();
});
html, html * {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color:white;
text-align: center;
font-size: 6vmin;
font-family: sans-serif;
}
#intro {
position:absolute;
width: 100%;
height: 100%;
-webkit-perspective: 200vmax;
perspective: 200vmax;
-webkit-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
transform-style: preserve-3d;
}
#one {
left: 33%;
}
#two {
left: 66%;
}
.square {
background-color: black;
width: 50vmin;
height: 50vmin;
line-height: 50vmin;
top: 50%;
margin-top: -25vmin;
margin-left: -25vmin;
transform-style: preserve-3d;
position: absolute;
-webkit-backface-visibility: visible;
backface-visibility: visible;
-webkit-transform-origin: 50% 37%;
transform-origin: 50% 37%;
/* -webkit-animation: rotate 25s linear infinite;
animation: rotate 25s linear infinite; */
pointer-events: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="intro">
<div id="one" class="square">Object</div>
<div id="two" class="square">User</div>
</div>
[https://codepen.io/rsepierre/pen/XqVJKR][1]
要控制您使用鼠标滚轮/触摸板滚动的任何正方形的旋转(shift+滚轮滚动 Y 轴。整理后会添加触摸支持)
- 左方的旋转是相对于对象的:
如果你只向左滚动向右,没问题,它可以工作。向上向下也一样。
现在,如果您将项目平放(向下滚动 90°向上),然后尝试在另一个轴(左右)上旋转,它会自行旋转。这意味着对用户来说,它看起来像 Z 轴旋转(像时钟)。
- 右方的旋转是我尝试做的旋转 相对于用户:
如果你向左滚动向右,没问题,它可以工作。向上向下也一样。
如果您再次将项目平放(向下滚动 90°向上)然后尝试在另一个轴上旋转(向左滚动向右),它将相对于用户旋转。 该项目在“Z”轴上旋转,但从用户的角度来看,它看起来像 Y 轴旋转。
它实际上正在工作: 如果您只向上滚动向下滚动 90° 步骤,并且从不介于两者之间。 即使您在向上向下滚动时得到 89° 角而不是 90° 角,它也会慢慢变得一团糟。
- 我最好的解决方案:
我开始明白 3D 旋转不是可交换的(应用旋转的顺序会影响最终结果,这就是为什么只有 Y 轴旋转会搞砸,而 X 轴旋转永远不会搞砸的原因)。
一个简单的解决方法是将每个新用户输入添加到一个新的旋转中 (rotateX(100) rotateY(5) rotateY(20) rotateX(105)...无限期。
但显然我每秒执行 60 次,它很快就会成为你在一段时间内见过的最糟糕的 CPU/GPU 韭菜。
因此,我相信我应该以某种方式在 JS 中完成所有幕后的数学运算,并且只应用一个 rotate3D(X,Y,Z,angle) css 旋转。
问题是我对旋转矩阵背后的数学一无所知。 我发现这个转换器可以将 3D 旋转事物转换为其他 3D 旋转事物,但我认为我需要了解什么是开始做任何数学运算。
非常感谢任何帮助。
【问题讨论】:
标签: javascript math 3d css-transforms rotational-matrices