深究AngularJS中ng-drag、ng-drop的用法
程序员文章站
2022-04-10 11:31:20
1.相关地址:
插件下载:https://github.com/fatlinesofcode/ngdraggable/blob/master/ngdraggable.js...
1.相关地址:
插件下载:https://github.com/fatlinesofcode/ngdraggable/blob/master/ngdraggable.js
2.讲解
<div ng-drop="true" ng-drop-success="dropcomplete($index,$data,$event)" ng-repeat="item in content"> <li ng-drag="true" ng-drag-data="item" > 姓名:{{item.name}},年龄:{{item.age}} </li> </div>
ng-drag : 表示该元素能够被拖动
ng-drag-data : 表示拖动元素时跟着被拖走的数据
ng-drop : 表示该元素内可放置被拖动的元素
ng-drop-success : 放置在ngd-drop所在元素里后触发,一般写事件.
ng-drop-success触发的dropcomplete方法的参数说明:
- $index : 表示拖动的数据所落的元素的下标
- $data : 被拖动的数据对象
3.拖拽排序示例
页面代码
<div ng-drop="true" ng-drop-success="dropcomplete($index,$data)" ng-repeat="item in content"> <li ng-drag="true" ng-drag-data="item" > 姓名:{{item.name}},年龄:{{item.age}} </li> </div>
js代码
//数据 $scope.content = [{'name':'张春玲','age':28},{'name':'王晰','age':26},{'name':'吴正青','age':66}]; /** 拖拽成功触发方法 * index 拖拽后落下时的元素的序号(下标) * obj被拖动数据对象 */ $scope.dropcomplete = function(index, obj){ //重新排序 var idx = $scope.content.indexof(obj); $scope.content.splice(idx,1); $scope.content.splice(index,0,obj); };
4.拖拽交换示例
页面代码
<div ng-drop="true" ng-drop-success="dropcomplete($index,$data)" ng-repeat="item in content"> <li ng-drag="true" ng-drag-data="item" > 姓名:{{item.name}},年龄:{{item.age}} </li> </div>
js代码
//数据 $scope.content = [{'name':'张春玲','age':28},{'name':'王晰','age':26},{'name':'吴正青','age':66}]; /** 拖拽成功触发方法 * index 拖拽后落下时的元素的序号(下标) * obj 被拖动数据对象 */ $scope.dropcomplete = function(index, obj){ var idx = $scope.content.indexof(obj); $scope.content[idx] = $scope.content[index]; $scope.content[index] = obj; }; 5. ngdraggable插件代码 /* * * https://github.com/fatlinesofcode/ngdraggable */ angular.module("ngdraggable", []) .service('ngdraggable', [function() { var scope = this; scope.inputevent = function(event) { if (angular.isdefined(event.touches)) { return event.touches[0]; } //checking both is not redundent. if only check if touches isdefined, angularjs isdefnied will return error and stop the remaining scripty if event.originalevent is not defined. else if (angular.isdefined(event.originalevent) && angular.isdefined(event.originalevent.touches)) { return event.originalevent.touches[0]; } return event; }; }]) .directive('ngdrag', ['$rootscope', '$parse', '$document', '$window', 'ngdraggable', function ($rootscope, $parse, $document, $window, ngdraggable) { return { restrict: 'a', link: function (scope, element, attrs) { scope.value = attrs.ngdrag; var offset,_centeranchor=false,_mx,_my,_tx,_ty,_mrx,_mry; var _hastouch = ('ontouchstart' in window) || window.documenttouch && document instanceof documenttouch; var _pressevents = 'touchstart mousedown'; var _moveevents = 'touchmove mousemove'; var _releaseevents = 'touchend mouseup'; var _draghandle; // to identify the element in order to prevent getting superflous events when a single element has both drag and drop directives on it. var _myid = scope.$id; var _data = null; var _dragoffset = null; var _dragenabled = false; var _presstimer = null; var ondragstartcallback = $parse(attrs.ngdragstart) || null; var ondragstopcallback = $parse(attrs.ngdragstop) || null; var ondragsuccesscallback = $parse(attrs.ngdragsuccess) || null; var allowtransform = angular.isdefined(attrs.allowtransform) ? scope.$eval(attrs.allowtransform) : true; var getdragdata = $parse(attrs.ngdragdata); // deregistration function for mouse move events in $rootscope triggered by jqlite trigger handler var _deregisterrootmovelistener = angular.noop; var initialize = function () { element.attr('draggable', 'false'); // prevent native drag // check to see if drag handle(s) was specified // if queryselectorall is available, we use this instead of find // as jqlite find is limited to tagnames if (element[0].queryselectorall) { var draghandles = angular.element(element[0].queryselectorall('[ng-drag-handle]')); } else { var draghandles = element.find('[ng-drag-handle]'); } if (draghandles.length) { _draghandle = draghandles; } togglelisteners(true); }; var togglelisteners = function (enable) { if (!enable)return; // add listeners. scope.$on('$destroy', ondestroy); scope.$watch(attrs.ngdrag, onenablechange); scope.$watch(attrs.ngcenteranchor, oncenteranchor); // wire up touch events if (_draghandle) { // handle(s) specified, use those to initiate drag _draghandle.on(_pressevents, onpress); } else { // no handle(s) specified, use the element as the handle element.on(_pressevents, onpress); } if(! _hastouch && element[0].nodename.tolowercase() == "img"){ element.on('mousedown', function(){ return false;}); // prevent native drag for images } }; var ondestroy = function (enable) { togglelisteners(false); }; var onenablechange = function (newval, oldval) { _dragenabled = (newval); }; var oncenteranchor = function (newval, oldval) { if(angular.isdefined(newval)) _centeranchor = (newval || 'true'); }; var isclickableelement = function (evt) { return ( angular.isdefined(angular.element(evt.target).attr("ng-cancel-drag")) ); }; /* * when the element is clicked start the drag behaviour * on touch devices as a small delay so as not to prevent native window scrolling */ var onpress = function(evt) { if(! _dragenabled)return; if (isclickableelement(evt)) { return; } if (evt.type == "mousedown" && evt.button != 0) { // do not start dragging on right-click return; } if(_hastouch){ cancelpress(); _presstimer = settimeout(function(){ cancelpress(); onlongpress(evt); },100); $document.on(_moveevents, cancelpress); $document.on(_releaseevents, cancelpress); }else{ onlongpress(evt); } }; var cancelpress = function() { cleartimeout(_presstimer); $document.off(_moveevents, cancelpress); $document.off(_releaseevents, cancelpress); }; var onlongpress = function(evt) { if(! _dragenabled)return; evt.preventdefault(); offset = element[0].getboundingclientrect(); if(allowtransform) _dragoffset = offset; else{ _dragoffset = {left:document.body.scrollleft, top:document.body.scrolltop}; } element.centerx = element[0].offsetwidth / 2; element.centery = element[0].offsetheight / 2; _mx = ngdraggable.inputevent(evt).pagex;//ngdraggable.geteventprop(evt, 'pagex'); _my = ngdraggable.inputevent(evt).pagey;//ngdraggable.geteventprop(evt, 'pagey'); _mrx = _mx - offset.left; _mry = _my - offset.top; if (_centeranchor) { _tx = _mx - element.centerx - $window.pagexoffset; _ty = _my - element.centery - $window.pageyoffset; } else { _tx = _mx - _mrx - $window.pagexoffset; _ty = _my - _mry - $window.pageyoffset; } $document.on(_moveevents, onmove); $document.on(_releaseevents, onrelease); // this event is used to receive manually triggered mouse move events // jqlite unfortunately only supports triggerhandler(...) // see http://api.jquery.com/triggerhandler/ // _deregisterrootmovelistener = $rootscope.$on('draggable:_triggerhandlermove', onmove); _deregisterrootmovelistener = $rootscope.$on('draggable:_triggerhandlermove', function(event, origevent) { onmove(origevent); }); }; var onmove = function (evt) { if (!_dragenabled)return; evt.preventdefault(); if (!element.hasclass('dragging')) { _data = getdragdata(scope); element.addclass('dragging'); $rootscope.$broadcast('draggable:start', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data}); if (ondragstartcallback ){ scope.$apply(function () { ondragstartcallback(scope, {$data: _data, $event: evt}); }); } } _mx = ngdraggable.inputevent(evt).pagex;//ngdraggable.geteventprop(evt, 'pagex'); _my = ngdraggable.inputevent(evt).pagey;//ngdraggable.geteventprop(evt, 'pagey'); if (_centeranchor) { _tx = _mx - element.centerx - _dragoffset.left; _ty = _my - element.centery - _dragoffset.top; } else { _tx = _mx - _mrx - _dragoffset.left; _ty = _my - _mry - _dragoffset.top; } moveelement(_tx, _ty); $rootscope.$broadcast('draggable:move', { x: _mx, y: _my, tx: _tx, ty: _ty, event: evt, element: element, data: _data, uid: _myid, dragoffset: _dragoffset }); }; var onrelease = function(evt) { if (!_dragenabled) return; evt.preventdefault(); $rootscope.$broadcast('draggable:end', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data, callback:ondragcomplete, uid: _myid}); element.removeclass('dragging'); element.parent().find('.drag-enter').removeclass('drag-enter'); reset(); $document.off(_moveevents, onmove); $document.off(_releaseevents, onrelease); if (ondragstopcallback ){ scope.$apply(function () { ondragstopcallback(scope, {$data: _data, $event: evt}); }); } _deregisterrootmovelistener(); }; var ondragcomplete = function(evt) { if (!ondragsuccesscallback )return; scope.$apply(function () { ondragsuccesscallback(scope, {$data: _data, $event: evt}); }); }; var reset = function() { if(allowtransform) element.css({transform:'', 'z-index':'', '-webkit-transform':'', '-ms-transform':''}); else element.css({'position':'',top:'',left:''}); }; var moveelement = function (x, y) { if(allowtransform) { element.css({ transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + x + ', ' + y + ', 0, 1)', 'z-index': 99999, '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + x + ', ' + y + ', 0, 1)', '-ms-transform': 'matrix(1, 0, 0, 1, ' + x + ', ' + y + ')' }); }else{ element.css({'left':x+'px','top':y+'px', 'position':'fixed'}); } }; initialize(); } }; }]) .directive('ngdrop', ['$parse', '$timeout', '$window', '$document', 'ngdraggable', function ($parse, $timeout, $window, $document, ngdraggable) { return { restrict: 'a', link: function (scope, element, attrs) { scope.value = attrs.ngdrop; scope.istouching = false; var _lastdroptouch=null; var _myid = scope.$id; var _dropenabled=false; var ondropcallback = $parse(attrs.ngdropsuccess);// || function(){}; var ondragstartcallback = $parse(attrs.ngdragstart); var ondragstopcallback = $parse(attrs.ngdragstop); var ondragmovecallback = $parse(attrs.ngdragmove); var initialize = function () { togglelisteners(true); }; var togglelisteners = function (enable) { // remove listeners if (!enable)return; // add listeners. scope.$watch(attrs.ngdrop, onenablechange); scope.$on('$destroy', ondestroy); scope.$on('draggable:start', ondragstart); scope.$on('draggable:move', ondragmove); scope.$on('draggable:end', ondragend); }; var ondestroy = function (enable) { togglelisteners(false); }; var onenablechange = function (newval, oldval) { _dropenabled=newval; }; var ondragstart = function(evt, obj) { if(! _dropenabled)return; istouching(obj.x,obj.y,obj.element); if (attrs.ngdragstart) { $timeout(function(){ ondragstartcallback(scope, {$data: obj.data, $event: obj}); }); } }; var ondragmove = function(evt, obj) { if(! _dropenabled)return; istouching(obj.x,obj.y,obj.element); if (attrs.ngdragmove) { $timeout(function(){ ondragmovecallback(scope, {$data: obj.data, $event: obj}); }); } }; var ondragend = function (evt, obj) { // don't listen to drop events if this is the element being dragged // only update the styles and return if (!_dropenabled || _myid === obj.uid) { updatedragstyles(false, obj.element); return; } if (istouching(obj.x, obj.y, obj.element)) { // call the ngdraggable ngdragsuccess element callback if(obj.callback){ obj.callback(obj); } if (attrs.ngdropsuccess) { $timeout(function(){ ondropcallback(scope, {$data: obj.data, $event: obj, $target: scope.$eval(scope.value)}); }); } } if (attrs.ngdragstop) { $timeout(function(){ ondragstopcallback(scope, {$data: obj.data, $event: obj}); }); } updatedragstyles(false, obj.element); }; var istouching = function(mousex, mousey, dragelement) { var touching= hittest(mousex, mousey); scope.istouching = touching; if(touching){ _lastdroptouch = element; } updatedragstyles(touching, dragelement); return touching; }; var updatedragstyles = function(touching, dragelement) { if(touching){ element.addclass('drag-enter'); dragelement.addclass('drag-over'); }else if(_lastdroptouch == element){ _lastdroptouch=null; element.removeclass('drag-enter'); dragelement.removeclass('drag-over'); } }; var hittest = function(x, y) { var bounds = element[0].getboundingclientrect();// ngdraggable.getprivoffset(element); x -= $document[0].body.scrollleft + $document[0].documentelement.scrollleft; y -= $document[0].body.scrolltop + $document[0].documentelement.scrolltop; return x >= bounds.left && x <= bounds.right && y <= bounds.bottom && y >= bounds.top; }; initialize(); } }; }]) .directive('ngdragclone', ['$parse', '$timeout', 'ngdraggable', function ($parse, $timeout, ngdraggable) { return { restrict: 'a', link: function (scope, element, attrs) { var img, _allowclone=true; var _dragoffset = null; scope.cloneddata = {}; var initialize = function () { img = element.find('img'); element.attr('draggable', 'false'); img.attr('draggable', 'false'); reset(); togglelisteners(true); }; var togglelisteners = function (enable) { // remove listeners if (!enable)return; // add listeners. scope.$on('draggable:start', ondragstart); scope.$on('draggable:move', ondragmove); scope.$on('draggable:end', ondragend); preventcontextmenu(); }; var preventcontextmenu = function() { // element.off('mousedown touchstart touchmove touchend touchcancel', absorbevent_); img.off('mousedown touchstart touchmove touchend touchcancel', absorbevent_); // element.on('mousedown touchstart touchmove touchend touchcancel', absorbevent_); img.on('mousedown touchstart touchmove touchend touchcancel', absorbevent_); }; var ondragstart = function(evt, obj, elm) { _allowclone=true; if(angular.isdefined(obj.data.allowclone)){ _allowclone=obj.data.allowclone; } if(_allowclone) { scope.$apply(function () { scope.cloneddata = obj.data; }); element.css('width', obj.element[0].offsetwidth); element.css('height', obj.element[0].offsetheight); moveelement(obj.tx, obj.ty); } }; var ondragmove = function(evt, obj) { if(_allowclone) { _tx = obj.tx + obj.dragoffset.left; _ty = obj.ty + obj.dragoffset.top; moveelement(_tx, _ty); } }; var ondragend = function(evt, obj) { //moveelement(obj.tx,obj.ty); if(_allowclone) { reset(); } }; var reset = function() { element.css({left:0,top:0, position:'fixed', 'z-index':-1, visibility:'hidden'}); }; var moveelement = function(x,y) { element.css({ transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', 'z-index': 99999, 'visibility': 'visible', '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', '-ms-transform': 'matrix(1, 0, 0, 1, '+x+', '+y+')' //,margin: '0' don't monkey with the margin, }); }; var absorbevent_ = function (event) { var e = event;//.originalevent; e.preventdefault && e.preventdefault(); e.stoppropagation && e.stoppropagation(); e.cancelbubble = true; e.returnvalue = false; return false; }; initialize(); } }; }]) .directive('ngpreventdrag', ['$parse', '$timeout', function ($parse, $timeout) { return { restrict: 'a', link: function (scope, element, attrs) { var initialize = function () { element.attr('draggable', 'false'); togglelisteners(true); }; var togglelisteners = function (enable) { // remove listeners if (!enable)return; // add listeners. element.on('mousedown touchstart touchmove touchend touchcancel', absorbevent_); }; var absorbevent_ = function (event) { var e = event.originalevent; e.preventdefault && e.preventdefault(); e.stoppropagation && e.stoppropagation(); e.cancelbubble = true; e.returnvalue = false; return false; }; initialize(); } }; }]) .directive('ngcanceldrag', [function () { return { restrict: 'a', link: function (scope, element, attrs) { element.find('*').attr('ng-cancel-drag', 'ng-cancel-drag'); } }; }]) .directive('ngdragscroll', ['$window', '$interval', '$timeout', '$document', '$rootscope', function($window, $interval, $timeout, $document, $rootscope) { return { restrict: 'a', link: function(scope, element, attrs) { var intervalpromise = null; var lastmouseevent = null; var config = { verticalscroll: attrs.verticalscroll || true, horizontalscroll: attrs.horizontalscroll || true, activationdistance: attrs.activationdistance || 75, scrolldistance: attrs.scrolldistance || 15 }; var reqanimframe = (function() { return window.requestanimationframe || window.webkitrequestanimationframe || window.mozrequestanimationframe || window.orequestanimationframe || window.msrequestanimationframe || function( /* function framerequestcallback */ callback, /* domelement element */ element ) { window.settimeout(callback, 1000 / 60); }; })(); var animationison = false; var createinterval = function() { animationison = true; function nextframe(callback) { var args = array.prototype.slice.call(arguments); if(animationison) { reqanimframe(function () { $rootscope.$apply(function () { callback.apply(null, args); nextframe(callback); }); }) } } nextframe(function() { if (!lastmouseevent) return; var viewportwidth = math.max(document.documentelement.clientwidth, window.innerwidth || 0); var viewportheight = math.max(document.documentelement.clientheight, window.innerheight || 0); var scrollx = 0; var scrolly = 0; if (config.horizontalscroll) { // if horizontal scrolling is active. if (lastmouseevent.clientx < config.activationdistance) { // if the mouse is on the left of the viewport within the activation distance. scrollx = -config.scrolldistance; } else if (lastmouseevent.clientx > viewportwidth - config.activationdistance) { // if the mouse is on the right of the viewport within the activation distance. scrollx = config.scrolldistance; } } if (config.verticalscroll) { // if vertical scrolling is active. if (lastmouseevent.clienty < config.activationdistance) { // if the mouse is on the top of the viewport within the activation distance. scrolly = -config.scrolldistance; } else if (lastmouseevent.clienty > viewportheight - config.activationdistance) { // if the mouse is on the bottom of the viewport within the activation distance. scrolly = config.scrolldistance; } } if (scrollx !== 0 || scrolly !== 0) { // record the current scroll position. var currentscrollleft = ($window.pagexoffset || $document[0].documentelement.scrollleft); var currentscrolltop = ($window.pageyoffset || $document[0].documentelement.scrolltop); // remove the transformation from the element, scroll the window by the scroll distance // record how far we scrolled, then reapply the element transformation. var elementtransform = element.css('transform'); element.css('transform', 'initial'); $window.scrollby(scrollx, scrolly); var horizontalscrollamount = ($window.pagexoffset || $document[0].documentelement.scrollleft) - currentscrollleft; var verticalscrollamount = ($window.pageyoffset || $document[0].documentelement.scrolltop) - currentscrolltop; element.css('transform', elementtransform); lastmouseevent.pagex += horizontalscrollamount; lastmouseevent.pagey += verticalscrollamount; $rootscope.$emit('draggable:_triggerhandlermove', lastmouseevent); } }); }; var clearinterval = function() { animationison = false; }; scope.$on('draggable:start', function(event, obj) { // ignore this event if it's not for this element. if (obj.element[0] !== element[0]) return; if (!animationison) createinterval(); }); scope.$on('draggable:end', function(event, obj) { // ignore this event if it's not for this element. if (obj.element[0] !== element[0]) return; if (animationison) clearinterval(); }); scope.$on('draggable:move', function(event, obj) { // ignore this event if it's not for this element. if (obj.element[0] !== element[0]) return; lastmouseevent = obj.event; }); } }; }]);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。