首先,是最基本的面向过程的拖拽代码
1 2 3 4 5 6
| #box{ width: 100px; height: 100px; background-color: red; position: absolute; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| window.onload=function(){ var oDiv=document.getElementById('box'); var disX=0; var disY=0; oDiv.onmousedown=function(event){ var event=event||window.event; disX=event.clientX-oDiv.offsetLeft; disY=event.clientY-oDiv.offsetTop; document.onmousemove=function(event){ var event=event||window.event; oDiv.style.left=event.clientX-disX+'px'; oDiv.style.top=event.clientY-disY+'px'; } document.onmouseup=function () { document.onmousemove=null; document.onmouseup=null; } return false; } }
|
开始改写版本一
尽量不要出现函数嵌套函数
- 可以有全局变量
- 把onload中不是赋值的语句放在单独函数中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| var oDiv=null; var disX=0; var disY=0; window.onload=function(){ oDiv=document.getElementById('box'); init() } function init() { oDiv.onmousedown=fnDown; } function fnDown(event){ var event=event||window.event; disX=event.clientX-oDiv.offsetLeft; disY=event.clientY-oDiv.offsetTop; document.onmousemove=fnMove; document.onmouseup=fnUp; return false; } function fnMove(event){ var event=event||window.event; oDiv.style.left=event.clientX-disX+'px'; oDiv.style.top=event.clientY-disY+'px'; } function fnUp() { document.onmousemove=null; document.onmouseup=null; }
|
面向对象的改写 es5
- 全局变量就是属性
- 函数就是方法
- onload中创建对象
- 改this指向问题
在ie和谷歌下,这样是可以的,但是火狐下,应为有些地方为了this指向 嵌套了一层函数,但火狐可不这样,他认为event是事件函数传递的,也就是事件后面更着的函数,这是好就需要把event当做参数传递了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| window.onload=function(){ var d=new Drag('box'); d.init(); }
function Drag(id) { this.disX=0; this.disY=0; this.oDiv=document.getElementById(id); } Drag.prototype.init=function () { var _this=this; this.oDiv.onmousedown=function () { _this.fnDown() }; } Drag.prototype.fnDown=function (event) { var event=event||window.event; this.disX=event.clientX-this.oDiv.offsetLeft; this.disY=event.clientY-this.oDiv.offsetTop; var _this=this; document.onmousemove=function () { _this.fnMove() }; document.onmouseup=this.fnUp; return false; } Drag.prototype.fnMove=function (event) { var event=event||window.event; this.oDiv.style.left=event.clientX- this.disX+'px'; this.oDiv.style.top=event.clientY- this.disY+'px'; } Drag.prototype.fnUp=function () { document.onmousemove=null; document.onmouseup=null; }
|
但是火狐下报错:TypeError: event is undefined
火狐的解决办法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| window.onload = function () { var d = new Drag('box'); d.init(); }
function Drag(id) { this.disX = 0; this.disY = 0; this.oDiv = document.getElementById('box'); } Drag.prototype.init = function () { var _this = this; this.oDiv.onmousedown = function (event) { var event = event || window.event; _this.fnDown(event) }; } Drag.prototype.fnDown = function (event) { this.disX = event.clientX - this.oDiv.offsetLeft; this.disY = event.clientY - this.oDiv.offsetTop; var _this = this; document.onmousemove = function (event) { _this.fnMove(event) }; document.onmouseup = this.fnUp; return false; } Drag.prototype.fnMove = function (event) { this.oDiv.style.left = event.clientX - this.disX + 'px'; this.oDiv.style.top = event.clientY - this.disY + 'px'; } Drag.prototype.fnUp = function () { document.onmousemove = null; document.onmouseup = null; }
|
也可以吧init 放进构造函数里面,这样只要new 一个就可以生成拖拽了
,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| window.onload=function(){ var d=new Drag('box'); }
function Drag(id) { var _this=this; this.disX=0; this.disY=0; this.oDiv=document.getElementById('box'); this.oDiv.onmousedown=function (event) { var event=event||window.event; _this.fnDown(event) }; }
Drag.prototype.fnDown=function (event) { this.disX=event.clientX-this.oDiv.offsetLeft; this.disY=event.clientY-this.oDiv.offsetTop; var _this=this; document.onmousemove=function (event) { _this.fnMove(event) }; document.onmouseup=this.fnUp; return false; } Drag.prototype.fnMove=function (event) { this.oDiv.style.left=event.clientX- this.disX+'px'; this.oDiv.style.top=event.clientY- this.disY+'px'; } Drag.prototype.fnUp=function () { document.onmousemove=null; document.onmouseup=null; }
|
es6 面向对象的改写,也可以吧init 放进构造函数里面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| window.onload = function () { var d = new Drag('box'); d.init(); }
class Drag { constructor(id) { this.disX = 0; this.disY = 0; this.oDiv = document.getElementById(id); } init() { var _this = this; this.oDiv.onmousedown = function (event) { var event = event || window.event; _this.fnDown(event) }; } fnDown(event) { this.disX = event.clientX - this.oDiv.offsetLeft; this.disY = event.clientY - this.oDiv.offsetTop; var _this = this; document.onmousemove = function (event) { _this.fnMove(event) }; document.onmouseup = this.fnUp; return false; } fnMove(event) { this.oDiv.style.left = event.clientX - this.disX + 'px'; this.oDiv.style.top = event.clientY - this.disY + 'px'; } fnUp() { document.onmousemove = null; document.onmouseup = null; } }
|
初步总结
- 原则
先写出普通的写法,然后改写成面向对象的写法
普通方法变形
- 尽量不要出现函数嵌套函数
- 可以有全局变量
- 把onload中不是赋值的语句放在单独函数中
改写面向对象
- 全局变量就是属性
- 函数就是方法
- onload中创建对象
- 改this指向问题
说了这么多,我们来封装一个拖拽组件吧
组件就该可以自自定义样式吧~~~~~,data-config写入自定义的样式,有人说你怎么怎么鸡肋,不如css里面写写快,但也是可以不写的,有默认参数,js里面已经写好了,如果data-config写了的话是可以覆盖js里面的,具体看js代码
1 2 3 4 5 6 7
| <div id="box1" data-config='{"width": "100px","height": "100px","backgroundColor": "black","position": "absolute"}'></div> <script src="./index.js"></script> <script> var div1 = new Drag('box1'); div1.init(); </script>
|
尽量让用户少写css,那你就帮他考虑周全吧
1 2 3 4 5 6 7 8
| *{ padding: 0; margin: 0; } div{ width: 200px; height: 200px; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| (function () { class Drag { constructor (id) { this.disX = 0; this.disY = 0; this.oDiv = document.getElementById(id); this.config = { 'width': '200px', 'height': '200px', 'backgroundColor': 'red', 'position': 'absolute' }; if (this.getConfig()) { Object.assign(this.config, this.getConfig()); } console.log(this.config); this.init(); } getConfig () { var config = this.oDiv.getAttribute('data-config'); if (config && config !== '') { return JSON.parse(config); } else { return null; } } init () { var _this = this; this.oDiv.onmousedown = function (ev) { _this.fnDown(ev, _this); }; for (const i in this.config) { this.oDiv.style[i] = this.config[i]; } } fnDown (ev, _this) { this.disX = ev.clientX - this.oDiv.offsetLeft; this.disY = ev.clientY - this.oDiv.offsetTop; document.onmousemove = function (ev) { _this.fnMove(ev); }; document.onmouseup = this.fnUp; return false; } fnMove (ev) { this.oDiv.style.left = ev.clientX - this.disX + 'px'; this.oDiv.style.top = ev.clientY - this.disY + 'px'; }; fnUp () { document.onmousemove = null; document.onmouseup = null; } } window.Drag = Drag; })();
|
你说啥??不支持手机端??那就来支持一下吧
支持的不够怎么完美,见谅。。
1 2 3 4 5 6 7 8 9 10
|
var touch; if (ev.touches) { touch = ev.touches[0]; } else { touch = ev; } this.disX = touch.clientX - this.oDiv.offsetLeft; this.disY = touch.clientY - this.oDiv.offsetTop;
|
pc上的web页面鼠 标会产生onmousedown、onmouseup、onmouseout、onmouseover、onmousemove的事件,但是在移动终端如 iphone、Touch、ipad,android上的web页面触屏时会产生ontouchstart、ontouchmove、ontouchend、ontouchcancel 事件,分别对应了触屏开始、拖拽及完成触屏事件和取消。
当按下手指时,触发ontouchstart;
当移动手指时,触发ontouchmove;
当移走手指时,触发ontouchend。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
|
(function () { class Drag { constructor(id) { this.disX = 0; this.disY = 0; this.oDiv = document.getElementById(id); this.config = { 'width': '200px', 'height': '200px', 'backgroundColor': 'red', 'position': 'absolute' }; if (this.getConfig()) { Object.assign(this.config, this.getConfig()); } console.log(this.config); this.init(); } getConfig() { var config = this.oDiv.getAttribute('data-config'); if (config && config !== '') { return JSON.parse(config); } else { return null; } } init() { var _this = this; this.oDiv.onmousedown = function (ev) { _this.fnDown(ev, _this); }; this.oDiv.ontouchstart=function(ev){ _this.fnDown(ev, _this); } for (const i in this.config) { this.oDiv.style[i] = this.config[i]; } } fnDown(ev, _this) { var touch; if (ev.touches) { touch = ev.touches[0]; } else { touch = ev; } this.disX = touch.clientX - this.oDiv.offsetLeft; this.disY = touch.clientY - this.oDiv.offsetTop; document.onmousemove = function (ev) { _this.fnMove(ev); }; document.ontouchmove = function (ev) { _this.fnMove(ev); }; document.onmouseup = this.fnUp; document.ontouchend = this.fnUp; return false; } fnMove(ev) { var touch; if (ev.touches) { touch = ev.touches[0]; } else { touch = ev; } this.oDiv.style.left = touch.clientX - this.disX + 'px'; this.oDiv.style.top = touch.clientY - this.disY + 'px'; }; fnUp() { document.onmousemove = null; document.ontouchmove = null; document.onmouseup = null; document.ontouchend = null; } } window.Drag = Drag; })();
|
传送门:点击查看演示
点击查看源码