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

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

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

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

完整代码

<!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. e代驾狂野裁员 O2O逐渐恢复理智?

    O2O逐渐恢复理智?" title="e代驾狂野裁员 O2O逐渐恢复理智?">     近段时间以来,O2O行业堪称"哀鸿遍野",十分凄惨.巨头 ...

  2. Linux sed命令实例解析

    最近看project的makefile,又见到了sed的强大编辑能力,在makefile工作之前,通常都是执行脚本或者make menuconfig来配置好各种全局变量.sed活动阶段通常在bash ...

  3. iPhone8的十面埋伏

    ​ 不知不觉,iPhone已经走到了第十个年头,也正因如此,业界最普遍的预测就是:iPhone8会出现颠覆性创新,让人眼前一亮的同时,给苹果再度续命.平心而论,苹果早就青史留名,创造了大量的奇迹,科技 ...

  4. 滑动表层div时 禁止底层滑动

    $(".container").bind("touchstart", function (events) { startX = events.originalE ...

  5. 跟我猜Spring-Boot:bean的创建

    废话在前 最近几年的技术路子很杂,先是node,然后是php,后来是openresty,再后来转到了java,而接触的框架(Framework),也越发的复杂,从最开始的express/koa,到lu ...

  6. Promise,Generator,Await/Async

    上节中忘记讲:Iterator接口和Generator函数的关系了,Symbol.iterator方法的最简单的实现就是通过Generator函数: let myIterable = { [Symbo ...

  7. Web安全相关(一):CSRF/XSRF(跨站请求伪造)和XSS(跨站脚本)

    XSS(Cross Site Script):跨站脚本,也就是javascript脚本注入,一般在站点中的富文本框,里面发表文章,留言等表单,这种表单一般是写入数据库,然后再某个页面打开. 防御: 1 ...

  8. AlphaGo、人工智能、深度学习解读以及应用

    经过比拼,AlphaGo最终还是胜出,创造了人机大战历史上的一个新的里程碑.几乎所有的人都在谈论这件事情,这使得把“人工智能”.“深度学习”的热潮推向了新的一个高潮.AlphaGo就像科幻电影里具有人 ...

  9. 【WPF学习】第五十八章 理解逻辑树和可视化树

    在前面章节中,花费大量时间分析了窗口的内容模型——换句话说,研究了如何在其他元素中嵌套元素,进而构建完整的窗口. 例如,考虑下图中显示的一个非常简单的窗口,该窗口包含两个按钮.为创建该按钮,在窗口中嵌 ...

  10. H5系列一、静态页面总结

    1.img父标签设置高度,如果容器没有设置高度的话,图片会默认把容器底部撑大几像素 -- 大概3px,给容器设置高度. 2.input标记换行后默认有一个间隙,设置float属性.input标记默认还 ...