栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > JavaScript

深究AngularJS中ng-drag、ng-drop的用法

JavaScript 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

深究AngularJS中ng-drag、ng-drop的用法

1.相关地址:

插件下载:https://github.com/fatlinesofcode/ngDraggable/blob/master/ngDraggable.js

2.讲解


  
  • 姓名:{{item.name}},年龄:{{item.age}}
  • ng-drag : 表示该元素能够被拖动

    ng-drag-data: 表示拖动元素时跟着被拖走的数据

    ng-drop : 表示该元素内可放置被拖动的元素

    ng-drop-success : 放置在ngd-drop所在元素里后触发,一般写事件.

    ng-drop-success触发的dropComplete方法的参数说明:

    1. $index : 表示拖动的数据所落的元素的下标
    2. $data: 被拖动的数据对象

    3.拖拽排序示例

    页面代码

    
      
  • 姓名:{{item.name}},年龄:{{item.age}}
  • js代码

    //数据
    $scope.content = [{'name':'张春玲','age':28},{'name':'王晰','age':26},{'name':'吴正青','age':66}];
    
    
    $scope.dropComplete = function(index, obj){
        //重新排序
        var idx = $scope.content.indexOf(obj);
        $scope.content.splice(idx,1);
        $scope.content.splice(index,0,obj);  
    
    };
    
    

    4.拖拽交换示例

    页面代码

    
      
  • 姓名:{{item.name}},年龄:{{item.age}}
  • JS代码

    //数据
    $scope.content = [{'name':'张春玲','age':28},{'name':'王晰','age':26},{'name':'吴正青','age':66}];
    
    
    $scope.dropComplete = function(index, obj){
        var idx = $scope.content.indexOf(obj); 
        $scope.content[idx] = $scope.content[index];
        $scope.content[index] = obj;      
    };
    
    5. 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"))
       );
     };
     
     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(  callback,  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;
     });
          }
        };
      }]);
    
    

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

    转载请注明:文章转载自 www.mshxw.com
    本文地址:https://www.mshxw.com/it/87137.html
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

    版权所有 (c)2021-2022 MSHXW.COM

    ICP备案号:晋ICP备2021003244-6号