一. 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)); }; } } })();