drop-card.uvue 7.0 KB
Newer Older
DCloud_JSON's avatar
DCloud_JSON 已提交
1
<template>
2 3 4 5
  <view class="root">
    <template v-for="(item,index) in cardList" :key="index">
      <view class="card" ref="card" @touchstart="touchstart($event as TouchEvent,index)" @touchmove="touchmove($event as TouchEvent,index)" @touchend="touchend" @touchcancel="touchend">
        <image class="card-img" ref="card-img" :src="item"></image>
6 7 8 9
        <view class="state">
          <image class="state-icon like" ref="state-icon-like" src="/static/template/drop-card/like.png" mode="widthFix"></image>
          <image class="state-icon dislike" ref="state-icon-dislike" src="/static/template/drop-card/dislike.png" mode="widthFix"></image>
        </view>
DCloud_JSON's avatar
DCloud_JSON 已提交
10
      </view>
11
    </template>
DCloud_JSON's avatar
DCloud_JSON 已提交
12 13 14 15
  </view>
</template>
<script lang="ts">
  let sX : number = 0,
16
    sY : number = 0,
17
    screenWidth : number = 1;
18
    
DCloud_JSON's avatar
DCloud_JSON 已提交
19 20 21
  export default {
    data() {
      return {
22 23
        x: 0 as number,
        y: 0 as number,
24 25 26 27 28
        cardList: [
          '/static/template/drop-card/1.jpg',
          '/static/template/drop-card/2.jpg',
          '/static/template/drop-card/3.jpg'
        ] as string[],
29
        // 页码
30 31
        currentIndex:0 as number,
        $nodesMap:new Map<string, INode[]>()
DCloud_JSON's avatar
DCloud_JSON 已提交
32 33
      }
    },
34
    onReady() {
DCloud_JSON's avatar
DCloud_JSON 已提交
35 36
      uni.getSystemInfo({
        success: (e) => {
37 38 39 40
          // console.log('e',e);
          screenWidth = e.screenWidth;
          let height = e.screenHeight - 200 + 'px'
          for (var i = 0; i < 3; i++) {
41 42
            this.setINodeStyle('card',i,'height', height);
            this.setINodeStyle('card-img',i,'height', height);
43
          }
DCloud_JSON's avatar
DCloud_JSON 已提交
44
        }
45 46 47
      })
      this.initCardList()
    },
48 49 50 51 52 53 54 55 56
    computed: {
      movePercent() : number {
        return Math.abs(this.x) / (screenWidth/2*3)
      },
      likeOpacity() : number {
        return this.x < 0 ? 0 : this.movePercent * 100
      },
      dislikeOpacity() : number {
        return this.x > 0 ? 0 : this.movePercent * 100
57 58 59
      },
      topCardIndex():number{
        return 2 - Math.abs(this.currentIndex)%3
60
      }
DCloud_JSON's avatar
DCloud_JSON 已提交
61
    },
62
    methods: {
63 64
      // 工具方法,用于快速设置 INode 的 style
      setINodeStyle(refName:string,index:number,propertyName:string,propertyStyle:any):void{
65
        let nodes:INode[]|null = this.$nodesMap.get(refName)
66 67
        if(nodes == null){
          nodes = this.$refs.get(refName) as INode[]
68
          this.$nodesMap.set(refName,nodes)
69 70 71 72
        }else{
          // console.log('直接拿');
        }
        (nodes)[index].style.setProperty(propertyName,propertyStyle);
73 74 75 76 77 78 79 80 81 82
      },
      // 设置卡片样式(层级,大小,上边距)
      initCardList(){
        for (var i = 0; i < 3; i++) {
          let endIndex = (i + this.currentIndex)%3
          this.setINodeStyle('card',i,'margin-top', 100 - 30*endIndex+'px');
          this.setINodeStyle('card',i,'transform', 'scale('+(0.9+0.05*endIndex)+')')
          // console.log(0.9+0.05*endIndex,50 - 20*endIndex+'px');
          this.setINodeStyle('card',i,'z-index', endIndex)
        }
DCloud_JSON's avatar
DCloud_JSON 已提交
83
      },
84
      moveCard() {
85
        for (var i = 0; i < 3; i++) {
86 87 88 89 90 91 92 93 94 95
          // 设置置顶卡片样式
          if(i === this.topCardIndex){
            this.setINodeStyle('card',this.topCardIndex,'transform', 'translateX('+this.x+'px) translateY('+this.y+'px) rotate('+this.x/-30+'deg) scale('+( 0.9+0.05*2 + movePercent/20 )+')')
            this.setINodeStyle('state-icon-like',this.topCardIndex,'opacity', x < 0 ? 0 : movePercent * 10)
            this.setINodeStyle('state-icon-dislike',this.topCardIndex,'opacity', x > 0 ? 0 : movePercent * 10)
          }else{
            let endIndex = (i + this.currentIndex)%3
            this.setINodeStyle('card',i,'transform', 'scale('+( 0.9+0.05*endIndex + movePercent*0.05 )+')')
            this.setINodeStyle('card',i,'margin-top', 100 - 30*endIndex - movePercent*30 +'px');
          }
96
        }
97 98
      },
      touchstart(e : TouchEvent,index:number) {
99
        if(index != this.topCardIndex){
100 101
          return 
        }
DCloud_JSON's avatar
DCloud_JSON 已提交
102
        sX = e.touches[0].screenX;
103 104 105
        sY = e.touches[0].screenY;
        this.x = 0
        this.y = 0
DCloud_JSON's avatar
DCloud_JSON 已提交
106
      },
107
      touchmove(e : TouchEvent,index:number) {
108
        if(index != this.topCardIndex){
109 110
          return 
        }
DCloud_JSON's avatar
DCloud_JSON 已提交
111 112 113
        this.x += e.touches[0].screenX - sX;
        this.y += e.touches[0].screenY - sY;
        sX = e.touches[0].screenX;
114
        sY = e.touches[0].screenY;
115
        this.moveCard()
DCloud_JSON's avatar
DCloud_JSON 已提交
116
      },
117 118
      touchend() {
        // console.log('touchend');
119

120 121 122 123 124 125 126 127
        // 设置释放之后飘走的方向 0回到坐标中心 1向右 2向左
        let k:number = 0;
        if (this.x > screenWidth / 6 ) {
          k = 1
        }else if(this.x < screenWidth * -1 / 6){
          k = -1
        }
        
128 129 130
        this.x = k * screenWidth * 1.5
        this.y = k * screenWidth * 0.5

131
        // 设置动画时间
132 133 134 135 136
        let transitionDuration = 300;
        let floatCardIndex = this.topCardIndex
        this.setINodeStyle('card',floatCardIndex,'transitionProperty','transform');
        this.setINodeStyle('card',floatCardIndex,'transitionDuration',transitionDuration);
        // this.setINodeStyle('card',floatCardIndex,'transitionOrigin','bottom center');
137 138 139
        this.moveCard()
         // 移动结束
        setTimeout(()=>{
140 141 142
          // 动画速度设置为0(即:关闭动画)
          this.setINodeStyle('card',floatCardIndex,'transitionDuration',0);
          
143
          if(this.x != 0.0){
144 145 146 147 148 149
              // 飘动的卡片挪回中心
              this.setINodeStyle('card',floatCardIndex,'transform', 'translate(0,0) rotate(0)')
              this.setINodeStyle('state-icon-like',floatCardIndex,'opacity', 0)
              this.setINodeStyle('state-icon-dislike',floatCardIndex,'opacity', 0)
              
              // 坐标归零
150 151
              this.x = 0
              this.y = 0
152 153 154 155 156
              
              // 动画改成marginTop,scale
              this.setINodeStyle('card',floatCardIndex,'transitionProperty','marginTop,scale');
              this.setINodeStyle('card',floatCardIndex,'transitionDuration',transitionDuration);
              // 切换卡片顺序
157
              this.currentIndex ++
158
              // 根据最新卡片顺序,设置层级大小样式
159 160
              this.initCardList()
          }
161
        },transitionDuration)
162
        
DCloud_JSON's avatar
DCloud_JSON 已提交
163 164 165 166 167 168 169 170 171 172 173
      }
    }
  }
