2013-11-14 17 views
5

Meine AngularJS-App muss sowohl den Start als auch den Stopp eines Berührungsereignisses erkennen können (ohne zu wischen). Zum Beispiel muss ich eine Logik ausführen, wenn die Berührung beginnt (der Benutzer drückt ihren Finger und hält) und führt dann unterschiedliche Logik aus, wenn die gleiche Berührung endet (der Benutzer entfernt ihren Finger). Ich bin dabei, ngTouch für diese Aufgabe zu implementieren, aber die Dokumentation für die ngTouch.ngClick-Anweisung erwähnt nur das Abfeuern des Ereignisses durch Antippen. Der ngTouch. $ Swipe-Dienst kann das Starten und Stoppen des Berührungsereignisses erkennen, aber nur, wenn der Benutzer während des Berührens tatsächlich über den Finger wischte (den Finger horizontal oder vertikal bewegte). Hat jemand Ideen? Muss ich meine eigene Direktive schreiben?Kann die ngTouch-Bibliothek von angular verwendet werden, um ein Ereignis mit langem Klick (berühren/halten/loslassen) zu erkennen?

Antwort

12

-Update 11/25/14:

Die dicktengleiche Winkel Hammer-Bibliothek ist jetzt veraltet, so dass das Hammer.js Team recommend die ryan mullins version zu verwenden, die über Hammer v2.0 + gebaut wird.


Ich grub in ngTouch und von dem, was ich kann sagen, es hat keine Unterstützung für etwas anderes als Tippen und Streichen (ab dem Zeitpunkt des Schreibens dieses Artikels, Version 1.2.0). Ich entschied mich für eine ausgereiftere Multitouch-Bibliothek (hammer.js) und ein gut getestetes und gewartetes Winkelmodul (Hammer), das alle Multi-Touch-Funktionen von hammer.js als Attribut-Direktiven enthält.

https://github.com/monospaced/angular-hammer

+0

Warum auf ein gegabeltes Repo zeigen? –

+7

@ PhươngNguyễn Weil das Repository, von dem es gespalten wird, älter ist, nicht mehr aktiv gepflegt wird, keine Versions-Tags enthält, und zu der Zeit, als ich das postete, unterstützte es auch keine Bower. Ich habe mich in den Code der verschiedenen Versionen vertieft und die monospaced Version ist die beste. – Egg

+5

Auch nicht sicher, warum so viele Leute diese Antwort ablehnen. Es wäre großartig, wenn einige von ihnen Gründe dafür angeben würden, damit sie verbessert werden könnten. Ich benutze diese Lösung nun schon seit fast einem Jahr in mehreren Enterprise/Production eckigen Projekten und es hat ziemlich gut funktioniert, und bis jetzt hat ngTouch immer noch einige ernste Probleme und keine Unterstützung für verschiedene Gesten. Wenn Sie bessere Möglichkeiten kennen, sagen Sie es bitte. – Egg

3

Die dicktengleiche Winkel Hammer-Bibliothek ist jetzt veraltet, so recommend die Hammer.js Team die ryan mullins version zu verwenden, die über Hammer v2.0 + gebaut wird.

+1

Das sind einige gute Informationen, danke! Ich ging weiter und fügte es hinzu, um sicherzustellen, dass die Leute es nicht verpassen. – Egg

3

Es ist eine gute Umsetzung:

// pressableElement: pressable-element 
.directive('pressableElement', function ($timeout) { 
    return { 
     restrict: 'A', 
     link: function ($scope, $elm, $attrs) { 
      $elm.bind('mousedown', function (evt) { 
       $scope.longPress = true; 
       $scope.click = true; 

       // onLongPress: on-long-press 
       $timeout(function() { 
        $scope.click = false; 
        if ($scope.longPress && $attrs.onLongPress) { 
         $scope.$apply(function() { 
          $scope.$eval($attrs.onLongPress, { $event: evt }); 
         }); 
        } 
       }, $attrs.timeOut || 600); // timeOut: time-out 

       // onTouch: on-touch 
       if ($attrs.onTouch) { 
        $scope.$apply(function() { 
         $scope.$eval($attrs.onTouch, { $event: evt }); 
        }); 
       } 
      }); 

      $elm.bind('mouseup', function (evt) { 
       $scope.longPress = false; 

       // onTouchEnd: on-touch-end 
       if ($attrs.onTouchEnd) { 
        $scope.$apply(function() { 
         $scope.$eval($attrs.onTouchEnd, { $event: evt }); 
        }); 
       } 

       // onClick: on-click 
       if ($scope.click && $attrs.onClick) { 
        $scope.$apply(function() { 
         $scope.$eval($attrs.onClick, { $event: evt }); 
        }); 
       } 
      }); 
     } 
    }; 
}) 

