提交 9fdec58e 编写于 作者: DCloud_JSON's avatar DCloud_JSON

更新 示例项目 pull-zoom-image 改用自定义下拉刷新实现

上级 36fdc098
<template> <template>
<view @click="back" class="nav-back"> <view @click="back" class="nav-back">
<image class="back-img" src="/static/template/scroll-fold-nav/back.png" mode="widthFix"></image> <image class="back-img" src="/static/template/scroll-fold-nav/back.png" mode="widthFix"></image>
</view> </view>
<view style="flex:1" @touchstart="touchstart($event as TouchEvent)" @touchmove="touchmove($event as TouchEvent)" @touchend="touchend" @touchcancel="touchend"> <scroll-view :scroll-y="true" style="flex:1;" :refresher-enabled="true"
<image class="head-img" ref="head-img" src="../../../static/template/pull-zoom-image/head-img.jpg" mode="scaleToFill"></image> :refresher-triggered="refresherTriggered" refresher-default-style="none" @refresherpulling="onRefresherpulling"
<view class="body" ref="body"> @refresherrefresh="onRefresherrefresh" :refresher-threshold="300">
<view class="user-info">
<image class="user-avatar" src="../../../static/test-image/logo.png" mode="widthFix"></image> <view class="head-img-box">
<view class="font-box"> <image class="head-img-2" ref="head-img-2" src="../../../static/template/pull-zoom-image/head-img.jpg" mode="scaleToFill"></image>
<text class="username">uni-app-x</text> </view>
<text class="slogan">一次开发,多端覆盖</text> <view class="body">
</view> <view class="user-info">
</view> <image class="user-avatar" src="../../../static/test-image/logo.png" mode="widthFix"></image>
<view class="content"> <view class="font-box">
<view class="content-item"> <text class="username">uni-app-x</text>
<text class="text"> <text class="slogan">一次开发,多端覆盖</text>
1. 当前示例监听了整个页面的touchstart、touchmove、touchend事件 ,实现监听拖动事件。 </view>
</text> </view>
</view> <view class="list-item" v-for="(item,index) in 30" :key="index" :class="{'last-list-item':index == 29}">
<view class="content-item"> <view class="item-content">
<text class="text"> <text class="item-content-text" style="padding-left: 4px;">{{item}}. 占位</text>
2. 在拖动事件,使用 ref 直接获取 ref="body" 元素的节点,通过节点的 setProperty 方法来修改 transform的translateY 的值(根据在Y轴方向拖动的距离),从而达到页面跟随手指上下拖动的效果。 </view>
</text> </view>
</view> </view>
<view class="content-item">
<text class="text"> <view slot="refresher">
3. 在拖动事件,使用 ref 直接获取 ref="head-img" 元素的节点,通过节点的 setProperty 方法来修改 transform的scale 的值(根据在Y轴方向拖动的距离),从而达到手指上下拖动时图片缩放的效果。 <view class="head-img-box">
</text> <image class="head-img-1" ref="head-img-1" src="../../../static/template/pull-zoom-image/head-img.jpg" mode="scaleToFill"></image>
</view> </view>
<view class="content-item"> </view>
<text class="text"> </scroll-view>
4. 在拖动完成事件,通过帧动画,设置上述两个元素回到原来的位置。
</text>
</view>
<view class="content-item">
<text class="text">
5. 请向上\向下拖动页面观察效果。
</text>
</view>
<!-- <view class="content-item" v-for="(item,index) in 15" :key="index">
<text class="text" style="padding-left: 4px;">{{item + 5}}. 占位</text>
</view> -->
</view>
</view>
</view>
</template> </template>
<script> <script>
let sY : number = 0,
dY : number = 0,
maxScrollTop:number = 0,
moveIng:boolean = false,
startMoveTime:number = 0;
export default { export default {
data() { data() {
return { return {
$nodeMap: new Map<string, INode>(), $INodeMap: new Map<string, INode>(),
y: 0 as number,
scrollTop:0 as number refresherTriggered: false,
} }
},
onReady() {
uni.getSystemInfo({
success: (e) => {
maxScrollTop = 683 - e.screenHeight
}
})
}, },
methods: { methods: {
doMove() { onRefresherpulling(e : RefresherEvent) {
// console.log('doMove',this.y); // console.log('onRefresherpulling',e.detail.dy)
if(this.y > 0){ let pullingDistance:number = e.detail.dy
this.setINodeStyle("head-img", 'transform', `scale(${(this.y > 0 ? this.y : 0) / 200 + 1})`) this.setINodeStyle("head-img-1", 'transform', `scale(${pullingDistance / 200 + 1})`)
}else{ this.setINodeStyle("head-img-2", 'transform', `scale(${pullingDistance / 200 + 1})`)
this.setINodeStyle("head-img", 'transform', `translateY(${this.y})`)
}
this.setINodeStyle("body", 'transform', `translateY(${this.y})`)
},
touchstart(e : TouchEvent) {
sY = e.touches[0].screenY;
//计时
startMoveTime = 0
}, },
touchmove(e : TouchEvent) { onRefresherrefresh() {
this.y += e.touches[0].screenY - sY; this.refresherTriggered = true
dY = e.touches[0].screenY - sY //拖动结束
sY = e.touches[0].screenY; setTimeout(() => {
// 限制滚动到底后上拉 this.refresherTriggered = false
if(this.y < maxScrollTop*-1){ }, 0)
this.y = maxScrollTop*-1
}
this.doMove()
//计时
if(startMoveTime === 0){
startMoveTime = Date.now()
}
}, },
touchend() { getINodeByRefName(refName : string) : INode {
// console.log('touchend') let iNode : INode | null = this.$INodeMap.get(refName)
if(moveIng){ if (iNode == null) {
return iNode = this.$refs.get(refName) as INode;
} this.$INodeMap.set(refName, iNode)
moveIng = true
function moveTo(y : number, callback : () => void, speed : number = 10,acceleration : number = 0.2) {
let interval : number = 0
let _acceleration : number = 1
interval = setInterval(() => {
// 加速度
_acceleration += acceleration
const dy = y - this.y
if (Math.abs(dy) < 3) {
this.y = y
} else {
this.y += dy / speed * _acceleration
}
this.doMove()
if (this.y == y || this.y == maxScrollTop*-1 || this.y == 0) {
clearInterval(interval)
callback()
}
}, 16)
}
// console.log('dY',dY);
// console.log('this.y',this.y);
if(this.y < 0){
let speed:number = dY/(Date.now() - startMoveTime) * 1000
let inertia = speed * 3
if( Math.abs(inertia) < 100 ){
inertia = inertia > 0 ? 100 : -100;
}
let endY = this.y + inertia
// 滚动边界限制
if(endY < maxScrollTop*-1){
endY = maxScrollTop*-1
}
if(endY > 0){
endY = 0
}
// console.log('endY',endY);
moveTo(endY, () => {
moveIng = false
},10,0.1)
}else{
moveTo(0, () => {
moveIng = false
})
} }
return iNode
}, },
// 工具方法,用于快速设置 INode 的 style // 工具方法,用于快速设置 INode 的 style
setINodeStyle(refName : string, propertyName : string, propertyStyle : any) : void { setINodeStyle(refName : string, propertyName : string, propertyStyle : any) : void {
let node : INode | null = this.$nodeMap.get(refName) let iNode = this.getINodeByRefName(refName)
if (node == null) { iNode?.style?.setProperty(propertyName, propertyStyle);
node = this.$refs.get(refName) as INode;
this.$nodeMap.set(refName, node)
} else {
// console.log('直接拿');
}
node?.style?.setProperty(propertyName, propertyStyle);
}, },
back() { back() {
uni.navigateBack({ uni.navigateBack({
...@@ -178,16 +86,25 @@ ...@@ -178,16 +86,25 @@
</script> </script>
<style> <style>
.head-img { .head-img-box {
height: 350px; position: relative;
/* width: 1000rpx; */ height: 300px;
margin-left: -125rpx; }
margin-top: -50px; .head-img-1,.head-img-2{
background-color: #aab8d9; position: absolute;
left: -125rpx;
width: 1000rpx;
height: 600px;
}
.head-img-1 {
top: 0;
}
.head-img-2 {
bottom: 0;
} }
.body { .body {
margin-top: -200px; margin-top: -200px;
width: 750rpx; width: 750rpx;
} }
...@@ -222,18 +139,26 @@ ...@@ -222,18 +139,26 @@
.content { .content {
background-color: #FFF; background-color: #FFF;
border-radius: 10px; border-radius: 10px;
padding: 15px; padding: 15px;
}
.list-item {
background-color: #FFF;
padding-top: 15px;
}
.last-list-item{
padding-bottom: 15px;
} }
.content-item { .item-content {
padding: 5px;
margin-bottom: 16px;
background-color: #fff; background-color: #fff;
margin: 0 5px;
padding: 10px;
border-radius: 5px; border-radius: 5px;
border: 1px solid rgba(220, 220, 220, 0.5); border: 1px solid rgba(220, 220, 220, 0.3);
} }
.text { .item-content-text {
font-size: 14px; font-size: 14px;
color: #666; color: #666;
line-height: 20px; line-height: 20px;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册