https://segmentfault.com/a/1190000012646488 https://yangbo5207.github.io/wutongluo/
说明:此处只是记录阅读前端基础进阶的理解和总结,如有需要请阅读上面的链接
1.如何让元素动起来
要让元素动起来就要修改元素的top、left 、translate 属性。因为使用top、left会使页面重绘,而translate不会,所以从性能上一般优先使用translate。另外因为translate是transform的一个用法,而transform是css3中的所以需要判断一下浏览器是否支持,不同的浏览器写法大概有几种
['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform']
//判断当前浏览器支持哪种transform function getTransform() { var transform = ''; var divStyle = document.createElement("div").style; //不同的浏览器大概支持如下几种transform var transArray = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'] for (var x in transArray) { if (transArray[x] in divStyle) return transform = transArray[x]; } return transform; }
2.获取元素初始位置
//获取目标元素样式 function getStyle(elem, property) { //ie 通过currentStyle获取样式,其他浏览器通过getComputedStyle,getComputedStyle是一个方法 return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(elem, false)[property] : elem.currentStyle[property]; } //获取元素的初始位置 function getTargetPos(elem) { var pos = { x: 0, y: 0 }; var transform = getTransform(); if (transform ) { var transformValue = getStyle(elem,transform); if (transformValue == 'none') { elem.style[transform] = 'translate(0, 0)'; return pos; } else { console.log(transformValue); var temp = transformValue.match(/[0-9,\s\.]+/)[0].split(','); return pos = { x: parseInt(temp[4].trim()), y: parseInt(temp[5].trim()) }; } } else { if (getStyle(elem, 'position') == 'static') { elem.style.position = 'relative'; return pos; } else { var x = parseInt(getStyle(elem, 'left') ? getStyle(elem, 'left') : 0); var y = parseInt(getStyle(elem, 'top') ? getStyle(elem, 'top') : 0); return pos = { x: x, y: y }; } } }
设置元素位置
//设置元素位置 function setTargetPos(elem, pos) { var transform = getTransform(); if (transform != "") { elem.style[transform] = "translate(" + pos.x + "px," + pos.y + "px)"; } else { elem.style.left = pos.x + "px"; elem.style.top = pos.y + "px"; } return elem; }
3.事件
拖拽的原理:mousedown记录元素和鼠标的初始位置,添加mousemove、mouseup事件,mousemove事件随着鼠标移动获取鼠标当前位置。移动后的鼠标位置-鼠标的初始位置=移动后的元素位置-元素的初始位置,如果用diss表示移动后的鼠标位置-鼠标的初始位置,那么元素移动后的位置=元素的初始位置+diss。这样在鼠标移动时就可以得到元素的位置。mouseup移除mousemove、mouseup事件和做其他处理
function start(event) { startX = event.pageX; //获取鼠标初始位置 startY = event.pageY; var pos = getTargetPos(oElem); sourceX = pos.x; sourceY = pos.y; document.addEventListener('mousemove', move, false); document.addEventListener('mouseup', end, false); } function move(event) { var currentX = event.pageX; var currentY = event.pageY; var distanceX = currentX - startX; var distanceY = currentY - startY; setTargetPos(oElem, { x: (sourceX + distanceX).toFixed(), y: (sourceY + distanceY).toFixed() }); } function end(event) { document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', end); }
完整的js代码
var oElem = document.getElementById("div1"); //document.getElementById("div1")必须在元素加载完成后才能获取到元素,所以这个JavaScript必须放在body后,否则返回null var startX = 0; var startY = 0; var sourceX = 0; var sourceY = 0; oElem.addEventListener('mousedown', start, false); //获取目标元素样式 function getStyle(elem, property) { //ie 通过currentStyle获取样式,其他浏览器通过getComputedStyle,getComputedStyle是一个方法 return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(elem, false)[property] : elem.currentStyle[property]; } //判断当前浏览器支持哪种transform function getTransform() { var transform = ''; var divStyle = document.createElement("div").style; //不同的浏览器大概支持如下几种transform var transArray = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'] for (var x in transArray) { if (transArray[x] in divStyle) return transform = transArray[x]; } return transform; } //获取元素的初始位置 function getTargetPos(elem) { var pos = { x: 0, y: 0 }; var transform = getTransform(); if (transform ) { var transformValue = getStyle(elem,transform); if (transformValue == 'none') { elem.style[transform] = 'translate(0, 0)'; return pos; } else { var temp = transformValue.match(/[0-9,\s\.]+/)[0].split(','); return pos = { x: parseInt(temp[4].trim()), y: parseInt(temp[5].trim()) }; } } else { if (getStyle(elem, 'position') == 'static') { elem.style.position = 'relative'; return pos; } else { var x = parseInt(getStyle(elem, 'left') ? getStyle(elem, 'left') : 0); var y = parseInt(getStyle(elem, 'top') ? getStyle(elem, 'top') : 0); return pos = { x: x, y: y }; } } } //设置元素位置 function setTargetPos(elem, pos) { var transform = getTransform(); if (transform != "") { elem.style[transform] = "translate(" + pos.x + "px," + pos.y + "px)"; } else { elem.style.left = pos.x + "px"; elem.style.top = pos.y + "px"; } return elem; } function start(event) { startX = event.pageX; //获取鼠标初始位置 startY = event.pageY; var pos = getTargetPos(oElem); sourceX = pos.x; sourceY = pos.y; document.addEventListener('mousemove', move, false); document.addEventListener('mouseup', end, false); } function move(event) { var currentX = event.pageX; var currentY = event.pageY; var distanceX = currentX - startX; var distanceY = currentY - startY; setTargetPos(oElem, { x: (sourceX + distanceX).toFixed(), y: (sourceY + distanceY).toFixed() }); } function end(event) { document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', end); }
我们可以把以上代码封装到一个模块里面,使用的时候只要传元素Id就可以了。
; (function () { var transform = getTransform(); //构造函数 function Drag(selector) { this.elem = typeof selector == 'Object' ? selector : document.getElementById(selector); this.startX = 0; this.startY = 0; this.sourceX = 0; this.sourceY = 0; this.init();//初始化 } //原型 Drag.prototype = { constructor: Drag, init: function () { this.setDrag(); }, //获取目标元素样式 getStyle: function (property) { //ie 通过currentStyle获取样式,其他浏览器通过getComputedStyle,getComputedStyle是一个方法 return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(this.elem, false)[property] : this.elem.currentStyle[property]; }, //获取元素的初始位置 getTargetPos: function () { var pos = { x: 0, y: 0 }; if (transform != "") { var transformValue = this.getStyle(transform); if (transformValue == 'none') { this.elem.style[transform] = 'translate(0, 0)'; return pos; } else { var temp = transformValue.match(/[0-9,\s\.]+/)[0].split(','); return pos = { x: parseInt(temp[4].trim()), y: parseInt(temp[5].trim()) }; } } else { if (this.getStyle(this.elem, 'position') == 'static') { this.elem.style.position = 'relative'; return pos; } else { var x = parseInt(this.getStyle('left') ? this.getStyle('left') : 0); var y = parseInt(this.getStyle('top') ? this.getStyle('top') : 0); return pos = { x: x, y: y }; } } }, //设置元素位置 setTargetPos: function (pos) { if (transform != "") { this.elem.style[transform] = "translate(" + pos.x + "px," + pos.y + "px)"; } else { this.elem.style.left = pos.x + "px"; this.elem.style.top = pos.y + "px"; } }, setDrag: function () { var self = this;//因为绑定的方法是独立执行的,this指向并不是Drag对象,所以必须使用闭包 this.elem.addEventListener('mousedown', start, false); function start(event) { self.startX = event.pageX; //获取鼠标初始位置 self.startY = event.pageY; var pos = self.getTargetPos(); self.sourceX = pos.x; self.sourceY = pos.y; document.addEventListener('mousemove', move, false); document.addEventListener('mouseup', end, false); } function move(event) { var currentX = event.pageX; var currentY = event.pageY; var distanceX = currentX - self.startX; var distanceY = currentY - self.startY; self.setTargetPos({ x: (self.sourceX + distanceX).toFixed(), y: (self.sourceY + distanceY).toFixed() }); } function end(event) { document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', end); } } } // 私有方法,仅仅用来获取transform的兼容写法 function getTransform() { var transform = '', divStyle = document.createElement('div').style, transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'], i = 0, len = transformArr.length; for (; i < len; i++) { if (transformArr[i] in divStyle) { return transform = transformArr[i]; } } return transform; } window .Drag=Drag;//对外暴露构造方法 })(); new Drag('div1');//拖拽实例