</script>
<style>
  .root {
    flex: 1;
    position: relative;
  }

  .card {
174
    width: 700rpx;
DCloud_JSON's avatar
DCloud_JSON 已提交
175 176 177
    height: 750rpx;
    position: absolute;
    margin: 0 25rpx;
178
    margin-top: 50px;
DCloud_JSON's avatar
DCloud_JSON 已提交
179
    border-radius: 10px;
180 181
    color: #FFF;
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
182 183 184
    background-color: #FFF;
    /* transform-origin:bottom; */
    transition:margin-top 60ms;
185
    transition-timing-function: ease-in;
DCloud_JSON's avatar
DCloud_JSON 已提交
186 187
  }
  
188 189 190 191 192 193 194 195 196 197 198
  .card-img {
    border-radius: 10px;
  }

  .state {
    top: 20rpx;
    left: 20rpx;
    width: 650rpx;
    padding: 4px;
    position: absolute;
    flex-direction: row;
199 200 201
    justify-content: space-between;
  }
  
202 203 204 205 206 207 208 209 210
  .state-icon {
    width: 30px;
    height: 30px;
    border: 1px solid #FFF;
    background-color: #FFF;
    padding: 3px;
    border-radius: 100px;
    box-shadow: 0 0 1px #EBEBEB;
    opacity: 0;
211 212
  }
  
DCloud_JSON's avatar
DCloud_JSON 已提交
213
</style>