js实现盒子拖拽动画效果

实现盒子拖拽动画效果需要以下步骤:

1. 为拖拽目标元素绑定事件监听器

首先需要为需要拖拽的目标元素添加事件监听器,通常是mousedown事件或者touchstart事件。

let target = document.getElementById('drag-target');
target.addEventListener('mousedown', dragStart);
target.addEventListener('touchstart', dragStart);

其中dragStart函数是拖拽开始的处理函数,我们接下来会讲到。

2. 实现拖拽功能

当用户开始拖拽目标元素时,我们需要对鼠标或手指的移动进行监听,并实时更新目标元素的位置,以实现拖拽效果。我们需要给目标元素的父元素绑定事件监听器,监听mousemove事件或者touchmove事件,并在事件处理函数中更新目标元素的位置。

let container = document.getElementById('drag-container');
container.addEventListener('mousemove', dragging);
container.addEventListener('touchmove', dragging);

其中dragging函数是拖拽中的处理函数,我们接下来会讲到。

在处理函数中,我们通过事件对象获取鼠标或手指的位置,然后计算出目标元素相对于父元素的位置,再设置目标元素的样式即可。

function dragging(e) {
  e.preventDefault(); // 防止默认行为(比如滚动)
  let offsetX, offsetY;
  if (e.type === 'mousemove') {
    offsetX = e.clientX - container.offsetLeft;
    offsetY = e.clientY - container.offsetTop;
  } else if (e.type === 'touchmove') {
    offsetX = e.touches[0].clientX - container.offsetLeft;
    offsetY = e.touches[0].clientY - container.offsetTop;
  }
  target.style.left = offsetX + 'px';
  target.style.top = offsetY + 'px';
}

需要注意的是,在触摸设备上,我们需要获取touches数组中第一个触摸点的位置。

3. 实现拖拽动画效果

在上一步拖动中,我们已经可以实现目标元素的拖动。接下来我们需要添加缓动效果,使目标元素在松开鼠标或手指时能够平稳地移动到目标位置。我们可以使用requestAnimationFrame函数来实现动画效果。

首先,我们需要在mousedowntouchstart事件中记录目标元素的初始位置和事件发生的时间。

function dragStart(e) {
  let offsetX, offsetY;
  if (e.type === 'mousedown') {
    offsetX = e.clientX - target.offsetLeft;
    offsetY = e.clientY - target.offsetTop;
  } else if (e.type === 'touchstart') {
    offsetX = e.touches[0].clientX - target.offsetLeft;
    offsetY = e.touches[0].clientY - target.offsetTop;
  }
  let startTime = Date.now();
  let startPos = {x: target.offsetLeft, y: target.offsetTop};
  // 在这里保存初始位置和时间
}

然后,我们可以在mousemovetouchmove事件中更新目标元素的位置,并计算出目标位置和当前位置之间的距离和时间间隔,以便计算缓动效果。

function dragging(e) {
  // 在这里更新目标元素的位置
  let offsetX, offsetY;
  if (e.type === 'mousemove') {
    offsetX = e.clientX - container.offsetLeft;
    offsetY = e.clientY - container.offsetTop;
  } else if (e.type === 'touchmove') {
    offsetX = e.touches[0].clientX - container.offsetLeft;
    offsetY = e.touches[0].clientY - container.offsetTop;
  }
  target.style.left = offsetX + 'px';
  target.style.top = offsetY + 'px';

  // 在这里计算移动距离和时间间隔
  let distance = Math.sqrt(Math.pow(offsetX-startPos.x,2) + Math.pow(offsetY-startPos.y,2));
  let duration = Date.now() - startTime;
}

最后,在mouseuptouchend事件中,我们可以根据移动距离和时间间隔计算出缓动效果的参数(速度和加速度),然后使用requestAnimationFrame函数实现动画效果。

function dragEnd(e) {
  // 在这里计算速度和加速度
  let velocity = distance / duration;
  let direction = Math.atan2(offsetY-startPos.y, offsetX-startPos.x);
  let acceleration = velocity * 10;
  let startX = target.offsetLeft, startY = target.offsetTop;

  // 定义动画函数
  function animate() {
    let elapsed = Date.now() - startTime;
    let dx = startX + velocity * elapsed * Math.cos(direction);
    let dy = startY + velocity * elapsed * Math.sin(direction) + acceleration * Math.pow(elapsed, 2) / 2;
    // 判断动画是否结束,如果未结束继续更新位置,否则停止动画
    if (elapsed < duration) {
      target.style.left = dx + 'px';
      target.style.top = dy + 'px';
      requestAnimationFrame(animate);
    } else {
      target.style.left = startX + distance * Math.cos(direction) + 'px';
      target.style.top = startY + distance * Math.sin(direction) + 'px';
    }
  }
  animate();
}

