首先,是最基本的程式導向的拖拽程式碼
/*css*/
<style>
#box{
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
</style>
/*html*/
<div id="box"></div>
/*js*/
<script>
window.onload=function(){
var oDiv=document.getElementById('box');
var disX=0;
var disY=0;
oDiv.onmousedown=function(event){
//獲取事件物件
var event=event||window.event;
// disX相當於滑鼠到div左側的距離,同理disY
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;
}
}
</script>
複製程式碼
開始改寫版本一
儘量不要出現函式巢狀函式
- 可以有全域性變數
- 把onload中不是賦值的語句放在單獨函式中
<script>
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;
}
</script>
複製程式碼
物件導向的改寫 es5
- 全域性變數就是屬性
- 函式就是方法
- onload中建立物件
- 改this指向問題
在ie和谷歌下,這樣是可以的,但是火狐下,應為有些地方為了this指向 巢狀了一層函式,但火狐可不這樣,他認為event是事件函式傳遞的,也就是事件後面更著的函式,這是好就需要把event當做引數傳遞了
<script>
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 () {
// 這裡的this 指向的是Drag這個類
var _this=this;
this.oDiv.onmousedown=function () { //這裡巢狀一層是為了解決若寫成this.fnDown的話,下面fnDown裡面的this就會變成this.oDiv,相當於this就變成div了
// 匿名函式裡的this是指window,因為this指的是呼叫他的物件,但是匿名函式不知道是誰呼叫的,所以可以認為是被window呼叫的
_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;
}
</script>
複製程式碼
但是火狐下報錯:TypeError: event is undefined
火狐的解決辦法
<script>
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) { //巢狀是為了解決this問題
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;
}
</script>
複製程式碼
也可以吧init 放進建構函式裡面,這樣只要new 一個就可以生成拖拽了 ,如下所示
<script>
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) { //巢狀是為了解決this問題
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;
}
</script>
複製程式碼
es6 物件導向的改寫,也可以吧init 放進建構函式裡面
<script>
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;
}
}
</script>
複製程式碼
初步總結
- 原則
先寫出普通的寫法,然後改寫成物件導向的寫法
普通方法變形
- 儘量不要出現函式巢狀函式
- 可以有全域性變數
- 把onload中不是賦值的語句放在單獨函式中
改寫物件導向
- 全域性變數就是屬性
- 函式就是方法
- onload中建立物件
- 改this指向問題
說了這麼多,我們來封裝一個拖拽元件吧
元件就該可以自自定義樣式吧~~~~~,data-config寫入自定義的樣式,有人說你怎麼怎麼雞肋,不如css裡面寫寫快,但也是可以不寫的,有預設引數,js裡面已經寫好了,如果data-config寫了的話是可以覆蓋js裡面的,具體看js程式碼
<body>
<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,那你就幫他考慮周全吧
*{
padding: 0;
margin: 0;
}
div{
width: 200px;
height: 200px;
}
複製程式碼
// 外層包裹防止函式被汙染
(function () {
// Drag 類
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,為了下面不在重複寫 */
_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;
})();
複製程式碼
你說啥??不支援手機端??那就來支援一下吧
支援的不夠怎麼完美,見諒。。
// 在fnDown裡面先判斷一下
// 判斷是否為手機端
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。
// 原理還是一樣的
// js程式碼如下
(function () {
// Drag 類
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;
// pc端
this.oDiv.onmousedown = function (ev) {
/* 傳入_this,為了下面不在重複寫 */
_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;
// pc
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;
})();
複製程式碼