原生JS實(shí)現(xiàn)拖拽照片墻
本文實(shí)例為大家分享了一個(gè)用原生JS實(shí)現(xiàn)的可拖拽照片墻,效果如下:

實(shí)現(xiàn)代碼如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>原生JS實(shí)現(xiàn)拖拽照片墻,實(shí)現(xiàn)照片互換位置</title>
<style>
* {
margin: 0;
padding: 0;
}
#ul1 {
width: 660px;
position: relative;
margin: 10px auto;
}
#ul1 li {
width: 200px;
height: 150px;
float: left;
list-style: none;
margin: 10px;
z-index: 1;
}
#ul1 .active {
border: 1px dashed red;
}
</style>
<script src="js/move.js"></script>
<script>
window.onload = function () {
var oUl = document.getElementById('ul1');
var aLi = oUl.getElementsByTagName('li');
var aPos = [];
var iMinZindex = 2;
var i = 0;
//布局轉(zhuǎn)換
//獲取當(dāng)前布局圖片的位置
for (i = 0; i < aLi.length; i++) {
aPos[i] = { left: aLi[i].offsetLeft, top: aLi[i].offsetTop };
}
//布局轉(zhuǎn)換必須要兩個(gè)for循環(huán)才能完成
for (i = 0; i < aLi.length; i++) {
//為每個(gè)圖片位置賦值
aLi[i].style.left = aPos[i].left + 'px';
aLi[i].style.top = aPos[i].top + 'px';
//轉(zhuǎn)換定位
aLi[i].style.position = 'absolute';
//offset的值經(jīng)已經(jīng)包括的margin值,所以要取消
aLi[i].style.margin = '0';
aLi[i].index = i;
}
//循環(huán)拖拽
for (i = 0; i < aLi.length; i++) {
setDrag(aLi[i]);
}
function setDrag(obj) {
//當(dāng)鼠標(biāo)按下時(shí)
obj.onmousedown = function (ev) {
//事件兼容
var oEvent = ev || event;
//將當(dāng)前圖片的堆疊順序增加
obj.style.zIndex = iMinZindex++;
//計(jì)算鼠標(biāo)相對(duì)于拖拽對(duì)象左上角的位置
var disX = oEvent.clientX - obj.offsetLeft;
var disY = oEvent.clientY - obj.offsetTop;
//當(dāng)鼠標(biāo)移動(dòng)時(shí)
document.onmousemove = function (ev) {
//事件兼容
var oEvent = ev || event;
//重新為圖片位置賦值
obj.style.left = oEvent.clientX - disX + 'px';
obj.style.top = oEvent.clientY - disY + 'px';
//清空所有l(wèi)i的樣式
for (i = 0; i < aLi.length; i++) {
aLi[i].className = '';
}
//獲取當(dāng)前拖拽對(duì)象的最近目標(biāo)對(duì)象
var oNear = findNearest(obj);
//如果存在
if (oNear) {
//將該對(duì)象的class賦于active
oNear.className = 'active';
}
};
//當(dāng)鼠標(biāo)松開時(shí)
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
//獲取當(dāng)前拖拽對(duì)象的最近目標(biāo)對(duì)象
var oNear = findNearest(obj);
//如果有最近的碰撞對(duì)象
if (oNear) {
oNear.className = '';
//將最近目標(biāo)對(duì)象的zIndex加加
//防止從背面移動(dòng)
oNear.style.zIndex = iMinZindex++;
//當(dāng)前拖拽對(duì)象移到目標(biāo)對(duì)象之上時(shí)位于目標(biāo)對(duì)象之上
obj.style.zIndex = iMinZindex++;
//將最近目標(biāo)對(duì)象(oNear)移到當(dāng)前對(duì)象(obj)位置
startMove(oNear, aPos[obj.index]);
//將當(dāng)前對(duì)象(obj)移到最近目標(biāo)對(duì)象(oNear)位置
startMove(obj, aPos[oNear.index]);
//交換當(dāng)前拖拽對(duì)象與目標(biāo)對(duì)象的index值
var tmp = 0;
tmp = obj.index;
obj.index = oNear.index;
oNear.index = tmp;
//如果沒有最近的碰撞對(duì)象
} else {
//回到原位
startMove(obj, aPos[obj.index]);
}
};
//清除定時(shí)器
//防止圖片在移位過程中再次拖動(dòng)出現(xiàn)抖動(dòng)
clearInterval(obj.timer);
//防止瀏覽器bug,拖拽時(shí)鼠標(biāo)指針變形
return false;
};
}
//碰撞檢測
function cdTest(obj1, obj2) {
//目標(biāo)1的左右上下輪廓位置
var l1 = obj1.offsetLeft;
var r1 = obj1.offsetLeft + obj1.offsetWidth;
var t1 = obj1.offsetTop;
var b1 = obj1.offsetTop + obj1.offsetHeight;
//目標(biāo)2的左右上下輪廓位置
var l2 = obj2.offsetLeft;
var r2 = obj2.offsetLeft + obj2.offsetWidth;
var t2 = obj2.offsetTop;
var b2 = obj2.offsetTop + obj2.offsetHeight;
//對(duì)兩個(gè)目標(biāo)的外輪廓線進(jìn)行對(duì)比,以檢測是否碰撞到了
if (r1 < l2 || l1 > r2 || b1 < t2 || t1 > b2) {
return false;
} else {
return true;
}
}
//計(jì)算拖拽對(duì)象和其它對(duì)象的連線距離
function getDis(obj1, obj2) {
var a = obj1.offsetLeft - obj2.offsetLeft;
var b = obj1.offsetTop - obj2.offsetTop;
return Math.sqrt(a * a + b * b);
}
//找到碰上的,并且最近的
function findNearest(obj) {
//為找出最小值做的參照數(shù)值
var iMin = 999999999;
var iMinIndex = -1;
for (i = 0; i < aLi.length; i++) {
//避免自身與自身相碰撞,跳過檢測
if (obj == aLi[i]) {
continue
};
//如果找到碰撞對(duì)象
if (cdTest(obj, aLi[i])) {
//計(jì)算拖拽對(duì)象與每個(gè)li的距離
var dis = getDis(obj, aLi[i]);
//如果當(dāng)前參照距離大于某一個(gè)li與當(dāng)前拖拽對(duì)象的距離
if (iMin > dis) {
//重新賦值參照距離(多次比對(duì),得出最小值)
iMin = dis;
//得出最近目標(biāo)的下標(biāo)
iMinIndex = i;
}
}
}
//iMinIndex為-1,代表始終沒有碰到
if (iMinIndex == -1) {
return null;
//否則
} else {
//返回碰撞最近的那個(gè)li
return aLi[iMinIndex];
}
}
};
</script>
</head>
<body>
<ul id="ul1">
<li><img src="images/0.jpg" /></li>
<li><img src="images/1.jpg" /></li>
<li><img src="images/2.jpg" /></li>
<li><img src="images/3.jpg" /></li>
<li><img src="images/4.jpg" /></li>
<li><img src="images/0.jpg" /></li>
<li><img src="images/1.jpg" /></li>
<li><img src="images/2.jpg" /></li>
<li><img src="images/3.jpg" /></li>
<li><img src="images/4.jpg" /></li>
</ul>
</body>
</html>
以下是上面代碼中引入的move.js文件,主要用于實(shí)現(xiàn)運(yùn)動(dòng)效果,代碼如下:
function getStyle(obj, attr) {
if (obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
function startMove(obj, json, fn) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
var bStop = true;
for (var attr in json) {
var iCur = 0;
if (attr == 'opacity') {
iCur = parseInt(parseFloat(getStyle(obj, attr)) * 100);
} else {
iCur = parseInt(getStyle(obj, attr));
}
var iSpeed = (json[attr] - iCur) / 8;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (iCur != json[attr]) {
bStop = false;
}
if (attr == 'opacity') {
obj.style.filter = 'alpha(opacity:' + (iCur + iSpeed) + ')';
obj.style.opacity = (iCur + iSpeed) / 100;
} else {
obj.style[attr] = iCur + iSpeed + 'px';
}
}
if (bStop) {
clearInterval(obj.timer);
if (fn) {
fn();
}
}
}, 30)
}
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
js新聞滾動(dòng) js如何實(shí)現(xiàn)新聞滾動(dòng)效果
JS實(shí)現(xiàn)新聞滾動(dòng)效果:滾動(dòng)頻率由setTimeout(F,#%18?10:3000)這個(gè)3000來控制,感興趣的朋友可以了解下哦2013-01-01
JavaScript Window窗口對(duì)象屬性和使用方法
這篇文章主要介紹了JavaScript Window窗口對(duì)象屬性和使用方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
JS時(shí)間戳與日期格式互相轉(zhuǎn)換的簡單方法示例
這篇文章主要給大家介紹了關(guān)于JS時(shí)間戳與日期格式互相轉(zhuǎn)換的簡單方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
使用javascript做時(shí)間倒數(shù)讀秒功能的實(shí)例
今天小編就為大家分享一篇關(guān)于使用javascript做時(shí)間倒數(shù)讀秒功能的實(shí)例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-01-01
javascript設(shè)計(jì)模式 – 原型模式原理與應(yīng)用實(shí)例分析
這篇文章主要介紹了javascript設(shè)計(jì)模式 – 原型模式,結(jié)合實(shí)例形式分析了javascript原型模式相關(guān)概念、原理、應(yīng)用場景及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04

