92JavaScript:原生位置交换

九宫格,里面有九张图片,用鼠标拖动其中1张图片置于另1张图片之上时并松开鼠标后,它俩的位置交换。
**html 代码**

```html:run
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>九宫格--位置交换</title>
<style type="text/css">
* {
padding: 0;
margin: 0;
list-style: none;
}

ul {
width: 480px;
height: 480px;
padding: 5px;
background: #CFC;
position: relative;
margin: 100px auto;
}

li {
width: 150px;
height: 150px;
margin: 5px;
cursor: move;
-webkit-user-select: none;
background: #FF9;
overflow: hidden;
float: left;
}

img {
width: 100%;
height: 100%;
border: none;
}

</style>
</head>

<body>
<ul>
<li><img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=46ac759c68ba5e51fc613502729240cf"></li>
<li><img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=46ac759c68ba5e51fc613502729240cf"></li>
<li><img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=46ac759c68ba5e51fc613502729240cf"></li>
<li><img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=46ac759c68ba5e51fc613502729240cf"></li>
<li><img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=46ac759c68ba5e51fc613502729240cf"></li>
<li><img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=46ac759c68ba5e51fc613502729240cf"></li>
<li><img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=46ac759c68ba5e51fc613502729240cf"></li>
<li><img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=46ac759c68ba5e51fc613502729240cf"></li>
<li><img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=46ac759c68ba5e51fc613502729240cf"></li>
</ul>
</body>
</html>

<script>
/*第一步:准备方法*/
function on(ele, type, fn) {
if (ele.addEventListener) {
ele.addEventListener(type, fn, false);

} else {
if (!ele["onEvent" + type]) {
ele["onEvent" + type] = [];
ele.attachEvent("on" + type, function () {
run.call(ele)
});
}
var a = ele["onEvent" + type];
for (var i = 0; i < a.length; i++) {
if (a[i] == fn)return;
}
a.push(fn);
}
}

function run() {
var e = window.event;
var type = e.type;
e.target = e.srcElement;
e.pageX = (document.documentElement.scrollLeft || document.body.scrollLeft) + e.clientX;
e.pageY = (document.documentElement.scrollTop || document.body.scrollTop) + e.clientY;
e.preventDefault = function () {
e.returnValue = false;
};
e.stopPropagation = function () {
e.cancelBubble = true;
};
var a = this["onEvent" + type];
if (a && a.length) {
for (var i = 0; i < a.length; i++) {
if (typeof a[i] == "function") {
a[i].call(this, e);
} else {
a.splice(i, 1);
i--;
}
}
}
}

function off(ele, type, fn) {
if (ele.removeEventListener) {
ele.removeEventListener(type, fn, false);
} else {
var a = ele["onEvent" + type];
if (a && a.length) {
for (var i = 0; i < a.length; i++) {
if (a[i] == fn) {
a[i] = null;
return;
}
}
}
}
}

function processThis(fn, context) {
return function (e) {
fn.call(context, e);
};
}

function EventEmitter() {
}
EventEmitter.prototype.on = function (type, fn) {
if (!this["emitter" + type]) {
this["emitter" + type] = [];
}
var a = this["emitter" + type];
for (var i = 0; i < a.length; i++) {
if (a[i] == fn)return this;
}
a.push(fn);
return this;
};
EventEmitter.prototype.run = function (type, e) {
var a = this["emitter" + type];
if (a && a.length) {
for (var i = 0; i < a.length; i++) {
if (typeof a[i] == "function") {
a[i].call(this, e);
} else {
a.splice(i, 1);
i--;
}
}
}
};
EventEmitter.prototype.off = function (type, fn) {
var a = this["emitter" + type];
if (a && a.length) {
for (var i = 0; i < a.length; i++) {
if (a[i] == fn) {
a[i] = null;
break;
}
}
}
return this;
};

function Drag(ele) {
this.x = null;
this.y = null;
this.mx = null;
this.my = null;
this.ele = ele;
this.obj = ele;
this.DOWN = processThis(this.down, this);
this.MOVE = processThis(this.move, this);
this.UP = processThis(this.up, this);
on(this.ele, "mousedown", this.DOWN);//对于这个on来说,我们只是使用者
//this.on;对于这个on来说,我们是开发者,
}
Drag.prototype.__proto__ = EventEmitter.prototype;
//这是更安全的继承方法,一般在Node里都是采用这种方式实现继承。IE不支持
Drag.prototype = new EventEmitter;//相对这种方式来说,上边的写法更安全
Drag.prototype.down = function (e) {
this.x = this.ele.offsetLeft;
this.y = this.ele.offsetTop;
this.mx = e.pageX;
this.my = e.pageY;
if (this.ele.setCapture) {
this.ele.setCapture();
on(this.ele, "mousemove", this.MOVE);
on(this.ele, "mouseup", this.UP);
} else {
on(document, "mousemove", this.MOVE);
on(document, "mouseup", this.UP);
}
e.preventDefault();
this.run("abcde1", e);
};
Drag.prototype.move = function (e) {
this.ele.style.left = this.x + (e.pageX - this.mx) + "px";
this.ele.style.top = this.y + (e.pageY - this.my) + "px";
this.run("abcde2", e);
};
Drag.prototype.up = function (e) {
if (this.ele.releaseCapture) {
this.ele.releaseCapture();
off(this.ele, "mousemove", this.MOVE);
off(this.ele, "mouseup", this.UP);
} else {
off(document, "mousemove", this.MOVE);
off(document, "mouseup", this.UP);
}
this.run("abcde3", e);
};

var oRange = {l: 0, r: 600, t: 0, b: 300};
//相当于重新写了一个计算元素拖拽位置的方法,用这个方法,把原来的Drag.prototype.move覆盖掉
Drag.prototype.addRange = function (obj) {
this.oRange = obj;
this.on("abcde2", this.range);
};
Drag.prototype.range = function range(e) {
var oRange = this.oRange;
var l = oRange.l, r = oRange.r, t = oRange.t, b = oRange.b;
var currentL = this.x + (e.pageX - this.mx);
var currentT = this.y + (e.pageY - this.my);
if (currentL >= r) {
this.ele.style.left = r + "px";
} else if (currentL <= l) {
this.ele.style.left = l + "px";
} else {
this.ele.style.left = currentL + "px";
}
if (currentT >= b) {
this.ele.style.top = b + "px";
} else if (currentT <= t) {
this.ele.style.top = t + "px";
} else {
this.ele.style.top = currentT + "px";
}
};

Drag.prototype.border = function (width, color, style) {
//允许不传参数,如果参数没有传,则这里给它指定默认的值
if (!width)width = "2";
if (!color)color = "#666";
if (!style)style = "dashed";
this.borderStyle = {width: width, color: color, style: style};
this.on("abcde1", this.addBorder);
this.on("abcde3", this.removeBorder);
};
Drag.prototype.addBorder = function () {
var bs = this.borderStyle;
this.ele.style.border = bs.width + "px " + bs.color + " " + bs.style;
};
Drag.prototype.removeBorder = function () {
this.ele.style.border = "none";
};


function Linear(t, b, c, d) {
return c * t / d + b;
}
function animate(ele, obj, duration, effect, callback) {
var oBegin = {};//用来保存多个方向begin;
var oChange = {};//用来保存多个方向的change;
var flag = 0;//用来记录各个方向的距离是否有效
for (var attr in obj) {
var target = obj[attr]
var begin = animate.getCss(ele, attr);
var change = target - begin;
if (change) {//判断一下此方向的运动距离有效,不为0
oBegin[attr] = begin;
oChange[attr] = change;
flag++;
}
}
if (!flag)return;//如果各个方向的运动距离都是0,则结束动画的执行
var interval = 15;
var times = 0;
clearInterval(ele.timer);
function step() {
times += interval;
if (times < duration) {
for (var attr in oChange) {
var change = oChange[attr];
var begin = oBegin[attr];
//var val=times/duration*change+begin;
var val = Linear(times, begin, change, duration);
animate.setCss(ele, attr, val);
}
} else {
for (var attr in oChange) {
var target = obj[attr];
animate.setCss(ele, attr, target);
}
clearInterval(ele.timer);
ele.timer = null;
if (typeof callback == "function") {
callback.call(ele);
}
}
}

ele.timer = setInterval(step, interval);
}

animate.getCss = function (ele, attr) {
if (window.getComputedStyle) {
return parseFloat(window.getComputedStyle(ele, null)[attr]);
} else {
if (attr == "opacity") {
var val = ele.currentStyle.filter;
//"alpha(opacity=50)";//匹配到这样的一个字符串,然后把这个字符串中的数字部分拿到
var reg = /alpha\(opacity=(\d+(?:\.\d+)?)\)/;
if (reg.test(val)) {
return RegExp.$1 / 100;
} else {
//如果没有给IE中的不透明度赋值,则上边的正则为false
return 1;//如果没有给不透明度赋值,则应该把默认值1返回
}
//方法没有返回值,则此方法执行结束后留下一个undefined。即:没有返回值的方法返回的是undefined
} else {
return parseFloat(ele.currentStyle[attr]);
}
}
};

animate.setCss = function (ele, attr, val) {
if (attr == "opacity") {
ele.style.opacity = val;
ele.style.filter = "alpha(opacity=" + val * 100 + ")";
} else {
ele.style[attr] = val + "px";
}
};

/*第二步:碰撞检测*/
var oLis = document.getElementsByTagName("li");
//如下代码,循环倒着做就可以,这是为什么呢?一定要搞清楚
for (var i = oLis.length - 1; i >= 0; i--) {
var oLi = oLis.item(i);
oLi.style.left = (oLi.l = oLi.offsetLeft) + "px";
oLi.style.top = (oLi.t = oLi.offsetTop) + "px";
oLi.style.position = "absolute";
oLi.style.margin = 0;
new Drag(oLi).on("abcde1", increaseIndex).on("abcde3", changePosition).on("abcde2", test);
}
var index = 0;
function increaseIndex() {
this.ele.style.zIndex = ++index;
}
function goHome() {
animate(this.ele, {left: this.ele.l, top: this.ele.t}, 700);
}

//如果两个元素撞上了,则返回true;没有撞上,则返回false
function isHited(b, r) {
if (b.offsetLeft + b.offsetWidth < r.offsetLeft || b.offsetTop
+ b.offsetHeight < r.offsetTop || b.offsetLeft > r.offsetLeft
+ r.offsetWidth || b.offsetTop > r.offsetTop + r.offsetHeight)
{
return false;
} else {
return true;
}
}

function test() {
this.aHited = [];
for (var i = 0; i < oLis.length; i++) {
var oLi = oLis.item(i);
if (oLi == this.ele)continue;
if (isHited(this.ele, oLi)) {
this.aHited.push(oLi);
oLi.style.backgroundColor = "red";
} else {
oLi.style.backgroundColor = "";
}
}
}

function changePosition() {
var a = this.aHited;
if (a && a.length) {
for (var i = 0; i < a.length; i++) {
var oLi = a[i];
//计算被拖拽的元素和撞上的元素之间的距离,并且把距离保存到distance属性上
oLi.distance = Math.sqrt(Math.pow(this.ele.offsetLeft - oLi.offsetLeft, 2)
+ Math.pow(this.ele.offsetTop - oLi.offsetTop, 2));
oLi.style.backgroundColor = "";
}
//排序,找出和被拖拽元素最短的那个元素
a.sort(function (a, b) {
return a.distance - b.distance
});
var shortest = a[0];
shortest.style.backgroundColor = "orange";
this.ele.style.backgroundColor = "orange";
//交换位置
animate(shortest, {left: this.ele.l, top: this.ele.t}, 700);
animate(this.ele, {left: shortest.l, top: shortest.t}, 700);
var l = this.ele.l, t = this.ele.t;
this.ele.l = shortest.l;
this.ele.t = shortest.t;
shortest.l = l;
shortest.t = t;
} else {//如果没有撞上的元素,则返回原始位置
animate(this.ele, {left: this.ele.l, top: this.ele.t}, 700);
}
}
</script>
```

猜你喜欢

转载自www.cnblogs.com/gushixianqiancheng/p/10967164.html
92