JavaScript实现立方体拖拽旋转:解决点击重置角度问题
解决立方体拖拽旋转重置位置的问题
你的问题出在每次拖拽时,旋转角度都是基于鼠标按下瞬间的坐标计算偏移,没有保存上次拖拽结束后的最终旋转状态。要解决这个问题,只需要记录累计的旋转角度,每次拖拽都在已有角度的基础上叠加偏移量即可。
修改后的完整代码
JavaScript 部分
// Select the Cube const cube = document.querySelector(".cube"); const body = document.querySelector("body"); // 保存累计的旋转角度 let currentX = 0; let currentY = 0; // Get the x, y position when click window.addEventListener("mousedown", function(e) { const startX = e.clientX; const startY = e.clientY; // 记录按下时的当前角度,避免拖拽初始瞬间跳动 const initialX = currentX; const initialY = currentY; // rotate window.addEventListener("mousemove", moveRotate); function moveRotate(e) { // 计算鼠标移动的偏移量 const deltaX = e.clientX - startX; const deltaY = e.clientY - startY; // 在已有角度基础上叠加偏移量 cube.style.transform = ` rotateX(${initialY + deltaY / -2}deg) rotateY(${initialX + deltaX / 2}deg)`; body.style.cursor = "grabbing"; } window.addEventListener("mouseup", function() { // 更新累计角度为当前最终旋转角度 const transform = cube.style.transform; // 从transform字符串中提取当前的rotateX和rotateY值 const xMatch = transform.match(/rotateX\((-?\d+\.?\d*)deg\)/); const yMatch = transform.match(/rotateY\((-?\d+\.?\d*)deg\)/); if (xMatch) currentY = parseFloat(xMatch[1]); if (yMatch) currentX = parseFloat(yMatch[1]); window.removeEventListener("mousemove", moveRotate); body.style.cursor = "context-menu"; }); });
CSS 部分(无需修改)
* { margin: 0; padding: 0; box-sizing: border-box; } body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background: rgb(0, 0, 0); } .cube { position: absolute; width: 300px; height: 300px; transform-style: preserve-3d; } .cube div { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transform-style: preserve-3d; } .cube div span { color: azure; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(black, rgb(0, 255, 0)); transform: rotateY(calc(90deg * var(--i))) translateZ(150px); } .top { position: absolute; top: 0; left: 0; width: 300px; height: 300px; background: #222; transform: rotateX(90deg) translateZ(150px); } .top div { color: white; position: absolute; top: 45%; left: 35% } .bottom { position: absolute; top: 0; left: 0; width: 300px; height: 300px; background: rgba(0, 255, 0); transform: rotateX(90deg) translateZ(-150px); }
HTML 部分(无需修改)
<body> <div class="cube"> <div class="top"></div> <div class="bottom"></div> <div class="sides"> <span class=front style="--i:0;">0</span> <span class=left style="--i:1;">1</span> <span class=back style="--i:2;">2</span> <span class=right style="--i:3;">3</span> </div> </div> </body>
关键修改说明
- 新增累计角度变量:
currentX和currentY用来保存每次拖拽结束后的最终旋转角度,初始值为0。 - 鼠标按下时记录初始状态:保存按下瞬间的鼠标位置和当前累计角度,避免拖拽开始时立方体突然跳动。
- 拖拽时叠加偏移量:旋转角度不再直接用鼠标偏移量,而是用初始累计角度加上偏移量的比例值,实现基于上次状态的连续旋转。
- 鼠标松开时更新累计角度:从元素的
transform样式中提取当前的旋转角度,更新到currentX和currentY,为下一次拖拽做准备。
内容的提问来源于stack exchange,提问作者vito
相关产品推荐
相关产品推荐

