angular.jsをやってみる (23) - ngTouchを使ってスワイプイベントを利用 -

2014-04-14T00:00:00+00:00 angular.js JavaScript

公式リファレンス: http://docs.angularjs.org/api/ngTouch

スマートフォン等においてカルーセルビュー的な例でスワイプする事でビューを切り替えたり出来るようにしたいとかの場合にはngTouchを使う事で出来る模様

index.html

<!DOCTYPE html>
<html ng-app="app">
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.5/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.5/angular-touch.js"></script>
    <script src="app.js"></script>
    <link rel="stylesheet" href="style.css" />
  </head>
  <!-- 画像をドラッグ出来ないようにする (Firefox) -->
  <body onselectstart="return false;" onmousedown="return false;">
    <div id="container" ng-controller="SampleController">
      <div id="carousel"></div>
    </div>
  </body>
</html>

で諸問題が画像な所にスワイプイベントをするとPCとかの場合にはクリックしてスライドさせるのだけど、これだと画像がドラッグ出来たりとかしちゃうので

#container {
  width: 300px;
  height: 300px;
}

.carousel {
  width: 300px;
  height: 300px;
  border: 1px solid;
}

.carousel-img {
  -webkit-user-select: none;
  -webkit-user-drag: none;
  -moz-user-select: none;
  user-select: none;
  width: 300px;
  height: 300px;
}

的な感じでuser-selectとかソッチ系なベンダープレフィックスなCSSを定義しておけば良いらしい。だけどFirefoxの場合はこれだけで作用しないので、にそういう系を無効にするのを記述しておく。詳しくはドラッグによるテキストの選択をキャンセルする

app.js

angular.module("app", ["ngTouch"])
  .controller("SampleController", function($swipe) {
    var rootElement = angular.element("#carousel");

    // ImageIteratorは単純にインデックスに対応する画像パスを取り出すだけなやつ
    var itr = new ImageIterator();

    var addImage = function(source) {
      angular.element(".carousel").remove();

      // <div class="carousel"></div>
      var elm1 = angular.element("<div>");
      elm1.addClass("carousel");

      // <img src="..." class="carousel-img" />
      var elm2 = angular.element("<img>");
      elm2.attr("src", source);
      elm2.addClass("carousel-img");

      // <div class="carousel"><img src="..." class="carousel-img" /></div>
      elm1.append(elm2);

      rootElement.append(elm1);
    };

    var x;

    $swipe.bind(
      rootElement,
      {
        start: function(coords) {
          x = coords.x;
        },
        end: function(coords) {
          // 終点のXよりもスタート地点のXの方が大きい場合はleft swipe
          // スタート地点のXよりも終点のXの方が大きい場合はright swipe
          if (x > coords.x) {
            var source = itr.prev();
            if (source != null) {
              addImage(source);
            }
          } else if (x < coords.x) {
            var source = itr.next();
            if (source != null) {
              addImage(source);
            }
          }

          // ココらへんで変数x自体は初期化なりすべきなのかも
        }
      }
    );

    addImage(itr.current());
  });

っていう感じで$swipe.bindでstart/end等のイベントを定義する事が出来て、指定したエレメントのスワイプイベントに対して適切なイベントを発生させる事が出来る模様

んまぁていうかんじでスワイプなイベントを利用したい場合にはngTouchな$swipeを利用する事で可能って事で

余談: left/rightなスワイプに関して

left/rightなスワイプだけに関してはng-swipe-left/ng-swipe-rightなディレクティブがngTouchによってサポートされているので

angular.module("app", ["ngTouch"])
  .controller("SampleController", function($scope) {
    $scope.swipeLeft = function() { alert("left"); };
    $scope.swipeRight = function() { alert("right"); };
  });

<!DOCTYPE html>
<html ng-app="app">
  <head>
    <script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.5/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.5/angular-animate.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.5/angular-touch.js"></script>
    <script src="app.js"></script>
  </head>
  <body>
    <div id="container" ng-controller="SampleController">
      <div ng-swipe-left="swipeLeft()" ng-swipe-right="swipeRight()">swipe me</div>
    </div>
  </body>
</html>

っていう感じでディレクティブで処理を行わせる事が可能。つまり上記で書いたように$swipe.bindしなくても出来る

「Can’t connect to local MySQL server through socket」について