模拟时钟时间调节气泡偏移问题求助
问题修复:模拟时钟调节气泡偏移问题
问题根源
反复拖拽后气泡偏离初始轨道,核心问题在于:
- 每次
mousemove计算位置时重复减去offsetX/offsetY,导致偏移量被持续叠加,气泡位置逐步偏离轨道 - 气泡坐标计算逻辑错误,未正确基于时钟中心定位气泡的中心位置,而是错误调整坐标引发偏移积累
修复方案
- 调整坐标计算逻辑:基于时钟中心计算气泡的中心坐标,再转换为气泡左上角的定位
- 仅在初始点击时校准鼠标与气泡的相对偏移,避免每次移动重复叠加该偏移量,确保气泡始终贴合圆环内侧轨道
修正后的代码
let isDragging = false; let offsetX, offsetY; const draggable = document.querySelector('.clock div:nth-child(3)'); const clock = document.querySelector('.clock'); const clockRadius = clock.offsetWidth / 2; const draggableRadius = draggable.offsetWidth / 2; const hourDisplay = document.querySelector('.clock div p'); // 提前获取时钟元素的位置基准,避免重复计算 const clockRect = clock.getBoundingClientRect(); draggable.addEventListener('mousedown', (e) => { isDragging = true; // 计算鼠标在气泡内的相对位置(相对于气泡左上角) offsetX = e.clientX - draggable.getBoundingClientRect().left; offsetY = e.clientY - draggable.getBoundingClientRect().top; draggable.style.cursor = 'grabbing'; }); document.addEventListener('mousemove', (e) => { if (!isDragging) return; // 计算鼠标相对于时钟中心的角度 const angle = Math.atan2( e.clientY - (clockRect.top + clockRadius), e.clientX - (clockRect.left + clockRadius) ); // 计算小时与分钟 let hours = Math.floor((angle + Math.PI / 2) / (Math.PI / 6)); hours = (hours + 12) % 12; const minuteSegment = ((angle + Math.PI / 2) / (Math.PI / 6 / 60)) % 60; const minutes = Math.floor(minuteSegment); // 更新时间显示 const formattedHour = hours < 10 ? `0${hours}` : `${hours}`; const formattedMinutes = minutes < 10 ? `0${minutes}` : `${minutes}`; hourDisplay.textContent = `${formattedHour}:${formattedMinutes}`; // 计算气泡中心相对于时钟左上角的坐标,确保中心在圆环内侧轨道上 const centerX = Math.cos(angle) * (clockRadius - draggableRadius) + clockRadius; const centerY = Math.sin(angle) * (clockRadius - draggableRadius) + clockRadius; // 转换为气泡左上角定位:中心坐标减去气泡半宽高,再校准鼠标点击偏移(避免拖拽跳变) draggable.style.left = (centerX - draggableRadius) - (offsetX - draggableRadius) + 'px'; draggable.style.top = (centerY - draggableRadius) - (offsetY - draggableRadius) + 'px'; }); document.addEventListener('mouseup', () => { isDragging = false; draggable.style.cursor = 'grab'; });
关键修改说明
- 提前缓存时钟的
getBoundingClientRect()结果,减少重复DOM计算,提升性能 - 气泡中心坐标计算改为
Math.cos(angle) * (clockRadius - draggableRadius) + clockRadius,确保中心始终贴合圆环内侧轨道 - 定位气泡左上角时,通过
(offsetX - draggableRadius)校准鼠标点击点与气泡中心的偏移,既避免拖拽时的位置跳变,又不会产生偏移积累
内容的提问来源于stack exchange,提问作者MohamedMbai
相关产品推荐
相关产品推荐

