<div id='ball'></div>
#ball {
  cursor: pointer;
  border: 1px solid #000;
  height: 50px;
  width: 50px;
  border-radius: 25px;
  background: #67f0b6;
  position: fixed;
  top: 50%;
  left: 50%;
}
// 主函数
const main = () => {
  const ball = document.getElementById('ball');
  
  let isDraging = false; // 记录是否在拖动中
  
  let dragWithParams; // 绑定参数的拖动方法
  
  const drag = (params, e) => {
    let x = e.clientX - params.offsetLeft;
    let y = e.clientY - params.offsetTop;
    
    // 避免小球移出视口
    if (x < 0) {
      x = 0;
    } else if (x > document.documentElement.clientWidth - ball.offsetWidth) {
      x = document.documentElement.clientWidth - ball.offsetWidth
    }
    if (y < 0) {
      y = 0;
    } else if (y > document.documentElement.clientHeight - ball.offsetHeight) {
      y = document.documentElement.clientHeight - ball.offsetHeight;
    }
    
    ball.style.left = x + 'px';
    ball.style.top = y + 'px';
  }
  
  // 当鼠标弹起时判断是否移除 mousemove 事件
  document.addEventListener('mouseup', () => {
    if (isDraging) {
      console.log('up');
      document.removeEventListener('mousemove', dragWithParams);
      isDraging = false;
    }
  })
  
  // 点击球时为 document 绑定 mousemove 事件
  ball.addEventListener('mousedown', e => {
    const offsetLeft = e.clientX - ball.offsetLeft;
    const offsetTop = e.clientY - ball.offsetTop;
    
    isDraging = true;
    
    // 绑定参数
    dragWithParams = drag.bind(null, {
      offsetLeft,
      offsetTop,
    })
    
    document.addEventListener('mousemove', dragWithParams);
   });
  
}

document.addEventListener('DOMContentLoaded', main);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.