(Demo分享)利用JavaScript(JS)實現一個九宮格拖拽功能

利用JavaScript(JS)實現一個九宮格拖拽功能javascript

 

Demo實現了對任意方格進行拖拽,能夠交換位置,其中Demo-1利用了勾股定理判斷距離!css

Demo-1總體思路:html

1.首先div實現自由移動,必定須要脫離標準文檔流,因此咱們給它使用絕對定位。java

2.利用視覺欺騙,點擊鼠標懸浮的實際上是利用JS生成的一個Div,交換信息的兩個Div並無位置交換,只是把雙方屬性進行了交換。web

3.利用了勾股定理去判斷距離。網絡


##效果圖以下:app

 

網頁源代碼:函數

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>九宮格拖拽</title>
</head>
<style type="text/css"> #content{ width: 300px; height:300px; margin: 0 auto; background: #F47564; position: relative; } #content div{ width: 100px; height: 100px; float: left; line-height: 100px; text-align: center; font-size:40px; font-weight: 900; color: #fff; cursor: pointer; position: absolute; } #content div:nth-child(1){ background-color: #f05b72; top:0; left: 0; } #content div:nth-child(2){ background-color: #faa755; top:0; left:100px; } #content div:nth-child(3){ background-color: #2585a6; top:0; left: 200px; } #content div:nth-child(4){ background:#5ce4fd; top:100px; left: 0; } #content div:nth-child(5){ background:#f61acf; top:100px; left: 100px; } #content div:nth-child(6){ background:#3ef9bd; top:100px; left: 200px; } #content div:nth-child(7){ background:#9af93e; top:200px; left: 0; } #content div:nth-child(8){ background:#eef93e; top:200px; left: 100px; } #content div:nth-child(9){ background:#f9843e; top:200px; left:200px; } #content .draging{ position: absolute; } </style>
<body>
<div id="content">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <div>9</div>
</div>

<script type="text/javascript">
    var content = document.getElementById('content'); var items = content.querySelectorAll('div'); console.log(items); function itemBox(itemName){ itemName.onmousedown = function(evt1){ var e = evt1 || window.event; //在鼠標點下item的時候克隆一個新的如出一轍的名爲cloneDiv
            var cloneDiv = document.createElement('div'); //把樣式文字賦給克隆div
            cloneDiv.innerHTML = itemName.innerHTML; cloneDiv.style.backgroundColor = getComputedStyle(itemName).backgroundColor; //使克隆div的class名爲draging,使克隆div加絕對定位position:absolute
            cloneDiv.className = 'draging'; //克隆div的定位top left 和原div相同
            cloneDiv.style.top = itemName.offsetTop +'px'; cloneDiv.style.left = itemName.offsetLeft+'px'

            //把kelongdiv加入到concent大盒子當中
 content.appendChild(cloneDiv); //算出鼠標點擊克隆div時,鼠標在克隆div中的相對位置
            var offsetX = evt1.pageX - cloneDiv.offsetLeft; var offsetY = evt1.pageY - cloneDiv.offsetTop; // cloneDiv.style.zIndex = 10;

            //鼠標開始移動的時候
            document.onmousemove = function(evt){ var e2 = evt || window.event; //克隆div定位的left top evt.pageX鼠標點相對於整個文檔中的位置, offsetX鼠標相對於克隆div中的位置 兩者相減就是克隆div相對於整個文檔中的位置
                cloneDiv.style.left = evt.pageX - offsetX +'px'; cloneDiv.style.top = evt.pageY -offsetY+'px' } //當鼠標鬆開的時候
            document.onmouseup = function(){ //先把移動事件中止
                document.onmousemove = null; //須要判斷 clonediv 的位置距 那個div 最近

                //先獲取到content大盒子下全部的div
                var divs = content.getElementsByTagName('div'); console.log(divs.length) //而後判斷移動到位置距離哪個最近


                var min = 800;//考慮到被拖拽的div拖拽到大盒子以外還能進行交換,距離設爲大盒子外 方圓800px
                var minDiv = null;//設一個空的div用來交換位置
                for(var i=0;i<divs.length-1;i++){//遍歷出除了鼠標移動的div外的全部的div 也就是length - 1
                    var div = divs[i]; //div cloneDiv

                    //distance(cloneDiv,div)返回值爲c,c爲兩div之間的距離
                    var dis = distance(cloneDiv,div);//調用運用勾股定理進行比較距離的函數
                    if(dis <= min){//a^2 + b^2 和c^2比較
                        min = dis; minDiv = div; } } //把距離小的那個div的樣式給拖拽走空出來的div itemName


                //若是這樣賦值的話target的innerHTML就會丟失都變成minDiv.innerHTML,因此的設一箇中轉變量,讓二者交換。background同理 // minDiv.innerHTML = target.innerHTML;

                //二者樣式交換,引入第三變量tmpInnerHTMl
                var tmpInnerHTMl = minDiv.innerHTML; minDiv.innerHTML = itemName.innerHTML; itemName.innerHTML = tmpInnerHTMl; //引入第三變量tmpColor
                var tmpColor = getComputedStyle(minDiv).backgroundColor; minDiv.style.backgroundColor = getComputedStyle(itemName).backgroundColor; itemName.style.backgroundColor = tmpColor; //刪掉克隆元素
 content.removeChild(cloneDiv) document.onmouseup = null;//把鼠標鬆開後的操做清除
 } return false; } } //for循環使每個item都調用itemBox()這個函數
    for(var i = 0; i < items.length; i++){ itemBox(items[i]); } function distance(div1,div2) { //勾股定理 記錄 兩個元素的距離
        var a = div1.offsetLeft - div2.offsetLeft; var b = div1.offsetTop - div2.offsetTop; var c = Math.sqrt(a*a+b*b);  //利用勾股定理算出兩個div的距離 a^2 + b^2 再開平方得出c
        return c; } </script>
