animate + ng-repeat 优雅的解决方案?

animate + ng-repeat in an elegant solution?

我有一个用 ng-repeat 构建的列表,我正在尝试在元素改变位置时为列表设置动画。

我试图将这个想法建立在 this codepen 的基础上,但是,我一直没有很好地让它发挥作用。

需要发生的是:

  1. 用户点击图钉
  2. 如果 pin 是灰色的(现在是红色的),固定的项目需要转到列表的顶部(在其过滤范围内)
  3. 如果引脚是红色的,现在是灰色的,它需要在其范围内的所有红色引脚下方。
  4. 需要为这种情况制作动画,用户可以看到新的红色图钉到达新位置,反之亦然,新的灰色图钉到达新位置。

如果有人能帮助我,那就太棒了。

This is what I have been working with (JSFiddle)

控制器

angular.module('MyApp', ['ngAnimate'])
.controller('App', function($scope){
  $scope.myData = [{
    id: 1,
    historyContact: [
            {
                "date": "2017-05-30T04:00:00.000Z",
                "time": "12:12pm",
                "method": "Incoming",
                "direction": "Inbound",
                "result": "answered",
                "notes": "a",
                "pin": true,
                "_id": 1
            }, {
                "date": "2017-05-30T04:00:00.000Z",
                "time": "12:12pm",
                "method": "Incoming",
                "result": "answered",
                "direction": "Inbound",
                "notes": "b",
                "pin": false,
                "_id": 2
            }, {
                "date": "2017-05-30T04:00:00.000Z",
                "time": "12:12pm",
                "method": "Incoming",
                "result": "answered",
                "direction": "Inbound",
                "notes": "c",
                "pin": false,
                "_id": 3
            }
        ]
  }];

  $scope.noteClicked = function(note) {
        console.log("clicked", note)
        if (note.pin == true) {
                note.pin = false;
            } else {
                note.pin = true;
            }
  };




});

模板

<div ng-controller="App" >
  <p>
    <p>
      <div class="note-wrapper itemPin" ng-repeat="note in myData[0].historyContact | orderBy: ['-pin', '-date' ] track by note._id">
        <div class="contact-history-date-device-wrapper">
          <p class="contact-history-date-device-text">
            {{note.date | date:'MMMM dd, yyyy'}} - {{note.time}}
          </p>
        </div>
        <div class="chat-wrap">
          <p class="chat-identifier">
            {{note.method}} | {{note.direction}}
          </p>
          <p class="chat-identifier">
            Contact Result: {{note.result}}
          </p>
        </div>


        <div class="pin-container">
          <div >
            <div ng-if="note.pin == true" >
              <img class="pin" src="http://i.imgur.com/QdFPdjY.png" ng-click="noteClicked(note)">
            </div>
            <div ng-if="note.pin == false" >
              <img class="pin" src="http://i.imgur.com/nNpprk2.png" ng-click="noteClicked(note)">
            </div>
          </div>
        </div>

        <div class="contact-history-note-text-wrapper">
          <p class="contact-history-note-atext">
            {{note.notes}}
          </p>
        </div>



        <hr> 

      </div>
</div>

样式

$font-stack:    'Roboto', sans-serif;
.metawrapper {
  position: relative;
}

.scrollbox-contact {
  width:100%;

  // no needed because #grid-container--ui-view has already overflow scroll param by kei
  /*
  overflow:auto;
  */
  overflow-x: hidden;

  height: 100%;
  position: absolute;
  padding-top: 50px; /* header height*/
  top: 0px;

}

.contact-history-header {
  background-color: #F8F8F8;
  height: 50px;
  width: 100%;
  position: absolute;
  top: 0px;
  left: 0px;
}

.header-title {
  font-family: $font-stack;
  font-size: 15px;
  color: #364350;
  font-weight: 400;
  text-align: left;
  line-height: 50px;
  letter-spacing: 1px;
  margin-left: 30px;
}


.pencil-icon {
  position: relative;
  margin-left: 20px;
  margin-top: 15px;
}

.contact-history-date-device-text {
  font-family: $font-stack;
  font-size: 16px;
  font-weight: 500;
  color: rgb(80, 92, 100);
  text-transform: capitalize;
}

.contact-history-date-device-wrapper {
  margin-top: 25px;
  margin-left: 25px;
  display: inline-block;
}

.contact-history-note-text-wrapper {
  height: auto;
  width: 80%;
  overflow: hidden;
  margin-left: 25px;
  display: block;
  position: relative;
  bottom: 5px;
  margin-top: 4px;
}

.contact-history-note-text {
  font-family: 'Lato', sans-serif;
  font-weight: 400;
  color: #505C64;
  // height: 14px;
}