这样,我们就实现了盒子拖拽动画效果。下面给出两个示例,分别实现了鼠标和触摸设备的拖拽效果。

示例 1:鼠标拖拽

<div id="drag-container" style="position: relative;width: 300px;height: 300px;background-color: #eee;">
  <div id="drag-target" style="position: absolute;width: 50px;height: 50px;background-color: red;"></div>
</div>

<script>
let target = document.getElementById('drag-target');
let container = document.getElementById('drag-container');
let startPos, startTime, distance, duration;

target.addEventListener('mousedown', dragStart);
container.addEventListener('mousemove', dragging);
container.addEventListener('mouseup', dragEnd);

function dragStart(e) {
  let offsetX = e.clientX - target.offsetLeft;
  let offsetY = e.clientY - target.offsetTop;
  startTime = Date.now();
  startPos = {x: target.offsetLeft, y: target.offsetTop};
}

function dragging(e) {
  e.preventDefault();
  let offsetX = e.clientX - container.offsetLeft;
  let offsetY = e.clientY - container.offsetTop;
  target.style.left = offsetX + 'px';
  target.style.top = offsetY + 'px';
  distance = Math.sqrt(Math.pow(offsetX-startPos.x,2) + Math.pow(offsetY-startPos.y,2));
  duration = Date.now() - startTime;
}

function dragEnd(e) {
  let velocity = distance / duration;
  let direction = Math.atan2(offsetY-startPos.y, offsetX-startPos.x);
  let acceleration = velocity * 10;
  let startX = target.offsetLeft, startY = target.offsetTop;

  function animate() {
    let elapsed = Date.now() - startTime;
    let dx = startX + velocity * elapsed * Math.cos(direction);
    let dy = startY + velocity * elapsed * Math.sin(direction) + acceleration * Math.pow(elapsed, 2) / 2;
    if (elapsed < duration) {
      target.style.left = dx + 'px';
      target.style.top = dy + 'px';
      requestAnimationFrame(animate);
    } else {
      target.style.left = startX + distance * Math.cos(direction) + 'px';
      target.style.top = startY + distance * Math.sin(direction) + 'px';
    }
  }
  animate();
}
</script>

示例 2:触摸设备拖拽

<div id="drag-container" style="position: relative;width: 300px;height: 300px;background-color: #eee;">
  <div id="drag-target" style="position: absolute;width: 50px;height: 50px;background-color: red;"></div>
</div>

<script>
let target = document.getElementById('drag-target');
let container = document.getElementById('drag-container');
let startPos, startTime, distance, duration;

target.addEventListener('touchstart', dragStart);
container.addEventListener('touchmove', dragging);
container.addEventListener('touchend', dragEnd);

function dragStart(e) {
  e.preventDefault();
  let offsetX = e.touches[0].clientX - target.offsetLeft;
  let offsetY = e.touches[0].clientY - target.offsetTop;
  startTime = Date.now();
  startPos = {x: target.offsetLeft, y: target.offsetTop};
}

function dragging(e) {
  e.preventDefault();
  let offsetX = e.touches[0].clientX - container.offsetLeft;
  let offsetY = e.touches[0].clientY - container.offsetTop;
  target.style.left = offsetX + 'px';
  target.style.top = offsetY + 'px';
  distance = Math.sqrt(Math.pow(offsetX-startPos.x,2) + Math.pow(offsetY-startPos.y,2));
  duration = Date.now() - startTime;
}