</body>
</html>

Demo-2總體思路(頁面存在不少Bug,提供另外一種思路,建議使用Demo1的方法):flex

1.首先div實現自由移動,必定須要脫離標準文檔流,因此咱們給它使用絕對定位。ui

2.利用每一個div方塊都有相對的座標值,當鼠標按下移動元素的時候,靠近哪一個座標值,靠近座標值對應的方塊就與當前元素進行位置交換。

3.當前demo,只能存在的bug:元素只能進行交換一次,第二次交換時會發生div被覆蓋的結果,不過也提供了另外一種思路。


##效果圖以下:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>九宮格</title>
    <style>
        /*CSS樣式設置*/
        /*爲了方便查看使用通配符去除默認樣式,實際開發不建議使用*/
        * { margin: 0; padding: 0; } #list { width: 390px; height: 390px; margin: 90px auto 0; border-radius: 10px; display: flex; flex-flow: wrap; position: relative; /*讓div中文字沒法被選取,防止因鼠標滑過選取文字而致使鼠標失去焦點*/
            -webkit-touch-callout: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } /*須要給移動的div設置絕對定位,使其脫離標準文檔流*/ div>div { width: 130px; height: 130px; font-size: 50px; line-height: 130px; border-radius: 8px; color: #fff; text-align: center; font-weight: bold; box-sizing: border-box; cursor: move; position: absolute; } #d1 { top: 0; left: 0; background-color: #f05b72; } #d2 { background-color: #faa755; top: 0; left: 130px; } #d3 { top: 0; left: 260px; background-color: #2585a6; } #d4 { top: 130px; left: 0; background-color: #50b7c1; } #d5 { top: 130px; left: 130px; background-color: #69541b; } #d6 { top: 130px; left: 260px; background-color: #8552a1; } #d7 { top: 260px; left: 0; background-color: #274d3d; } #d8 { top: 260px; left: 130px; background-color: #73b9a2; } #d9 { top: 260px; left: 260px; background-color: #7fb80e; } </style>
</head>
<body>
<div id="list">
    <div id="d1">1</div>
    <div id="d2">2</div>
    <div id="d3">3</div>
    <div id="d4">4</div>
    <div id="d5">5</div>
    <div id="d6">6</div>
    <div id="d7">7</div>
    <div id="d8">8</div>
    <div id="d9">9</div>
</div>
</body>
<script>
    // 首先獲取每一個div的ID,聲明變量
    var list = document.getElementById("list") var d1 = document.getElementById("d1"); var d2 = document.getElementById("d2"); var d3 = document.getElementById("d3"); var d4 = document.getElementById("d4"); var d5 = document.getElementById("d5"); var d6 = document.getElementById("d6"); var d7 = document.getElementById("d7"); var d8 = document.getElementById("d8"); var d9 = document.getElementById("d9"); // 封裝函數,方便後續使用
    function box (divname) { // 當在divname上點下鼠標發生的事件
        divname.onmousedown = function (env) { // 在div移動前先獲取每一個傳入的實參(divname)的位置,留做位置判斷失敗後返回原位置
            var a1x = divname.offsetLeft; var a1y = divname.offsetTop; console.log(a1x+"這是") console.log(a1y+"這是") // 給每一個傳入的實參(divname)設置層級,否則會被其餘div遮擋住
            divname.style.zIndex = "4"; // env表明事件的狀態,設置兼容。
            var env = env || window.event; // 獲取鼠標當被點擊的在div上的位置:
            // env.clientX(表明當前鼠標距離屏幕左邊的位置)。
            // list.offsetLeft(表明list盒子距離屏幕的左邊的位置)。
            // 由於divname設置了絕對定位,因此divname.offsetLeft的參數表明鼠標在div上距離父元素的位置
            // (env.clientX - list.offsetLeft - divname.offsetLeft)至關於把鼠標當前位置設置爲原點
            var divmosue_x = (env.clientX - list.offsetLeft - divname.offsetLeft); var divmosue_y = (env.clientY - list.offsetTop - divname.offsetTop); // 當在divname上點下鼠標發生而且鼠標在指定的元素中移動
            divname.onmousemove = function (env) { var env = env || window.event; // 獲取鼠標當被點擊移動的時候在div上的位置:
                // env.clientX(表明當前鼠標距離屏幕左邊的位置)。
                // divmosue_x的含義參照上條註釋
                // list.offsetLeft(表明list盒子距離屏幕的左邊的位置)。
                // div_x的含義至關於把鼠標當前座標點設置爲原點
                var div_x = env.clientX - divmosue_x - list.offsetLeft; var div_y = env.clientY - divmosue_y - list.offsetTop; // 由於divname設置了絕對定位,下面讓divname的位置隨着鼠標的移動而發生變化
                divname.style.top =  div_y+"px" divname.style.left = div_x+"px"
                // 當鼠標鬆開時的事件,移動的div根據if判斷座標位置,讓div符合要求的div交換位置。
                // 並讓移動後的雙方層級爲1,防止元素層級遮擋
                divname.onmouseup = function () { if (div_x > -65 && div_x < 0 && div_y > -65 && div_y < 0) { d1.style.top = a1y + "px"; d1.style.left = a1x +"px"; divname.style.top = "0px"; divname.style.left = "0px" d1.style.zIndex = "1"; divname.style.zIndex = "1"; }else if (div_x > 65 && div_x < 130 && div_y > -65 && div_y < 0) { d2.style.top = a1y + "px"; d2.style.left = a1x +"px"; divname.style.top = "0px" divname.style.left = "130px" d2.style.zIndex = "1"; divname.style.zIndex = "1"; }else if (div_x > 190 && div_x <255  && div_y > -65 && div_y < 0) { d3.style.top = a1y + "px"; d3.style.left = a1x +"px"; divname.style.top = "0px" divname.style.left = "260px" d3.style.zIndex = "1"; divname.style.zIndex = "1"; }else if (div_x > -65 && div_x < 0 && div_y > 65 && div_y < 130) { d4.style.top = a1y + "px"; d4.style.left = a1x +"px"; divname.style.top = "130px" divname.style.left = "0px" d4.style.zIndex = "1"; divname.style.zIndex = "1"; }else if (div_x > 65 && div_x < 130 && div_y > 65 && div_y < 130) { d5.style.top = a1y + "px"; d5.style.left = a1x +"px"; divname.style.top = "130px" divname.style.left = "130px" d5.style.zIndex = "1"; divname.style.zIndex = "1"; }else if (div_x > 190 && div_x <255  && div_y > 65 && div_y < 130) { d6.style.top = a1y + "px"; d6.style.left = a1x +"px"; divname.style.top = "130px" divname.style.left = "260px" }else if (div_x > -65 && div_x < 0 && div_y > 190 && div_y < 255) { d7.style.top = a1y + "px"; d7.style.left = a1x +"px"; divname.style.top = "260px" divname.style.left = "0px" d5.style.zIndex = "1"; divname.style.zIndex = "1"; }else if (div_x > 65 && div_x < 130 && div_y > 190 && div_y < 255) { d8.style.top = a1y + "px"; d8.style.left = a1x +"px"; divname.style.top = "260px" divname.style.left = "130px" d8.style.zIndex = "1"; divname.style.zIndex = "1"; }else if (div_x > 190 && div_x <255  && div_y > 190 && div_y < 255) { d9.style.top = a1y + "px"; d9.style.left = a1x +"px"; divname.style.top = "260px" divname.style.left = "260px" d9.style.zIndex = "1"; divname.style.zIndex = "1"; } // 若是divname,未符合判斷條件,則讓它回到原點位置
                    else{ console.log("asdsa") console.log(a1x) console.log(a1y) divname.style.top = a1x + "px"; divname.style.left = a1y+"px"; divname.style.zIndex = "1"; divname.onmousemove = null; } divname.onmousemove = null; console.log("鬆開了"); } } } } box(d1) box(d2) box(d3) box(d4) box(d5) box(d6) box(d7) box(d8) box(d9) </script>
</html>

本demo-1參考思路來源於網絡,若有侵權,請及時聯繫刪除。

相關文章
相關標籤/搜索