547 lines
15 KiB
JavaScript
547 lines
15 KiB
JavaScript
// miniprogram_npm/coolui-scroller/second-floor/index.js
|
||
Component({
|
||
options: {
|
||
multipleSlots: true,
|
||
addGlobalClass: true,
|
||
},
|
||
externalClasses: ['second-floor-class'],
|
||
relations: {
|
||
'../second-floor-refresh/index': {
|
||
type: 'child',
|
||
linked(target) {
|
||
// console.log(target);
|
||
},
|
||
},
|
||
'../nav-bar/index': {
|
||
type: 'child',
|
||
linked(target) {
|
||
// console.log(target.data)
|
||
// console.log(target.data.statusBarHeight)
|
||
// this.setData({
|
||
// navBar: target,
|
||
// })
|
||
},
|
||
},
|
||
},
|
||
properties: {
|
||
threshold: {
|
||
type: Number,
|
||
value: 0,
|
||
},
|
||
offset: {
|
||
type: Number,
|
||
value: 0,
|
||
},
|
||
center: {
|
||
type: Boolean,
|
||
value: false,
|
||
observer: function (newVal) {
|
||
this.init()
|
||
},
|
||
},
|
||
bottom: {
|
||
type: Boolean,
|
||
value: true,
|
||
observer: function (newVal) {
|
||
this.init()
|
||
},
|
||
},
|
||
top: {
|
||
type: Boolean,
|
||
value: false,
|
||
observer: function (newVal) {
|
||
this.init()
|
||
},
|
||
},
|
||
scale: {
|
||
type: Boolean,
|
||
value: false,
|
||
observer: function (newVal) {
|
||
this.init()
|
||
},
|
||
},
|
||
tip: {
|
||
type: Object,
|
||
value: {
|
||
show: false,
|
||
height: 100,
|
||
times: 1,
|
||
duration: 2000,
|
||
},
|
||
},
|
||
},
|
||
data: {
|
||
scroll_height: 0,
|
||
touchy: 0,
|
||
isLoading: false,
|
||
isFloorShow: false,
|
||
wapperAnimationData: {},
|
||
innerAnimationData: {},
|
||
statusBarHeight: 0,
|
||
navBar: null,
|
||
},
|
||
lifetimes: {
|
||
attached: function () {
|
||
// 在组件实例进入页面节点树时执行
|
||
// this.init()
|
||
let info = wx.getSystemInfoSync()
|
||
console.log(info)
|
||
this.setData({
|
||
scroll_height: info.windowHeight,
|
||
})
|
||
},
|
||
},
|
||
ready() {
|
||
this.init(() => {
|
||
this.navNodes = this.getRelationNodes('../nav-bar/index')
|
||
this.navNode = this.navNodes[0] ? this.navNodes[0] : null
|
||
this.setData({
|
||
statusBarHeight: this.navNode.data.statusBarHeight,
|
||
})
|
||
})
|
||
},
|
||
methods: {
|
||
debounce(fn, wait) {
|
||
const that = this
|
||
that.setData({
|
||
timeout: null,
|
||
})
|
||
return function () {
|
||
if (that.data.timeout !== null) {
|
||
clearTimeout(that.data.timeout)
|
||
}
|
||
const timeout = setTimeout(() => {
|
||
fn()
|
||
}, wait)
|
||
that.setData({
|
||
timeout,
|
||
})
|
||
}
|
||
},
|
||
/**
|
||
* @name: 初始化
|
||
* @description: 根据设置初始化动画,初始化参数,初始化子组件
|
||
* @return {*}
|
||
*/
|
||
init(callback = null) {
|
||
let info = wx.getSystemInfoSync()
|
||
this.refreshNodes = this.getRelationNodes('../second-floor-refresh/index')
|
||
this.refreshNode = this.refreshNodes[0] ? this.refreshNodes[0] : null
|
||
this.refreshNode.setData({
|
||
scroll_height: this.data.scroll_height,
|
||
})
|
||
this.refreshNode.setDown()
|
||
let animation = this.setAnimation(
|
||
-this.data.scroll_height + this.data.offset,
|
||
0
|
||
)
|
||
console.log(this.data.offset)
|
||
let animationInner = null
|
||
let scaleXy = this.data.scale ? 0.1 : 1
|
||
if (this.data.top) {
|
||
animationInner = this.setAnimation(
|
||
this.data.scroll_height,
|
||
0,
|
||
scaleXy,
|
||
scaleXy
|
||
)
|
||
}
|
||
if (this.data.center) {
|
||
animationInner = this.setAnimation(
|
||
this.data.scroll_height / 2,
|
||
0,
|
||
scaleXy,
|
||
scaleXy
|
||
)
|
||
}
|
||
if (this.data.bottom) {
|
||
animationInner = this.setAnimation(0, 0, scaleXy, scaleXy)
|
||
}
|
||
this.setData(
|
||
{
|
||
wapperAnimationData: animation.export(),
|
||
innerAnimationData: animationInner ? animationInner.export() : {},
|
||
threshold: this.data.threshold,
|
||
},
|
||
() => {
|
||
this.wapper = this.selectComponent('.second-floor-wapper')
|
||
if (callback) {
|
||
callback()
|
||
}
|
||
if (this.data.tip.show) {
|
||
this.tipShow()
|
||
}
|
||
}
|
||
)
|
||
},
|
||
tipShow(
|
||
duration = this.data.tip.duration,
|
||
wait = this.data.tip.duration,
|
||
times = this.data.tip.times
|
||
) {
|
||
const animation = wx.createAnimation()
|
||
let offset = -this.data.scroll_height + this.data.offset
|
||
animation.translateY(offset).step({
|
||
duration,
|
||
timingFunction: 'ease-in',
|
||
})
|
||
this.setData(
|
||
{
|
||
wapperAnimationData: animation.export(),
|
||
threshold: 0,
|
||
},
|
||
() => {
|
||
this.refreshNode.setText(this.data.scroll_height / 2)
|
||
if (this.data.tip.show) {
|
||
setTimeout(() => {
|
||
animation
|
||
.translateY(-this.data.scroll_height + this.data.tip.height)
|
||
.step({
|
||
duration,
|
||
timingFunction: 'ease-out',
|
||
})
|
||
this.setData(
|
||
{
|
||
wapperAnimationData: animation.export(),
|
||
threshold: this.data.tip.height,
|
||
},
|
||
() => {
|
||
this.refreshNode.setText(this.data.scroll_height / 2)
|
||
if (times > 1) {
|
||
setTimeout(() => {
|
||
this.tipShow(duration, wait, times - 1)
|
||
}, wait)
|
||
} else {
|
||
setTimeout(() => {
|
||
this.setData(
|
||
{
|
||
tip: {
|
||
show: false,
|
||
height: this.data.tip.height,
|
||
times: this.data.tip.times,
|
||
},
|
||
},
|
||
() => {
|
||
this.tipShow(duration, wait, times - 1)
|
||
}
|
||
)
|
||
}, wait)
|
||
}
|
||
}
|
||
)
|
||
}, duration)
|
||
}
|
||
}
|
||
)
|
||
},
|
||
/**
|
||
* @name: 触摸拖拽开始
|
||
* @description: 记录初始触摸位置
|
||
* @param {*} e
|
||
* @return {*}
|
||
*/
|
||
touchStart(e) {
|
||
console.log(this.data.tip.show)
|
||
// 正在刷新时不操作触摸
|
||
if (this.data.tip.show) {
|
||
return false
|
||
}
|
||
if (this.data.isLoading) {
|
||
return false
|
||
}
|
||
this.setData({
|
||
touchy: e.changedTouches[0].clientY,
|
||
})
|
||
},
|
||
/**
|
||
* @name: 拖动时执行
|
||
* @description: 修改页面动画,传递触摸动态参数给refresh组件
|
||
* @return {*}
|
||
*/
|
||
touchMove(e) {
|
||
if (this.data.tip.show) {
|
||
return false
|
||
}
|
||
// 正在刷新时不进行操作, 二楼已加载是不进行操作
|
||
if (!this.data.isFloorShow && !this.data.isLoading) {
|
||
const distance = Math.round(
|
||
e.changedTouches[0].clientY - this.data.touchy
|
||
)
|
||
let scaleXy = 1
|
||
if (this.data.scale) {
|
||
scaleXy = 0.1 + distance / 200
|
||
scaleXy = scaleXy >= 1 ? 1 : scaleXy
|
||
}
|
||
|
||
if (distance > 0) {
|
||
let animation = this.setAnimation(
|
||
-this.data.scroll_height + distance + this.data.offset,
|
||
0
|
||
)
|
||
|
||
let animationInner = null
|
||
|
||
if (this.data.top) {
|
||
animationInner = this.setAnimation(
|
||
this.data.scroll_height - distance,
|
||
0,
|
||
scaleXy,
|
||
scaleXy
|
||
)
|
||
}
|
||
|
||
if (this.data.bottom) {
|
||
animationInner = this.setAnimation(0, 0, scaleXy, scaleXy)
|
||
}
|
||
|
||
if (this.data.center) {
|
||
animationInner = this.setAnimation(
|
||
(this.data.scroll_height - distance) / 2,
|
||
0,
|
||
scaleXy,
|
||
scaleXy
|
||
)
|
||
}
|
||
// console.log(animationInner);
|
||
this.setData({
|
||
wapperAnimationData: animation.export(),
|
||
innerAnimationData: animationInner ? animationInner.export() : null,
|
||
threshold: distance,
|
||
})
|
||
this.refreshNode.setText(distance)
|
||
}
|
||
}
|
||
},
|
||
/**
|
||
* @name: 松手后执行
|
||
* @description: 松手时如果拖拽的距离大于屏幕三分之一,直接执行拉到二楼动画,如果大于六分之一小于三分之一则回到六分之一并开启刷新状态,如果小于六分之一直接回弹
|
||
* @return {*}
|
||
*/
|
||
touchEnd() {
|
||
if (this.data.tip.show) {
|
||
return false
|
||
}
|
||
// 正在刷新时不进行操作, 二楼已加载是不进行操作,只点屏幕不拖拽时不进行操作
|
||
if (
|
||
!this.data.isFloorShow &&
|
||
this.data.threshold > 0 &&
|
||
!this.data.isLoading
|
||
) {
|
||
// 大于3分之1 直接拉到二楼
|
||
if (this.data.threshold > this.data.scroll_height / 3) {
|
||
const animation = this.setAnimation(0, 400)
|
||
let animationInner = null
|
||
if (this.data.top) {
|
||
animationInner = this.setAnimation(0, 400, 1, 1)
|
||
}
|
||
if (this.data.bottom) {
|
||
animationInner = this.setAnimation(0, 0, 1, 1)
|
||
}
|
||
|
||
if (this.data.center) {
|
||
animationInner = this.setAnimation(0, 400, 1, 1)
|
||
}
|
||
this.setData(
|
||
{
|
||
wapperAnimationData: animation.export(),
|
||
innerAnimationData: animationInner ? animationInner.export() : {},
|
||
},
|
||
() => {
|
||
setTimeout(() => {
|
||
this.refreshNode.setSecondShow(true)
|
||
this.setData({
|
||
isFloorShow: true,
|
||
})
|
||
this.triggerEvent('secondShow')
|
||
}, 400)
|
||
}
|
||
)
|
||
} else {
|
||
if (this.data.threshold > this.data.scroll_height / 6) {
|
||
// 大于6分之一,小于3分之一,回到 6分之一停顿开始刷新
|
||
const animation = this.setAnimation(
|
||
-this.data.scroll_height + this.data.scroll_height / 6,
|
||
400
|
||
)
|
||
let animationInner = null
|
||
if (this.data.top) {
|
||
animationInner = this.setAnimation(
|
||
this.data.scroll_height - this.data.scroll_height / 6,
|
||
400
|
||
)
|
||
}
|
||
if (this.data.bottom) {
|
||
animationInner = this.setAnimation(0, 0)
|
||
}
|
||
if (this.data.center) {
|
||
animationInner = this.setAnimation(
|
||
(this.data.scroll_height - this.data.scroll_height / 6) / 2,
|
||
400
|
||
)
|
||
}
|
||
this.setData(
|
||
{
|
||
wapperAnimationData: animation.export(),
|
||
innerAnimationData: animationInner
|
||
? animationInner.export()
|
||
: {},
|
||
},
|
||
() => {
|
||
this.triggerEvent('refresh')
|
||
this.setData({
|
||
isLoading: true,
|
||
})
|
||
this.refreshNode.setLoading(true)
|
||
}
|
||
)
|
||
} else {
|
||
// 小于6分之一 直接回顶部
|
||
this.back(false)
|
||
}
|
||
}
|
||
}
|
||
},
|
||
/**
|
||
* @name: 回弹及二楼关闭
|
||
* @description: 拖动小于6分之一直接回顶部或外部自定义调用关闭二楼
|
||
* @return {*}
|
||
*/
|
||
back(callback = true) {
|
||
return new Promise((resolve) => {
|
||
const animation = this.setAnimation(
|
||
-this.data.scroll_height + this.data.offset,
|
||
800
|
||
)
|
||
let animationInner = null
|
||
|
||
if (this.data.top) {
|
||
animationInner = this.setAnimation(
|
||
this.data.scroll_height,
|
||
800,
|
||
1,
|
||
this.data.scale ? 0 : 1
|
||
)
|
||
}
|
||
if (this.data.bottom) {
|
||
animationInner = this.setAnimation(0, 0, 1, this.data.scale ? 0 : 1)
|
||
}
|
||
if (this.data.center) {
|
||
animationInner = this.setAnimation(
|
||
this.data.scroll_height / 2,
|
||
800,
|
||
1,
|
||
this.data.scale ? 0 : 1
|
||
)
|
||
}
|
||
this.setData(
|
||
{
|
||
wapperAnimationData: animation.export(),
|
||
innerAnimationData: animationInner ? animationInner.export() : {},
|
||
},
|
||
() => {
|
||
setTimeout(() => {
|
||
// this.refreshNode.setShow(false)
|
||
this.refreshNode.setDown()
|
||
this.setData(
|
||
{
|
||
isFloorShow: false,
|
||
threshold: 0,
|
||
},
|
||
() => {
|
||
if (callback) {
|
||
this.triggerEvent('secondBack')
|
||
resolve()
|
||
}
|
||
}
|
||
)
|
||
}, 800)
|
||
}
|
||
)
|
||
})
|
||
},
|
||
/**
|
||
* @name: 刷新后的回弹
|
||
* @description: 刷新之后回弹方法,再请求完数据之后执行
|
||
* @return {*}
|
||
*/
|
||
settriggered() {
|
||
return new Promise((resolve) => {
|
||
const animation = this.setAnimation(
|
||
-this.data.scroll_height + this.data.offset,
|
||
800
|
||
)
|
||
let animationInner = null
|
||
|
||
if (this.data.top) {
|
||
animationInner = this.setAnimation(
|
||
this.data.scroll_height,
|
||
800,
|
||
1,
|
||
this.data.scale ? 0 : 1
|
||
)
|
||
}
|
||
if (this.data.bottom) {
|
||
animationInner = this.setAnimation(0, 0, 1, this.data.scale ? 0 : 1)
|
||
}
|
||
if (this.data.center) {
|
||
animationInner = this.setAnimation(
|
||
this.data.scroll_height / 2,
|
||
800,
|
||
1,
|
||
this.data.scale ? 0 : 1
|
||
)
|
||
}
|
||
this.setData(
|
||
{
|
||
wapperAnimationData: animation.export(),
|
||
innerAnimationData: animationInner ? animationInner.export() : {},
|
||
isLoading: false,
|
||
},
|
||
() => {
|
||
setTimeout(() => {
|
||
this.refreshNode.setDown()
|
||
this.setData(
|
||
{
|
||
threshold: 0,
|
||
},
|
||
() => {
|
||
resolve()
|
||
}
|
||
)
|
||
}, 400)
|
||
}
|
||
)
|
||
})
|
||
},
|
||
setAnimation(
|
||
y,
|
||
duration = 400,
|
||
scale = 1,
|
||
opacity = 1,
|
||
timingFunction = 'ease-out'
|
||
) {
|
||
let transformOrigin = '50% 50% 0'
|
||
if (this.data.top) {
|
||
transformOrigin = '50% 0 0'
|
||
}
|
||
if (this.data.bottom) {
|
||
transformOrigin = '50% 100% 0'
|
||
}
|
||
if (this.data.center) {
|
||
transformOrigin = '50% 50% 0'
|
||
}
|
||
const animation = wx.createAnimation({
|
||
delay: 0,
|
||
duration: duration,
|
||
timingFunction: timingFunction,
|
||
transformOrigin: transformOrigin,
|
||
})
|
||
animation.translateY(y).scale(scale, scale).opacity(opacity)
|
||
|
||
animation.step()
|
||
|
||
return animation
|
||
},
|
||
},
|
||
})
|