angular.jsをやってみる (23) - ngTouchを使ってスワイプイベントを利用 -
公式リファレンス: 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しなくても出来る