如果我们查看图片,我们会看到立方体在其初始位置(带有一个点)跟随光标。当光标向左或向右移动时,立方体沿轴旋转Y。实际上,这就是我试图从多维数据集实现的目标。
但是当正方体以五个点翻转到一边时,左右移动时,正方体沿轴旋转Z。然后,将立方体旋转三个点,首先它向正确的方向旋转,在 gif 结束时它向相反的方向旋转。
如何使旋转方向可预测?例如,使立方体始终像在其原始位置一样旋转。
let [action,angleX,angleY,map,touchX,touchY] = ["idle",0,0,new WeakMap,0,0];
const dice = [first, second, third, fourth, fifth, sixth];
dice.forEach(el =>
map.set(el, [...document.styleSheets[0].rules]
.find(rule=>`#${el.id}`==rule.selectorText).style.transform
));
const ontouchstart=e => {
if(e.touches.length==1){
[touchX,touchY]=[e.touches[0].pageX,e.touches[0].pageY];}
else {
[touchX,touchY]=[0,0];
}
};
const ontouchend =()=>[touchX,touchY]=[0,0];
const ontouchmove=e=>{
if(touchX&&touchY){
[angleX,angleY]=[
angleX-e.touches[0].pageY+touchY,
angleY+e.touches[0].pageX-touchX]
.map((a) => (a > 360 ? a - 360 : a < 0 ? a + 360 : a));
dice.map(el => el.style.transform =
`rotateX(${angleX}deg) rotateY(${angleY}deg) ` + map.get(el));
[touchX,touchY]=[e.touches[0].pageX,e.touches[0].pageY];
}
}
const onmousedown = () => action = "rotate";
const onmouseup = () => action = "idle";
const onmousemove = e => {
if (action == "rotate") {
[angleX, angleY] = [ angleX - e.movementY, angleY + e.movementX ]
.map((a) => (a > 360 ? a - 360 : a < 0 ? a + 360 : a));
dice.map(el => el.style.transform =
`rotateX(${angleX}deg) rotateY(${angleY}deg) ` + map.get(el));
}
};
Object.assign(document.body, {onmousedown, onmousemove,ontouchstart,ontouchmove});
Object.assign(window, {onmouseup,ontouchend});
* {
box-sizing: border-box;
}
body,
div {
margin: 0;
padding: 0;
}
body {
width: 100vw;
height: 100vh;
perspective: 100vh;
transform-style: preserve-3d;
background-color: #333;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.face {
background-color: #cccc;
border-radius: 0;
border: 3px solid #000;
padding: 3vh;
margin: 3px;
display: flex;
width: 25vh;
height: 25vh;
position: fixed;
left: calc(50vw - 12.5vh);
top: calc(50vh - 12.5vh);
pointer-events: none;
/* backdrop-filter: blur(2px); */
}
.column {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.pip {
background-color: #000;
width: 4vh;
height: 4vh;
display: inline-block;
border-radius: 4rem;
}
#first {
justify-content: center;
align-items: center;
transform: translateZ(12.5vh);
}
#second {
justify-content: space-between;
transform: rotateX(90deg) translateZ(-12.5vh);
}
#second .pip:nth-of-type(2) {
align-self: flex-end;
}
#third {
justify-content: space-between;
align-items: center;
transform: rotateY(90deg) translateZ(-12.5vh);
}
#third .pip:nth-of-type(1) {
align-self: flex-start;
}
#third .pip:nth-of-type(3) {
align-self: flex-end;
}
#fourth {
justify-content: space-between;
transform: rotateY(180deg) translateZ(12.5vh);
}
#fifth {
justify-content: space-between;
justify-content: space-between;
transform: rotateX(90deg) translateZ(12.5vh);
}
#fifth .column:nth-of-type(2) {
align-self: center;
}
#sixth {
justify-content: space-between;
transform: rotateY(90deg) translateZ(12.5vh);
}
<div id="first" class="face"><span class="pip"></span></div>
<div id="second" class="face">
<span class="pip"></span>
<span class="pip"></span>
</div>
<div id="third" class="face">
<span class="pip"></span>
<span class="pip"></span>
<span class="pip"></span>
</div>
<div id="fourth" class="face">
<div class="column">
<span class="pip"></span> <span class="pip"></span>
</div>
<div class="column">
<span class="pip"></span> <span class="pip"></span>
</div>
</div>
<div id="fifth" class="face">
<div class="column">
<span class="pip"></span> <span class="pip"></span>
</div>
<div class="column"><span class="pip"></span></div>
<div class="column">
<span class="pip"></span> <span class="pip"></span>
</div>
</div>
<div id="sixth" class="face">
<div class="column">
<span class="pip"></span> <span class="pip"></span>
<span class="pip"></span>
</div>
<div class="column">
<span class="pip"></span> <span class="pip"></span>
<span class="pip"></span>
</div>
</div>

该解决方案并不完美,但似乎有效。基于旋转矩阵的保存。