本文通过拖拽案例,实现“跟随鼠标、边界限定、轨迹回放”三大效果;

完整代码中有详尽注释,故不再进行细致讲解;

对于案例中需要注意的重点或易错点问题,会总结在最后。

效果图(仅演示左、上边界限定)

完整代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>盒子拖拽</title>
<style>
body{
margin: 0;
padding: 0;
}
#box{
width: 100px;
height: 100px;
background: skyblue;
position: absolute;
/* 盒子在页面中的初始位置,可以随意设置 */
left: 200px;
top: 200px;
}
#btn{
display: inline-block;
width: 80px;
height: 30px;
font-size: 16px;
cursor: pointer;
outline: none;
}
</style>
</head>
<body>
<div id="box"><button id="btn">轨迹回放</button></div>
<script>
var box_ele = document.getElementById("box");
// 声明位置数组,用于记录盒子每次移动后的位置
var position_arr = [];
// 获取页面初始宽高,用于限定盒子移动边界
var screen_width = document.body.offsetWidth;
var screen_height = window.innerHeight; // 注意页面高度不能通过 document.body.offsetTop 获取 // 功能1:拖拽
// 设置变量记录鼠标的状态,鼠标按下时为true
var flag = false;
// 鼠标按下准备拖拽,记录鼠标按下时的位置
var mouse_x, mouse_y;
box_ele.addEventListener("mousedown", function(evt){
flag = true;
var e = evt || event;
mouse_x = e.offsetX; // 要以元素做参照物,用offset,不能用client
mouse_y = e.offsetY;
// 将盒子初始位置(盒子元素偏移量)记录在位置数组中
position_arr.push({
x : box_ele.offsetLeft,
y : box_ele.offsetTop
})
})
// 鼠标移动拖拽开始
// 事件绑定在document上,避免因鼠标移动速度太快超出盒子边界时盒子跟不上
document.addEventListener("mousemove", function(evt){
if(flag){
var e = evt || event;
// 声明盒子的位置
var box_left = e.clientX - mouse_x;
var box_top = e.clientY - mouse_y;
// 通过页面初始宽高和盒子宽高计算获得盒子移动的最大值
var move_width_max = screen_width - box_ele.offsetWidth;
var move_height_max = screen_height - box_ele.offsetHeight;
// 分别限定盒子移动的左右上下边界
box_left = box_left <= 0 ? 0 : box_left;
box_left = box_left >= move_width_max ? move_width_max : box_left;
box_top = box_top <= 0 ? 0 : box_top;
box_top = box_top >= move_height_max ? move_height_max : box_top;
// 将数据赋值给盒子从而在页面中渲染
box_ele.style.left = box_left + "px";
box_ele.style.top = box_top + "px";
// 若x或y方向移动距离大于5px,则将移动后的盒子位置记录到位置数组中(避免数组中保存数据过多,消耗性能)
if(box_left >= position_arr[position_arr.length - 1].x + 5 || box_top >= position_arr[position_arr.length - 1].y + 5){
position_arr.push({
x : box_left,
y : box_top
})
} }
}) // 鼠标抬起拖拽停止
box_ele.addEventListener("mouseup", function(){
flag = false;
}) // 功能2:回放
var btn_ele = document.getElementById("btn");
var timer;
btn_ele.addEventListener("click", function(){
// 原思路:通过for循环遍历位置数组中的每一个位置
// 由于for循环执行太快,故使用定时器
timer = setInterval(function(){
// 每次取出位置数组中的最后一个元素位置
var last_position = position_arr.pop();
box_ele.style.left = last_position.x + "px";
box_ele.style.top = last_position.y + "px";
// 当移动到最后一个位置(即位置数组中数据为空)时,关闭定时器
if(position_arr.length === 0){
clearInterval(timer);
}
}, 50)
})
</script>
</body>
</html>

注意点

1、鼠标拖拽过程中的盒子位置需要通过 鼠标位置 - 初始时鼠标相对于元素位置 获取,即

box_left = e.clientX - mouse_x

box_top = e.clientY - mouse_y;

否则盒子会出现在鼠标的右下方。

2、初始的页面高度不能通过 document.body.offsetTop 获取,需要用 window.innerHeight

3、限制鼠标移动边界时,宽高方向的最大值需要通过 初始页面宽高 - 盒子宽高 获取,即

move_width_max = screen_width - box_ele.offsetWidth;

move_height_max = screen_height - box_ele.offsetHeight;

4、轨迹回放时,目标是位置数组中从后往前依次取出元素,最好的办法就是使用 pop()

5、注意定时器的关闭条件。position_arr.length === 0

