使用Ionic和AngularJS创建可以滑动的卡片

来源:互联网 发布:女生学编程好吗 编辑:程序博客网 时间:2024/06/04 18:54

这篇文章讲的是怎么样使用Ionic和AngularJS创建可以滑动的卡片,下面是demo:

demo和代码

原文地址:http://www.ionicframework.com/blog/ionic-swipeable-cards/index.html

卡片堆栈

我们可以看到这个组件其实就是在一组卡片堆栈中进行滑动。这意味着我们需要一些控制器(View Controller)来管理这些卡片,当滑动时推出一个卡片并且让另一个新的卡片进入堆栈,让我们看一下是怎么写的。

var SwipeableCardController = ionic.controllers.ViewController.inherit({  initialize: function(opts) {    this.cards = [];    // 根据opts进行初始化  },  pushCard: function(card) {    this.cards.push(card);    // 显示卡片  },  popCard: function() {    var card = this.cards.pop();    // 卡片消失的动画  }})
这就是控制器的核心啦!除了管理堆栈,还需要初始化每一张卡片并且告诉它们消失时的动画,仅此而已!

相对控制器,视图就复杂一些,它需要对卡片界面进行渲染(控制器只需要管理逻辑就可以),它还要对DOM元素进行跟踪并且为其附上监听的事件。

在下面的例子中,我已经列出了一小段代码,里面讲了拖动时会发生什么,所有的代码在代码库里:

var SwipeableCardView = ionic.views.View.inherit({  initialize: function(opts) {    // 保存卡片元素    this.el = opts.el;    this.bindEvents();  },  bindEvents: function() {    var self = this;    ionic.onGesture('dragstart', function(e) {      // 拖动过程开始    }, this.el);    ionic.onGesture('drag', function(e) {      // 拖动的过程      window.rAF(function() {        self._doDrag(e);      });    }, this.el);    ionic.onGesture('dragend', function(e) {      // 拖动过程结束    }, this.el);  },  _doDrag: function(e) {    // 在拖动的过程中计算出我们已经拖多远    var o = e.gesture.deltaY / 3;    // Get the angle of rotation based on the    // drag distance and our distance from the     // center of the card (computed in dragstart),    // and the side of the card we are dragging from    this.rotationAngle = Math.atan(o/this.touchDistance) * this.rotationDirection;    // Don't rotate if dragging up    if(e.gesture.deltaY < 0) {      this.rotationAngle = 0;    }    // Update the y position of this view    this.y = this.startY + (e.gesture.deltaY * 0.4);    // Apply the CSS transformation to the card,    // translating it up or down, and rotating    // it based on the computed angle    this.el.style[ionic.CSS.TRANSFORM] = 'translate3d(' + this.x + 'px, ' + this.y  + 'px, 0) rotate(' + (this.rotationAngle || 0) + 'rad)';  }});
这就是ionic的强大之处,我们可以监听各种复杂的手势例如拖拽,向一个特定的方向拖动,轻扫,双指缩放和其他很酷的手势(使用Hammer.js)

手势系统会告诉我们已经拖了多远(如上面那个例子中的gesture.deltaY)和拖动的速度和角度。

AngluarJS的帮助

如果我们只有上面的视图和控制器的话,我们就不得不自己写一些js来管理它们。我们希望的是创建一些DOM节点来显示卡片,为这些节点实例化一些SwipeableCardView,并且把他们放在一个控制器上就行了。如果没有AngluarJS来集成这个卡片堆栈的话,我们必须手写这些烦人的代码,为此我们必须创建一些自定义指令,现在,我们假设指令是这样的:

<swipe-cards>  <swipe-card ng-repeat="card in cards" on-destroy="cardDestroyed($index)" on-swipe="cardSwiped($index)">    <!-- Card content here -->  </swipe-card></swipe-cards>
我们使用上面的这个自定义元素来指定,这整个元素又SwipeableCardController来管理,每一个孩子<swipe-card>就是一个SwipeableCardView视图实例。

让我们从<swipe-cards>开始把,它比较简单:

// 定义模块名称,加载ionic代码angular.module('ionic.contrib.ui.cards', ['ionic']).directive('swipeCards', ['$rootScope', function($rootScope) {  return {    restrict: 'E',    template: '<div class="swipe-cards" ng-transclude></div>',    replace: true,    transclude: true,    scope: {},    controller: function($scope, $element) {      // Instantiate the controller      var swipeController = new SwipeableCardController({      });      // We add a root scope event listener to facilitate interacting with the      // directive incase of no direct scope access      $rootScope.$on('swipeCard.pop', function(isAnimated) {        swipeController.popCard(isAnimated);      });      // return the object so it is accessible to child      // directives that 'require' this directive as a parent.      return swipeController;    }  }}])
接下来看看<swipe-card>:

.directive('swipeCard', ['$timeout', function($timeout) {  return {    restrict: 'E',    template: '<div class="swipe-card" ng-transclude></div>',    // Requiring the swipeCards directive makes the controller available    // in the linking function    require: '^swipeCards',    replace: true,    transclude: true,    scope: {      onSwipe: '&',      onDestroy: '&'    },    compile: function(element, attr) {      return function($scope, $element, $attr, swipeCards) {        var el = $element[0];        // Instantiate our card view        var swipeableCard = new SwipeableCardView({          el: el,          onSwipe: function() {            $timeout(function() {              $scope.onSwipe();            });          },          onDestroy: function() {            $timeout(function() {              $scope.onDestroy();            });          },        });        // Make the card available to the parent scope, not necessary        // but makes it easier to interact with (similar to iOS exposing        // parent controllers and views dynamically to children)        $scope.$parent.swipeCard = swipeableCard;        // We can push a new card onto the controller card stack, animating it in        swipeCards.pushCard(swipeableCard);      }    }  }}])

我喜欢使用一个很小的AngularJS来处理像滑动卡片这么复杂的组件,事实上,大多数控制器和视图已经暴露在ionic的代码里了。

我们被问及最多的问题是什么时候使用directives指令来替换DOM元素,其实很多时候都是因为这个组件会被广泛使用。




0 0
原创粉丝点击