數獨是很好玩的游戲,之前我用jQuery做了一個數獨游戲,因為用javaScript來實現drag和drap非常麻煩,jQuery的UI提供了一套非常不錯的drag和drap(以後就簡稱DnD算了),方便我們開發。現在HTML5支持原生的DnD了,那我們來學習下,並且將原先的數獨游戲遷移到HTML5的DnD應用來。
先簡單的了解下HTML5的DnD事件模型,事件發生在源元素(被拖動的元素)和目標元素(被進入的元素)上,為了簡單的描述,我們將源元素稱為src,目標元素叫des。
drag:src[拖動中]
dragstart:src[開始拖動]
dragenter:des[進入目標]
dragover:des[在目標移動]
dragleave:des[離開目標]
drop:des[釋放拖動]
dragend:src[拖動完成]所有的事件我們知道肯定都應該給我們一個event對象,幫助我們獲得一些信息或我們來設置一些信息,以上事件都可以得到一個event,如果我們的事件函數是function(e)那
e.dataTransfer.effectAllowed,只能在dragstart事件設置,值為以下之一:"none", "copy", "copyLink", "copyMove", "link", "linkMove", "move", "all", and "uninitialized"
e.dataTransfer.dropEffect,返回拖來的行為,對應上面的effectAllowed,值是:"none", "copy", "link", and "move"
e.target,可以得到當前事件的dom對象,比如你可以得到e.target.innerHTML,或者設置e.target.classList.add,或者e.target.classList.remove
e.dataTransfer.setData(foramt,value),為拖動賦值,foramt的值是為了描述值的類型,一般有text/plain 和 text/uri-list
e.dataTransfer.getData(foramt),獲取被拖來的元素通過setData存儲的值
e.stopPropagation,阻止事件冒泡,這樣可以防止子元素的拖動處理被帶到父元素事件中(觸發父元素事件),在IE中可以用e.cancelBubble = true
e.preventDefault,阻止默認事件發生,也可以簡單的寫return false,在IE中可以用e.returnValue = false
有了上面的基本概念,我們先做一個小小的模型,來測試幾個技術要點:監視拖放事件,改變元素在拖放中的樣式,傳遞值和檢查值什麼的
在body裡面,我們聲明了10個div元素,並且都標記允許拖放
- <body>
- <div style="width: 50px; height: 50px; background-color: Red;" draggable="true">
- 1
- </div>
- <div style="width: 50px; height: 50px; background-color: Yellow;" draggable="true">
- 2
- </div>
- <div style="width: 50px; height: 50px; background-color: Blue;" draggable="true">
- 3
- </div>
- <div style="width: 50px; height: 50px; background-color: Lime;" draggable="true">
- 4
- </div>
- <div style="width: 50px; height: 50px; background-color: Maroon;" draggable="true">
- 5
- </div>
- <div style="width: 50px; height: 50px; background-color: Black;" draggable="true">
- 6
- </div>
- <div style="width: 50px; height: 50px; background-color: Orange;" draggable="true">
- 7
- </div>
- <div style="width: 50px; height: 50px; background-color: Olive;" draggable="true">
- 8
- </div>
- <div style="width: 50px; height: 50px; background-color: Teal;" draggable="true">
- 9
- </div>
- <div style="width: 50px; height: 50px; background-color: Green;" draggable="true">
- 10
- </div>
- </body>
現在我們想做一個應用,只有相互有倍數關系的div之間才可用拖放。
首選我們做一個用於輸出調式的小工具代碼
- $.log = function(msg) {
- console.log(msg);
- }
這個我們可以方便的$.log()輸出,而不要寫冗長的console.log了
第一步,編寫dragStart事件函數
- function handleDragStart(e) {
- this.style.opacity = "0.5";
- e.dataTransfer.effectAllowed = "move";
- e.dataTransfer.setData("text/plain", this.innerHTML);
- //$.log(this.innerHTML);
- //$.log(e.target.innerHTML);
- //$.log(e.srcElement.innerHTML);
- [ ].forEach.call(document.querySelectorAll("div"),
- function(item) {
- var a = parseInt(e.target.innerHTML);
- var b = parseInt(item.innerHTML);
- if (a % b != 0 && b % a != 0) {
- item.style.opacity = "0.1";
-
- }
- });
- }
以上的代碼有幾個要點
1 對事件來講this、e.target和e.srcElement都是同一對象
2 在forEach中,this是指item,所以forEach中,我們要用e.target來引用