Animations

14

Μεταφρασμένο Ποσοστό

Σε αυτό το κεφάλαιο θα:

  • See what happens behind the scenes when Meteor swaps two DOM elements.
  • Learn how to animate the reordering of posts.
  • Learn how to animate the insertion of new posts.
  • Out of Date?

    ////

    ////

    ////

    Meteor & the DOM

    ////

    ////

    ////

    The Soviet Runner

    ////

    ////

    ////

    Breaking It Down

    ////

    ////

    //// //// //// //// //// ////

    ////

    Switching two posts
    Switching two posts

    ////

    ////

    ////

    Proper Timing

    ////

    ////

    ////

    ////

    ////

    ////

    CSS Positioning

    ////

    ////

    ////

    ////

    ////

    .post{
      position:relative;
      transition:all 300ms 0ms ease-in;
    }
    
    client/stylesheets/style.css

    ////

    ////

    Position:absolute

    ////

    ////

    Total Recall

    ////

    ////

    Ranking Posts

    ////

    ////

    ////

    ////

    Template.postsList.helpers({
      postsWithRank: function() {
        return this.posts.map(function(post, index, cursor) {
          post._rank = index;
          return post;
        });
      }
    });
    
    /client/templates/posts/posts_list.js

    ////

    ////

    <template name="postsList">
      <div class="posts">
        {{#each postsWithRank}}
          {{> postItem}}
        {{/each}}
    
        {{#if nextPath}}
          <a class="load-more" href="{{nextPath}}">Load more</a>
        {{/if}}
      </div>
    </template>
    
    /client/templates/posts/posts_list.html

    Putting It Together

    ////

    //// //// ////

    ////

    //// ////

    /client/templates/posts/post_item.html

    ////

    ////

    var POST_HEIGHT = 80;
    var Positions = new Mongo.Collection(null);
    
    Template.postItem.helpers({
    
      //..
    
      },
      attributes: function() {
        var post = _.extend({}, Positions.findOne({postId: this._id}), this);
        var newPosition = post._rank * POST_HEIGHT;
        var attributes = {};
    
        if (! _.isUndefined(post.position)) {
          var offset = post.position - newPosition;      
          attributes.style = "top: " + offset + "px";
          if (offset === 0)
            attributes.class = "post animate"
        }
    
        Meteor.setTimeout(function() {
          Positions.upsert({postId: post._id}, {$set: {position: newPosition}})
        });
    
        return attributes;
      }
    });
    
    //..
    
    /client/templates/posts/post_item.js

    ////

    ////

    ////

    Running Schedule

    ////

    ////

    ////

    The Attributes Helper

    ////

    ////

    ////

    ////

    ////

    ////

    Timing Out

    ////

    ////

    • ////
    • ////
    • ////
    • ////
    • ////

    ////

    • ////
    • ////
    • ////
    • ////
    • ////
    • ////

    ////

    Animating New Posts

    ////

    //..
    
    attributes: function() {
      var post = _.extend({}, Positions.findOne({postId: this._id}), this);
      var newPosition = post._rank * POST_HEIGHT;
      var attributes = {};
    
      if (_.isUndefined(post.position)) {
        attributes.class = 'post invisible';
      } else {
        var delta = post.position - newPosition;      
        attributes.style = "top: " + delta + "px";
        if (delta === 0)
          attributes.class = "post animate"
      }
    
      Meteor.setTimeout(function() {
        Positions.upsert({postId: post._id}, {$set: {position: newPosition}})
      });
    
      return attributes;
    }
    
    //..
    
    /client/templates/posts/post_item.js

    ////

    CSS & JavaScript

    ////

    ////

    ////