Javascript之盒子拖拽(跟随鼠标、边界限定、轨迹回放)的更多相关文章

  1. 每天一个JavaScript实例-html5拖拽

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  2. day25—JavaScript实现文件拖拽上传案例实践

    转行学开发,代码100天——2018-04-10 今天记录一个利用JavaScript实现文件拖拽上传到浏览器,后天将文件打开的小案例. 基本功能:1点击添加文件 2 文件拖拽添加 html: < ...

  3. day23—JavaScript实现DIV盒子拖拽(原生方式)

    转行学开发,代码100天——2018-04-08 <!doctype html> <html> <head> <meta charset="utf- ...

  4. JavaScript动画-模拟拖拽

    模拟拖拽的原理: x1等于div.offsetLeft y1等于div.offsetTop x2等于ev.clientX(ev表示event事件) y2等于ev.clientY 当我们在方块上按下鼠标 ...

  5. QTGraphics-View拖拽以及鼠标指针操作

    因为QGraphicsView继承自QWidget,它也提供了像QWidget那样的拖拽功能. 另外,为了方便,Graphics View框架也为场景以及每个item提供拖拽支持.当视图接收到拖拽事件 ...

  6. JavaScript实现图片拖拽、粘贴上传

    前些日子为老婆做了一个web管理商品的工具,因为商品的图片比较多并且还需要剪裁图,为了上传图片方便加了一个拖拽.粘贴上传的功能. 我已经把代码整理出来放到GitHub上了,有兴趣的朋友可以下来玩玩. ...

  7. javascript实现的拖拽回放

    这个功能很简单,直接贴代码啊: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ht ...

  8. 超级简单的利用javascript实现文件拖拽事件

    1.效果图: 2.源码 <%@ page contentType="text/html;charset=UTF-8" language="java" %& ...

  9. JavaScript 面向对象的拖拽

    一.body <div id="box"></div> 二.css <style> #box { position: abaolute; top ...

随机推荐

  1. USB小白学习之路(11) Cy7c68013A驱动电路设计注意事项(转)

    Cy7c68013A驱动电路设计注意事项 转自:http://group.chinaaet.com/116/79029#0-tsina-1-71467-397232819ff9a47a7b7e80a4 ...

  2. Oracle密码验证函数与Create Profile

    今天看到了一个oracle密码函数的东西,就在网上找文档自己做测试,刚开始看不懂,最后做完记录一下 密码函数的作用就是要将用户密码进行限制,比如申请一个网站的账号的时候,密码会要求你不少于8位,必须要 ...

  3. 对象深拷贝deepCopy

    function type(obj){ return Object.prototype.toString.call(obj).slice(8,-1); } function deepCopy(targ ...

  4. Roma - Facebook工具链大一统

    什么是roma roma,中文名罗马,是Facebook的rn团队的产出,是一个试验性质的javascript工具链,集编译,linter,格式化,打包,测试等等于一体.目标是成为一个处理javasc ...

  5. 微信Android自动播放视频(可交互,设置层级,无控制条,非X5)ffmpeg,jsmpeg.js,.ts视频

    原料: ffmpeg : http://ffmpeg.zeranoe.com/builds/  win64 https://evermeet.cx/ffmpeg/   mac OS X 64 jsmp ...

  6. 盘点Mac上搭建本地WebServer的几种方式

    第一种: 通过Nginx搭建本地WebServer 安装nginx brew install nginx 安装完后在终端输入nginx指令,启动nginx查看效果 确定安装好之后,在根目录创建一个文件 ...

  7. Aircrack-ng无线审计工具破解无线密码

    Aircrack-ng工具 Aircrack-ng是一个与802.11标准的无线网络分析的安全软件,主要功能有网络探测.数据包嗅探捕获.WEP和WPA/WPA2-PSK破解.Aircrack可以工作在 ...

  8. MATLAB神经网络(1)之R练习

    )之R练习 将在MATLAB神经网络中学到的知识用R进行适当地重构,再写一遍,一方面可以加深理解和记忆,另一方面练习R,比较R和MATLAB的不同.如要在R中使用之前的数据,应首先在MATLAB中用w ...

  9. C语言程序设计(九) 指针

    第九章 指针 C程序中的变量都是存储在计算机内存特定的存储单元中的,内存中的每个单元都有唯一的地址 通过取地址运算符&可以获得变量的地址 //L9-1 #include <stdio.h ...

  10. Python 装饰器(无参,有参、多重))

    Python装饰器介绍 在Python中,装饰器(decorator)是在闭包的基础上发展起来的. 装饰器的实质是一个高阶函数,其参数是要装饰的函数名,其返回值是完成装饰的函数名,其作用是为已经存在的 ...