Anwendungsbeispiel:

<div pressable-element 
    ng-repeat="item in list" 
    on-long-press="itemOnLongPress(item.id)" 
    on-touch="itemOnTouch(item.id)" 
    on-touch-end="itemOnTouchEnd(item.id)" 
    on-click="itemOnClick(item.id)" 
    time-out="600" 
    >{{item}}</div> 

var app = angular.module('pressableTest', []) 
 

 
.controller('MyCtrl', function($scope) { 
 
    $scope.result = '-'; 
 

 
    $scope.list = [ 
 
     { id: 1 }, 
 
     { id: 2 }, 
 
     { id: 3 }, 
 
     { id: 4 }, 
 
     { id: 5 }, 
 
     { id: 6 }, 
 
     { id: 7 } 
 
    ]; 
 

 
    $scope.itemOnLongPress = function (id) { $scope.result = 'itemOnLongPress: ' + id; }; 
 
    $scope.itemOnTouch = function (id) { $scope.result = 'itemOnTouch: ' + id; }; 
 
    $scope.itemOnTouchEnd = function (id) { $scope.result = 'itemOnTouchEnd: ' + id; }; 
 
    $scope.itemOnClick = function (id) { $scope.result = 'itemOnClick: ' + id; }; 
 
}) 
 

 
.directive('pressableElement', function ($timeout) { 
 
    return { 
 
     restrict: 'A', 
 
     link: function ($scope, $elm, $attrs) { 
 
      $elm.bind('mousedown', function (evt) { 
 
       $scope.longPress = true; 
 
       $scope.click = true; 
 
       $scope._pressed = null; 
 

 
       // onLongPress: on-long-press 
 
       $scope._pressed = $timeout(function() { 
 
        $scope.click = false; 
 
        if ($scope.longPress && $attrs.onLongPress) { 
 
         $scope.$apply(function() { 
 
          $scope.$eval($attrs.onLongPress, { $event: evt }); 
 
         }); 
 
        } 
 
       }, $attrs.timeOut || 600); // timeOut: time-out 
 

 
       // onTouch: on-touch 
 
       if ($attrs.onTouch) { 
 
        $scope.$apply(function() { 
 
         $scope.$eval($attrs.onTouch, { $event: evt }); 
 
        }); 
 
       } 
 
      }); 
 

 
      $elm.bind('mouseup', function (evt) { 
 
       $scope.longPress = false; 
 
       $timeout.cancel($scope._pressed); 
 

 
       // onTouchEnd: on-touch-end 
 
       if ($attrs.onTouchEnd) { 
 
        $scope.$apply(function() { 
 
         $scope.$eval($attrs.onTouchEnd, { $event: evt }); 
 
        }); 
 
       } 
 

 
       // onClick: on-click 
 
       if ($scope.click && $attrs.onClick) { 
 
        $scope.$apply(function() { 
 
         $scope.$eval($attrs.onClick, { $event: evt }); 
 
        }); 
 
       } 
 
      }); 
 
     } 
 
    }; 
 
})
li { 
 
    cursor: pointer; 
 
    margin: 0 0 5px 0; 
 
    background: #FFAAAA; 
 
}
<div ng-app="pressableTest"> 
 
    <div ng-controller="MyCtrl"> 
 
     <ul> 
 
      <li ng-repeat="item in list" 
 
       pressable-element 
 
       on-long-press="itemOnLongPress(item.id)" 
 
       on-touch="itemOnTouch(item.id)" 
 
       on-touch-end="itemOnTouchEnd(item.id)" 
 
       on-click="itemOnClick(item.id)" 
 
       time-out="600" 
 
       >{{item.id}}</li> 
 
     </ul> 
 
     <h3>{{result}}</h3> 
 
    </div> 
 
</div> 
 

 
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

Basierend auf: https://gist.github.com/BobNisco/9885852

+1

Schön! Muss neu gewählt werden. –