drop-card.uvue 6.5 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 17
    sY : number = 0,
    screenWidth : number = 1,
18 19
    nodesMap = new Map<string, INode[]>();
    
DCloud_JSON's avatar
DCloud_JSON 已提交
20 21 22
  export default {
    data() {
      return {
23 24
        x: 0 as number,
        y: 0 as number,
25 26 27 28 29 30
        cardList: [
          '/static/template/drop-card/1.jpg',
          '/static/template/drop-card/2.jpg',
          '/static/template/drop-card/3.jpg'
        ] as string[],
        NodesMap: new Map<string, INode[]>(),
31 32
        // 页码
        currentIndex:0 as number
DCloud_JSON's avatar
DCloud_JSON 已提交
33 34
      }
    },
35
    onReady() {
DCloud_JSON's avatar
DCloud_JSON 已提交
36 37
      uni.getSystemInfo({
        success: (e) => {
38 39 40 41
          // console.log('e',e);
          screenWidth = e.screenWidth;
          let height = e.screenHeight - 200 + 'px'
          for (var i = 0; i < 3; i++) {
42 43
            this.setINodeStyle('card',i,'height', height);
            this.setINodeStyle('card-img',i,'height', height);
44
          }
DCloud_JSON's avatar
DCloud_JSON 已提交
45
        }
46 47 48
      })
      this.initCardList()
    },
49 50 51 52 53 54 55 56 57
    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
58 59 60
      },
      topCardIndex():number{
        return 2 - Math.abs(this.currentIndex)%3
61
      }
DCloud_JSON's avatar
DCloud_JSON 已提交
62
    },
63
    methods: {
64 65
      // 工具方法,用于快速设置 INode 的 style
      setINodeStyle(refName:string,index:number,propertyName:string,propertyStyle:any):void{
66 67 68 69 70 71 72 73
        let nodes:INode[]|null = nodesMap.get(refName)
        if(nodes == null){
          nodes = this.$refs.get(refName) as INode[]
          nodesMap.set(refName,nodes)
        }else{
          // console.log('直接拿');
        }
        (nodes)[index].style.setProperty(propertyName,propertyStyle);
74 75 76 77 78 79 80 81 82 83
      },
      // 设置卡片样式(层级,大小,上边距)
      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 已提交
84
      },
85
      moveCard() {
86
        for (var i = 0; i < 3; i++) {
87 88 89 90 91 92 93 94 95 96
          // 设置置顶卡片样式
          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');
          }
97
        }
98 99
      },
      touchstart(e : TouchEvent,index:number) {
100
        if(index != this.topCardIndex){
101 102
          return 
        }
DCloud_JSON's avatar
DCloud_JSON 已提交
103
        sX = e.touches[0].screenX;
104 105 106
        sY = e.touches[0].screenY;
        this.x = 0
        this.y = 0
DCloud_JSON's avatar
DCloud_JSON 已提交
107
      },
108
      touchmove(e : TouchEvent,index:number) {
109
        if(index != this.topCardIndex){
110 111
          return 
        }
DCloud_JSON's avatar
DCloud_JSON 已提交
112 113 114
        this.x += e.touches[0].screenX - sX;
        this.y += e.touches[0].screenY - sY;
        sX = e.touches[0].screenX;
115
        sY = e.touches[0].screenY;
116
        this.moveCard()
DCloud_JSON's avatar
DCloud_JSON 已提交
117
      },
118 119
      touchend() {
        // console.log('touchend');
120

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

132
        // 设置动画时间
133 134 135 136 137 138 139 140 141 142 143
        let time = 60;
        let topCardIndex = this.topCardIndex
        this.setINodeStyle('card',topCardIndex,'transitionProperty','transform');
        this.setINodeStyle('card',topCardIndex,'transitionDuration',time);
        // this.setINodeStyle('card',topCardIndex,'transitionOrigin','bottom center');
        this.moveCard()
         // 移动结束
        setTimeout(()=>{
          // 关闭动画
          this.setINodeStyle('card',topCardIndex,'transitionProperty','scale');
          if(this.x != 0.0){
144
            setTimeout(()=>{
145 146 147 148 149 150
              this.x = 0
              this.y = 0
              this.moveCard()
              this.setINodeStyle('card',topCardIndex,'transitionProperty','marginTop,scale');
              this.currentIndex ++
              this.initCardList()
151
            },100)
152 153
          }
        },time)
154
        
DCloud_JSON's avatar
DCloud_JSON 已提交
155 156 157 158 159 160 161 162 163 164 165
      }
    }
  }
</script>
<style>
  .root {
    flex: 1;
    position: relative;
  }

  .card {
166
    width: 700rpx;
DCloud_JSON's avatar
DCloud_JSON 已提交
167 168 169
    height: 750rpx;
    position: absolute;
    margin: 0 25rpx;
170
    margin-top: 50px;
DCloud_JSON's avatar
DCloud_JSON 已提交
171
    border-radius: 10px;
172 173
    color: #FFF;
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
174 175 176 177
    background-color: #FFF;
    /* transform-origin:bottom; */
    transition:margin-top 60ms;
    transition-timing-function: linear;
DCloud_JSON's avatar
DCloud_JSON 已提交
178 179
  }
  
180 181 182 183 184 185 186 187 188 189 190
  .card-img {
    border-radius: 10px;
  }

  .state {
    top: 20rpx;
    left: 20rpx;
    width: 650rpx;
    padding: 4px;
    position: absolute;
    flex-direction: row;
191 192 193
    justify-content: space-between;
  }
  
194 195 196 197 198 199 200 201 202
  .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;
203 204
  }
  
DCloud_JSON's avatar
DCloud_JSON 已提交
205
</style>