function dragEnd(e) {
  let velocity = distance / duration;
  let direction = Math.atan2(offsetY-startPos.y, offsetX-startPos.x);
  let acceleration = velocity * 10;
  let startX = target.offsetLeft, startY = target.offsetTop;

  function animate() {
    let elapsed = Date.now() - startTime;
    let dx = startX + velocity * elapsed * Math.cos(direction);
    let dy = startY + velocity * elapsed * Math.sin(direction) + acceleration * Math.pow(elapsed, 2) / 2;
    if (elapsed < duration) {
      target.style.left = dx + 'px';
      target.style.top = dy + 'px';
      requestAnimationFrame(animate);
    } else {
      target.style.left = startX + distance * Math.cos(direction) + 'px';
      target.style.top = startY + distance * Math.sin(direction) + 'px';
    }
  }
  animate();
}
</script>

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:js实现盒子拖拽动画效果 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • 浅谈JS正则RegExp对象

    浅谈JS正则RegExp对象 正则表达式(Regular Expression)是一种文本模式,用于匹配一系列特定模式文本或字符。JavaScript中的正则表达式由RegExp对象表示。在JavaScript中,正则表达式主要用于字符串匹配和替换、字符串分割和字符串提取等场合。RegExp对象有很多属性和方法,下面我们来详细介绍一下。 RegExp对象的创…

    JavaScript 2023年5月27日
    00
  • js实现简单模态框实例

    这里是基于 Markdown 编写的攻略,以下将详细讲述如何使用 JavaScript 实现简单模态框。 简述 模态框(Modal)是一种弹出框的交互方式,即在页面的中心或者某个指定区域以弹窗的形式展示内容,遮罩层和窗口通常会阻止用户进行其他操作,只有完成当前操作或者关闭模态框后才能继续页面内的其他操作。 使用步骤 参考以下的实现步骤: 1.创建基本结构 我…

    JavaScript 2023年6月10日
    00
  • javascript 两个字符串比较函数

    下面是关于 JavaScript 字符串比较函数的完整攻略。 在 JavaScript 中比较字符串时,有两个比较函数可以使用: localeCompare():用于比较给定字符串与目标字符串的顺序关系,根据本地化规则和当前语言环境来进行比较,支持多种语言。该函数返回一个数字,表示两个字符串的大小关系。 charCodeAt():返回字符串中指定位置的字符的…

    JavaScript 2023年5月28日
    00
  • javascript中的有名函数和无名函数

    JavaScript中的函数可以分为有名函数和无名函数两种类型。有名函数为函数定义指定了一个名称,而无名函数则没有。 有名函数 函数定义 有名函数最基本的定义方式就是定义一个函数名,并编写函数体: function add(a, b) { return a + b; } 这是定义一个相加函数的示例,函数名为add,接受两个参数a和b,并返回a和b的和。 函数…

    JavaScript 2023年5月27日
    00
  • 如何实现chrome浏览器关闭页面时弹出“确定要离开此面吗?”

    要实现chrome浏览器关闭页面时弹出“确定要离开此页面吗?”,可以通过 JavaScript 中的 beforeunload 事件来实现。 具体步骤如下: 1. 在 HTML 文件中添加代码 在需要弹出确认窗口的页面中,添加以下代码: <script> window.addEventListener(‘beforeunload’, functi…

    JavaScript 2023年6月10日
    00
  • js中取得变量绝对值的方法

    当我们需要在 JavaScript 中获取一个变量的绝对值时,可以使用 Math 对象的 abs() 方法。下面是详细的攻略: 使用 Math.abs() 方法获取变量的绝对值 Math 对象是 JavaScript 提供的一个内置对象,通过该对象提供的 abs() 方法,即可获取任意数字类型的变量的绝对值。 let num1 = -5, num2 = 10…

    JavaScript 2023年5月28日
    00
  • JavaScript的DOM事件详解

    下面是JavaScript的DOM事件详解的完整攻略。 什么是DOM事件? DOM事件是指由DOM元素触发的事件,包括如下几种类型: 鼠标事件:click、mousedown、mousemove、mouseup、mouseover、mouseout、mouseenter、mouseleave等。 键盘事件:keydown、keypress、keyup等。 表…

    JavaScript 2023年6月10日
    00
  • 什么是jsonp

    jsonp 是前端一种用来解决网站跨域的技术,利用script标签不受同源策略影响的特性引入一个非同源的js文件,并定义一个回调函数来接收数据,这样就可以实现跨域获取数据了,例如:现在有一个链接返回的数据是这样的: cb({ “name”: “swk”, “age”: 18 }) 这是一个标准的jsonp格式,它通过调用函数cb来传递数据,那么我们只需要定义…

    JavaScript 2023年5月9日
    00
合作推广
合作推广
分享本页
返回顶部