一. Html5的拖拽行為
1.設置元素為可拖放:把draggable屬性設置為true.
example: <div id="drag1" draggable="true"></div>
(注:img和帶href的a默認是auto,表示可拖拽,其他的元素都是不可拖拽。為安全起見,建議對可拖拽元素都添加draggable='true'設置)
2.拖拽元素事件:
1). dragstart:拖拽前觸發,即鼠標按下,被拖拽元素被拖拽的瞬間觸發。
event.dataTransfer:傳遞數據,數據類型為字符串和文件類型。
event.dataTransfer的大部分設置均在這里配置,即通過event.dataTransfer來保存拖拽的數據,例如:e.dataTransfer.setData("Text", e.target.id);
event.dataTransfer.effectAllowed:用於設置被拖拽元素可執行的操作
example:event.dataTransfer.effectAllowed = "link"; 限定dropEffect的屬性值為link,否則會鼠標指針為禁止樣式
觸發dragstart事件后,其他元素的mousemove,mouseover,mouseenter,mouseleave,mouseout事件均不會被觸發了
2). drag:拖拽前、拖拽結束之間連續觸發,即使鼠標沒有移動,只要未釋放,都會觸發。
3). dragend:拖拽結束觸發,即釋放鼠標觸發。
3.目標元素事件:
1). dragenter:進入目標元素觸發,相當於mouseover
2). dragover:被拖拽元素在目標元素上移動時觸發,相當於mousemove
在該事件里填寫: event.preventDefault() 。
(注:事件的默認行為是不允許被拖拽元素在其他元素上釋放或放置(即無法觸發 drop 事件),需要通過 event.preventDefault() 來阻止默認行為才能觸發后續的 drop 事件)
dropEffect:拖放的操作類型,決定了瀏覽器如何顯示鼠標形狀,可能的值為copy、move、link和none。
可以在這里設置dropEffect的值,事件的默認行為是將dropEffect設置為none。
例如:e.dataTransfer.dropEffect = "link"
3). dragleave:被拖拽元素離開目標元素時觸發
4). drop:被拖拽元素放置在目標元素上時觸發(釋放鼠標)
(注:對於外來的被拖拽元素(超鏈接、文件、圖片源), drop 事件的默認行為是瀏覽器將當前頁面重定向到被拖拽元素所指向的資源上
對文檔內部的被拖拽元素,IE10+和Chrome下的默認行為是不作為,而FF得默認行為是新打開一個文檔用於訪問被拖拽元素所指向的資源)
4.事件執行順序
1) drop不觸發的時候:dragstart > drag > dragenter > dragover > dragleave > dragend
2) drop觸發的時候(dragover阻止了默認事件):dragstart > drag > dragenter > dragover > drop > dragend
二:拖拽事件和Angular JS的結合
html
<!DocType html> <html data-ng-app="myApp"> <head> <title>angularjs 和拖拽事件的結合</title> <meta charset="utf-8" /> <script type="text/javascript" src="angular.js"></script> <script type="text/javascript" src="dragdirective.js"></script> <script type="text/javascript" src="mydrag.js"></script> <style type="text/css"> .mydemo > div { display: inline-block; } .mydemo > div > div { width: 150px; height: 100px; border: 1px dotted grey; display: inline-block; float: left; margin-right: 20px; } </style> </head> <body data-ng-controller="myDragController as vm" class="mydemo"> <div> <div ruby-drop="vm.drop(event)" ruby-dragover="vm.dragover(event)"> <img src="ruby.png" draggable="true" ruby-dragstart="vm.dragstart(event)" id="imgId" /> </div> <div ruby-drop="vm.drop(event)" ruby-dragover="vm.dragover(event)"></div> </div> </body> </html>
js->dragdirective.js
(function () { "use strict" var convertFirstUpperCase = function (str) { return str.replace(/(\w)/, function (s) { return s.toUpperCase(); }); } angular.module("myApp", []); var myApp = angular.module("myApp"), rubyDragEventDirectives = {}; angular.forEach("dragstart drag dragenter dragover drop dragleave dragend".split(' '), function (eventName) { var rubyEventName = 'ruby' + convertFirstUpperCase(eventName); rubyDragEventDirectives[rubyEventName] = ['$parse', function ($parse) { //$parse 語句解析器 return { restrict: 'A', compile: function (ele, attr) { var fn = $parse(attr[rubyEventName]); return function rubyEventHandler(scope, ele) { ele[0].addEventListener(eventName, function (event) { if (eventName == 'dragover' || eventName == 'drop') { event.preventDefault(); } var callback = function () { fn(scope, { event: event }); }; callback(); }); } } } }] }); myApp.directive(rubyDragEventDirectives); })();
js->mydrag.js
(function () { "use strict" if (window.angular) { angular.module("myApp").controller("myDragController", myDragController); myDragController.$inject = ['$scope']; function myDragController($scope) { $scope.vm.dragstart = function (e) { e.dataTransfer.setData("Text", e.target.id); }; $scope.vm.dragover = function (e) { e.preventDefault(); }; $scope.vm.drop = function (e) { e.preventDefault(); var data = e.dataTransfer.getData("Text"); e.target.appendChild(document.getElementById(data)); }; } } })();