You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

模拟时钟时间调节气泡偏移问题求助

问题修复:模拟时钟调节气泡偏移问题

问题根源

反复拖拽后气泡偏离初始轨道,核心问题在于:

  • 每次mousemove计算位置时重复减去offsetX/offsetY,导致偏移量被持续叠加,气泡位置逐步偏离轨道
  • 气泡坐标计算逻辑错误,未正确基于时钟中心定位气泡的中心位置,而是错误调整坐标引发偏移积累

修复方案

  1. 调整坐标计算逻辑:基于时钟中心计算气泡的中心坐标,再转换为气泡左上角的定位
  2. 仅在初始点击时校准鼠标与气泡的相对偏移,避免每次移动重复叠加该偏移量,确保气泡始终贴合圆环内侧轨道

修正后的代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 03:07:45