.contact-history-horizontal-line {
  height: 1px;
  width: 90%;
  margin-left: 5%;
  margin-right: 5%;
  background-color: rgba(80, 92, 100, 0.1);
  margin-top: 20px;
  margin-bottom: 20px;
}

.contact-history-horizontal-line2 {
  height: 1px;
  width: 85%;
  margin-left: 5%;
  margin-right: 10%;
  background-color: rgba(80, 92, 100, 0.1);
  margin-top: 40px;
  margin-bottom: 30px;
}

.contact-history-button {
  width: 175px;
  height: 36px;
  border-radius: 3px;
  border: 1px solid;
  border-color: rgba(119, 119, 119, 0.4);
  position: relative;
  left: 75%;
  bottom: 20px;
}

// ANIMATION FOR PIN MOVEMENT
// like .list-item in the animation walkthough
.note-wrapper {
  &:after {
  clear: both;
  content: '';
  display: block;
  }
  &.ng-move {
   animation: list-sort-flip-top 0.4s ease-in;
   transform: translate(0, 100%);
   z-index: 2;
   & + .note-wrapper {
     transform: translate(0, -100%);
     z-index: -1;
   }
   &.ng-move-active {
     & + .note-wrapper {
       animation: list-sort-flip-bottom 0.4s ease-in;
     }
   }
 }
}

@keyframes list-sort-flip-top {
  0% {
    transform: rotate(0) translate(0, 100%) rotate(0);
  }

  50% {
    transform: rotate(45deg) translate(0, 50%) rotate(-45deg)
  }

  100% {
    transform: rotate(90deg) translate(0, 0) rotate(-90deg)
  }
}

@keyframes list-sort-flip-bottom {
  0% {
    transform: rotate(0) translate(0, -100%) rotate(0);
  }

  50% {
    transform: rotate(45deg) translate(0, -50%) rotate(-45deg);
  }

  100% {
    transform: rotate(90deg) translate(0, 0) rotate(-90deg);
  }
}

@keyframes list-sort-slide-top {
  0% {
    transform:translate(0, 100%);
  }

  75% {
    transform:translate(0, 100%);
  }

  100% {
    transform:translate(0, 0);
  }
}

@keyframes list-sort-slide-bottom {
  0% {
    transform: translate(0, -100%);
  }

  25% {
    transform: translate(100%, -100%);
  }

  75% {
    transform: translate(100%, 80%);
  }

  80% {
    transform: translate(90%, 60%) skew(-50deg, 1deg);
  }

  100% {
    transform: translate(0, 0) skew(0, 0);
  }
}
//END ANIMATIONB

.edit-note-wrapper {
  display: none;
  margin-left: 20px;
  margin-top: 20px;
  width: 100%;
}

.save-btn {
  left: 1% !important;
}

.edit-contact-history-button {
  width: 25%;
  height: 36px;
  border-radius: 3px;
  border: 1px solid;
  border-color: rgba(119, 119, 119, 0.4);
  display: inline-block !important;
  position: relative;

}

.chat-identifier {
  font-size: 14px;
  font-family: $font-stack;
  font-weight: 300;
  color: #505C64;
}

.chat-wrap {
  position: relative;
  left: 25px;
  top: 5px;
}

.pin-container {
  position: relative;
  left: 90%;
  bottom: 35px;
}

.who-wrote-this {
  position: relative;
  left: 25%;
  p {
    color: #3da5d9;
    font-weight: 500;
    font-family: $font-stack;
  }
}

.pin {
  cursor: pointer;
  cursor: hand;
}

.patient-info-blue88 {
  width: 160px;
  height: 40px;
  border: 1px solid;
  border-radius: 4px;
  color: white;
  background-color: #3DA5D9;
  border-color: #3DA5D9;
  position: relative;
  right: 6px;
  bottom: 60px;
  cursor: pointer;
  float: right;
  cursor: hand;
}

.itemPin {
  -webkit-transition: top 1s ease-out, opacity 1s;
    -moz-transition: top 1s ease-out, opacity 1s;
}

我添加了带有时间戳的位置字段来控制音符位置,还请注意 CSS 类 用于 ng-move,ng-active 等。您可以按顺序修改它让它更花哨

CSS:

.ng-enter {
  -webkit-transition: s;
  transition: 1s;
  margin-top: 100%;
}

.ng-enter-active {
  margin-top: 0;
}

.ng-leave {
  -webkit-transition: 1s;
  transition: 1s;
  margin-top: 0;
}

.ng-leave-active {
  margin-top: 100%;
}

.ng-move {
  -webkit-transition: 1s;
  transition: 1s;
  background: gold;
}

.ng-move-active {
  background: #fff;
} 

这是工作 fiddle:

Fiddle