如何编写JavaScript函数实现转盘向预设位置缓慢减速停止?
实现转盘缓慢减速并精准停在预设弧度的方案
要让转盘从最大速度开始,在剩余弧度范围内匀减速到0并精准停在radiansUntilStop,核心是根据剩余可转动的弧度动态调整当前速度,确保速度随剩余距离线性降低,最终到达目标时速度恰好为0。
关键修改思路
- 添加
deceleration(减速度)变量,控制每帧速度降低的幅度 - 计算剩余可转动弧度,根据剩余距离判断是否继续减速或直接定位到目标
- 避免"过冲",确保最终位置完全匹配预设值
修改后的核心代码(update函数)
function update() { if (spin === true) { const remainingRadians = radiansUntilStop - radians; // 剩余弧度不足以支撑当前速度时,直接跳到目标位置停止 if (remainingRadians <= currentSpeed) { radians = radiansUntilStop; currentSpeed = 0; spin = false; } else { // 按固定减速度降低当前速度,最低降到0 currentSpeed = Math.max(currentSpeed - deceleration, 0); radians += currentSpeed; } } debug(); }
完整修改代码
<canvas id="wheel" width="300" height="300"></canvas> <button id="spin" type="button">Spin</button><br> Radians: <span id="radians"></span><br> Speed: <span id="speed"></span><br>
const canvas = document.querySelector('#wheel'); const ctx = canvas.getContext('2d'); var radians = 0; // 当前转盘弧度 var maxSpeed = 0.2; // 每帧最大增加弧度 var currentSpeed = 0; // 当前每帧增加弧度 var radiansUntilStop = 47.8; // 目标停止弧度 var spin = false; // 是否正在转动 var deceleration = 0.001; // 每帧减速度,可按需调整 document.querySelector('#spin').addEventListener('click', function() { spin = true; currentSpeed = maxSpeed; }); function update() { if (spin === true) { const remainingRadians = radiansUntilStop - radians; if (remainingRadians <= currentSpeed) { radians = radiansUntilStop; currentSpeed = 0; spin = false; } else { currentSpeed = Math.max(currentSpeed - deceleration, 0); radians += currentSpeed; } } debug(); } function draw() { ctx.clearRect(0,0,canvas.width,canvas.height); ctx.arc(canvas.width/2, canvas.height/2, 150, 0, Math.PI * 2); for( let i = 0; i < Math.PI * 2; i += Math.PI * 0.5 ) { let fill = i === 0 ? true : false; drawWheelSection(150, 0, radians + i, fill); } } function loop() { window.requestAnimationFrame(loop); update(); draw(); }; loop(); function drawWheelSection(center, radius, wheelRadians, fill = false) { ctx.beginPath(); ctx.moveTo(center, center); ctx.arc(center, center, 140, 0 + wheelRadians, Math.PI * 0.5 + wheelRadians); ctx.lineTo(center, center); if( fill === true ) { ctx.fillStyle = 'blue'; ctx.fill(); } ctx.stroke(); // 修正箭头绘制位置,确保箭头在转盘顶部 ctx.save(); ctx.translate(canvas.width/2, canvas.height/2); ctx.beginPath(); ctx.moveTo(0, -140); ctx.lineTo(-10, -110); ctx.lineTo(10, -110); ctx.closePath(); ctx.fillStyle = 'red'; ctx.fill(); ctx.stroke(); ctx.restore(); } function debug() { document.querySelector('#radians').innerHTML = radians.toFixed(2); document.querySelector('#speed').innerHTML = currentSpeed.toFixed(4); }
体验优化技巧
- 调整
deceleration值:值越大减速越快,值越小减速越平缓 - 可添加加速阶段:点击后从0逐步加速到
maxSpeed,再进入减速流程,更贴近真实转盘体验 - 若需要更自然的减速曲线,可将减速度设置为随剩余弧度动态变化(剩余越多减速度越小)
内容的提问来源于stack exchange,提问作者Myles
相关产品推荐
相关产品推荐

