Skip to content

Instantly share code, notes, and snippets.

@JSoon
Last active April 4, 2018 09:25
Show Gist options
  • Save JSoon/ec347df594a80fd5ab9a266d7e3cb501 to your computer and use it in GitHub Desktop.
Save JSoon/ec347df594a80fd5ab9a266d7e3cb501 to your computer and use it in GitHub Desktop.
JavaScript 简单拖拽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>拖拽</title>
<style>
html,
body {
margin: 0;
padding: 0;
}
#dragEle {
width: 200px;
height: 150px;
background: red;
}
</style>
</head>
<body>
<div id="dragEle"></div>
<script>
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Notes
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/attachEvent
//#region IE 8 support
(function () {
if (!Event.prototype.preventDefault) {
Event.prototype.preventDefault = function () {
this.returnValue = false;
};
}
if (!Event.prototype.stopPropagation) {
Event.prototype.stopPropagation = function () {
this.cancelBubble = true;
};
}
if (!Element.prototype.addEventListener) {
var eventListeners = [];
var addEventListener = function (type, listener /*, useCapture (will be ignored) */ ) {
var self = this;
var wrapper = function (e) {
e.target = e.srcElement;
e.currentTarget = self;
if (typeof listener.handleEvent != 'undefined') {
listener.handleEvent(e);
} else {
listener.call(self, e);
}
};
if (type == "DOMContentLoaded") {
var wrapper2 = function (e) {
if (document.readyState == "complete") {
wrapper(e);
}
};
document.attachEvent("onreadystatechange", wrapper2);
eventListeners.push({
object: this,
type: type,
listener: listener,
wrapper: wrapper2
});
if (document.readyState == "complete") {
var e = new Event();
e.srcElement = window;
wrapper2(e);
}
} else {
this.attachEvent("on" + type, wrapper);
eventListeners.push({
object: this,
type: type,
listener: listener,
wrapper: wrapper
});
}
};
var removeEventListener = function (type, listener /*, useCapture (will be ignored) */ ) {
var counter = 0;
while (counter < eventListeners.length) {
var eventListener = eventListeners[counter];
if (eventListener.object == this && eventListener.type == type && eventListener.listener ==
listener) {
if (type == "DOMContentLoaded") {
this.detachEvent("onreadystatechange", eventListener.wrapper);
} else {
this.detachEvent("on" + type, eventListener.wrapper);
}
eventListeners.splice(counter, 1);
break;
}
++counter;
}
};
Element.prototype.addEventListener = addEventListener;
Element.prototype.removeEventListener = removeEventListener;
if (HTMLDocument) {
HTMLDocument.prototype.addEventListener = addEventListener;
HTMLDocument.prototype.removeEventListener = removeEventListener;
}
if (Window) {
Window.prototype.addEventListener = addEventListener;
Window.prototype.removeEventListener = removeEventListener;
}
}
})();
//#endregion
var dom = document.getElementById('dragEle'); // 拖拽区DOM节点
var domW = dom.clientWidth; // 拖拽节点宽度(包含padding)
var domH = dom.clientHeight; // 拖拽节点高度(包含padding)
var domPointL; // 鼠标相对拖拽区域的左边距
var domPointR; // 鼠标相对拖拽区域的右边距
var domPointT; // 鼠标相对拖拽区域的上边距
var domPointB; // 鼠标相对拖拽区域的下边距
var dragEndFlag = true; // 拖拽是否已经结束(即鼠标松开,默认结束)
document.addEventListener('mousedown', dragStart, false); // 鼠标按下,拖拽开始
document.addEventListener('mouseup', dragEnd, false); // 鼠标松开,拖拽结束
document.addEventListener('mouseenter', dragMouseEnter, false); // 鼠标进入拖拽区
document.addEventListener('mouseleave', dragMouseLeave, false); // 鼠标离开拖拽区
function dragStart(e) {
// 若鼠标按下的坐标不在拖拽区,则不进行拖拽
// https://stackoverflow.com/questions/2642095/access-event-target-in-ie8-unobstrusive-javascript
// https://stackoverflow.com/questions/19371589/onchange-event-object-undefined-in-ie8
e = e || window.event; // get window.event if argument is falsy (in IE)
e.target = e.target || e.srcElement; // get srcElement if target is falsy (IE)
if (e.target !== dom) {
return;
}
// 鼠标初始拖拽点(相对于body)
var x = e.clientX; // 鼠标处据body左边距
var y = e.clientY; // 鼠标处据body上边距
// console.log(x, y);
// 鼠标初始拖拽点(相对于拖拽区域)
var domX = dom.offsetLeft; // 拖拽节点距body左边距
var domY = dom.offsetTop; // 拖拽节点距body上边距
domPointL = x - domX;
domPointR = domW - domPointL;
domPointT = y - domY;
domPointB = domH - domPointT;
document.addEventListener('mousemove', dragMove, false);
}
function dragEnd(e) {
dragEndFlag = true;
document.removeEventListener('mousemove', dragMove, false);
}
function dragMove(e) {
var x = e.clientX; // 鼠标处距body左边距
var y = e.clientY; // 鼠标处距body上边距
// console.log(x, y);
var domW = dom.clientWidth; // 拖拽节点宽度(包含padding)
var domH = dom.clientHeight; // 拖拽节点高度(包含padding)
var domX = dom.offsetLeft; // 拖拽节点距body左边距
var domY = dom.offsetTop; // 拖拽节点距body上边距
var viewportW = document.documentElement.clientWidth; // 窗口可视区域宽度
var viewportH = document.documentElement.clientHeight; // 窗口可视区域高度
// 移动拖拽节点
dom.style.position = 'fixed';
/**
* 限定拖拽节点的活动范围只能在浏览器窗口可视区域中
*
* 拖拽节点在可视区域中判断条件:
* 1. 鼠标相对浏览器窗口的左边距 - 相对拖拽区域的左边距 > 0
* 2. 鼠标相对浏览器窗口的左边距 + 相对拖拽区域的右边距 < 可视区域宽度
* 3. 鼠标相对浏览器窗口的上边距 - 相对拖拽区域的上边距 > 0
* 4. 鼠标相对浏览器窗口的上边距 + 相对拖拽区域的上边距 < 可视区域高度
* 5. 若非情况1,则拖拽节点左边距 = 0
* 6. 若非情况2,则拖拽节点左边距 = 可视区域宽度 - 拖拽节点宽度
* 5. 若非情况3,则拖拽节点上边距 = 0
* 5. 若非情况4,则拖拽节点上边距 = 可视区域高度 - 拖拽节点高度
*/
// 限定x轴上的移动
if (x - domPointL > 0 && x + domPointR < viewportW) {
dom.style.left = x - domPointL + 'px';
} else if (x - domPointL <= 0) {
dom.style.left = 0 + 'px';
} else if (x + domPointR >= viewportW) {
dom.style.left = viewportW - domW + 'px';
}
// 限定y轴上的移动
if (y - domPointT > 0 && y + domPointB < viewportH) {
dom.style.top = y - domPointT + 'px';
} else if (y - domPointT <= 0) {
dom.style.top = 0 + 'px';
} else if (y + domPointB >= viewportH) {
dom.style.top = viewportH - domH + 'px';
}
dragEndFlag = false;
}
function dragMouseEnter(e) {
// 若拖拽已结束,则不进行拖拽操作
if (dragEndFlag) {
return;
}
document.addEventListener('mousemove', dragMove, false);
}
function dragMouseLeave(e) {
document.removeEventListener('mousemove', dragMove, false);
}
</script>
</body>
</html>
@JSoon
Copy link
Author

JSoon commented Apr 4, 2018

新增IE8兼容代码

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment