pull-zoom-image.uvue 4.6 KB
Newer Older
1 2
<template>
  <view @click="back" class="nav-back">
3
    <image class="back-img" src="/static/template/pull-zoom-image/back.png" mode="widthFix"></image>
4 5
  </view>
  <scroll-view :scroll-y="true" style="flex:1;" :refresher-enabled="true"
6 7 8 9 10 11
    refresher-default-style="none" @refresherpulling="onRefresherpulling"
    :refresher-threshold="300" :refresher-max-drag-distance="299"
    @scroll="onScroll" :rebound="false"
    >
    <view class="head-img-box-2" ref="head-img-box-2">
      <image class="img" ref="head-img-2" src="../../../static/template/pull-zoom-image/head-img.jpg" mode="scaleToFill"></image>
12
    </view>
13 14 15 16 17
    <view class="user-info" ref="user-info">
      <image class="user-avatar" src="../../../static/test-image/logo.png" mode="widthFix"></image>
      <view class="font-box">
        <text class="username">uni-app-x</text>
        <text class="slogan">一次开发,多端覆盖</text>
18
      </view>
19 20 21 22 23 24
    </view>
    <view class="list-box">
      <view class="item" v-for="(item,index) in 30" :key="index">
        <text class="text">{{item}}. 占位</text>
      </view>
    </view>
25 26

    <view slot="refresher">
27 28
      <view class="head-img-box-1">
        <image class="img" ref="head-img-1" src="../../../static/template/pull-zoom-image/head-img.jpg" mode="scaleToFill"></image>
29
      </view>
30 31
    </view>

32
  </scroll-view>
33 34
</template>

35
<script>
36 37 38
  export default {
    data() {
      return {
39
        $INodeMap: new Map<string, INode>()
40 41
      }
    },
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
    methods: {
      onScroll(e : ScrollEvent) {
        const {scrollTop} = e.detail
        let y : number = scrollTop - 110
        let s : number = (100 - scrollTop/3)/100
        if(y < 0){
          y = 0
        }
        if(s < 0.7){
          s = 0.7
        }
        let x : number = (1 - s) * -100
        this.setINodeStyle("user-info", "transform", `translate(${x},${y + (s-1)* -50}px) scale(${s})`)
        this.setINodeStyle("head-img-box-2", "transform", `translateY(${y}px)`)
      },
57 58
      onRefresherpulling(e : RefresherEvent) {
        // console.log('onRefresherpulling',e.detail.dy)
59
        let pullingDistance : number = e.detail.dy
60 61
        this.setINodeStyle("head-img-1", 'transform', `scale(${pullingDistance / 200 + 1})`)
        this.setINodeStyle("head-img-2", 'transform', `scale(${pullingDistance / 200 + 1})`)
62 63 64
      },
      // 工具方法,用于快速设置 INode 的 style
      setINodeStyle(refName : string, propertyName : string, propertyStyle : any) : void {
65 66 67 68 69
        let iNode : INode | null = this.$INodeMap.get(refName)
        if (iNode == null) {
          iNode = this.$refs.get(refName) as INode;
          this.$INodeMap.set(refName, iNode)
        }
70
        iNode.style.setProperty(propertyName, propertyStyle);
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
      },
      back() {
        uni.navigateBack({
          success(result) {
            console.log('navigateBack success', result.errMsg)
          },
          fail(error) {
            console.log('navigateBack fail', error.errMsg)
          },
          complete(result) {
            console.log('navigateBack complete', result.errMsg)
          }
        })
      }
    }
  }
</script>

<style>
90 91 92
  .head-img-box-1,
  .head-img-box-2
  {
93 94 95
    position: relative;
    height: 300px;
  }
96 97 98 99

  .head-img-box-1 .img,
  .head-img-box-2 .img
  {
100 101 102 103 104
    position: absolute;
    left: -125rpx;
    width: 1000rpx;
    height: 600px;
  }
105 106

  .head-img-box-1 .img {
107 108
    top: 0;
  }
109 110 111 112 113 114 115 116

  .head-img-box-2 .img {
    bottom: -100;
  }

  .head-img-box-2 {
    z-index: 9;
    height: 200px;
117 118
  }

119 120
  .user-info{
    margin-top: -110px;
121
    width: 750rpx;
122
    padding: 15px;
123 124
    flex-direction: row;
    z-index: 10;
125 126
  }

127
  .user-info .user-avatar {
128 129 130 131 132 133
    width: 150rpx;
    height: 150rpx;
    border-radius: 100px;
    border: 3px solid #FFF;
  }

134
  .user-info .font-box {
135 136 137 138 139
    flex-direction: column;
    justify-content: space-around;
    padding: 10px;
  }

140
  .user-info .username {
141 142 143 144
    font-size: 26px;
    color: #FFF;
  }

145
  .user-info .slogan {
146 147 148 149
    font-size: 16px;
    color: #FFF;
  }

150 151 152 153

  .list-box {
    background-color: #FFF;
    z-index: 1;
154
  }
155

156
  .list-box .item {
157
    padding: 10px;
158
    margin: 5px;
159
    border-radius: 5px;
160 161
    border: 1px solid rgba(220, 220, 220, 0.3);
  }
162

163
  .list-box .text {
164
    font-size: 14px;
165 166 167 168 169 170
    color: #666;
    line-height: 20px;
  }

  .nav-back {
    position: absolute;
171 172
    top: 30px;
    left: 10px;
173 174 175 176 177 178 179 180 181 182 183 184 185
    border-radius: 100px;
    width: 28px;
    height: 28px;
    justify-content: center;
    align-items: center;
    z-index: 10;
  }

  .nav-back .back-img {
    width: 18px;
    height: 18px;
  }
</style>