You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
4.6 KiB

// 文档:https://developers.weixin.qq.com/miniprogram/dev/framework/view/interactive-animation.html
/* eslint-disable */
function calcResistance(distExtra, distMax) {
return Math.min(1, distExtra / distMax / 1.2) * Math.min(distMax, distExtra)
}
function touchStart(e, ins) {
var dataset = e.instance.getDataset()
var state = e.instance.getState()
state.distMax = dataset.distMax
state.type = dataset.type
state.distThreshold = state.distMax * 0.75
state.reachTop = dataset.reachTop
state.status = state.status || "pending" // pending、pulling、releasing、refreshing
if (state.status === "pending" && state.reachTop) {
state.startPulling = true
state.pullStartX = e.touches[0].clientX
state.pullStartY = e.touches[0].clientY
state.distance = 0
state.component = state.component || ins.selectComponent(".refresh-wrap")
state.component.removeClass("transition")
state.component.removeClass("animation")
state.component.removeClass("fadeout")
state.component.setStyle({
top: (state.distance * 2 - 20) + "rpx",
opacity: 0,
transform: "rotate(0)",
"-webkit-transform": "rotate(0)"
})
}
}
function touchMove(e, ins) {
var state = e.instance.getState()
if (!state.startPulling || state.status === "refreshing") {
return true
}
state.pullMoveX = e.touches[0].clientX
state.pullMoveY = e.touches[0].clientY
if (state.status === "pending") {
state.status = "pulling"
}
var distExtraX = state.pullMoveX - state.pullStartX
var distExtraY = state.pullMoveY - state.pullStartY
if (distExtraY > 0 && Math.abs(distExtraY) >= Math.abs(distExtraX)) {
state.distance = calcResistance(distExtraY, state.distMax)
state.component.setStyle({
top: setop(state.distance, state.type),
opacity: Math.min(1, state.distance / state.distThreshold),
transform: "rotate(" + (245 * state.distance / state.distMax) + "deg)",
"-webkit-transform": "rotate(" + (245 * state.distance / state.distMax) + "deg)"
})
if (state.status === "pulling" && state.distance > state.distThreshold) {
state.status = "releasing"
}
if (state.status === "releasing" && state.distance < state.distThreshold) {
state.status = "pulling"
}
return false
}
return true
}
function touchEnd(e, ins) {
var state = e.instance.getState()
if (!state.startPulling || state.status === "refreshing") {
return
}
state.startPulling = false
if (state.status === "releasing" && state.distance > state.distThreshold) {
state.status = "refreshing"
state.distance = state.distThreshold
state.component.addClass("animation")
state.component.setStyle({
top: setop(state.distance, state.type),
opacity: Math.min(1, state.distance / state.distThreshold),
})
ins.triggerEvent("refresh")
} else {
reset(state)
}
}
function reset(state) {
state.status = "pending"
state.startPulling = false
state.distance = 0
state.component.addClass("transition")
state.component.setStyle({
top: setop(state.distance, state.type),
opacity: 0,
transform: "rotate(0)",
"-webkit-transform": "rotate(0)"
})
}
function onRefreshed(newValue, oldValue, ins, itemIns) {
if (newValue) {
var state = itemIns.getState()
state.status = "pending"
state.startPulling = false
var component = state.component || ins.selectComponent(".refresh-wrap")
component.removeClass("animation")
component.addClass("fadeout")
component.setStyle({
top: (state.distance * 2 - (state.type? 12 : 30)) + "rpx",
opacity: 0,
transform: "scale(0)",
"-webkit-transform": "rotate(0)"
})
}
}
function setop(distance, type){
var top = (distance * 2 + (type == 0 ? 120 : -30)) + "rpx"
return top
}
function onRefreshing(newValue, oldValue, ins, itemIns) {
if (newValue) {
var dataset = itemIns.getDataset()
var state = itemIns.getState()
state.distMax = state.distMax || dataset.distMax
state.distThreshold = state.distThreshold || state.distMax * 0.75
state.status = "refreshing"
state.distance = state.distThreshold
state.startPulling = false
state.component = state.component || ins.selectComponent(".refresh-wrap")
state.component.removeClass("transition")
state.component.removeClass("fadeout")
state.component.addClass("animation")
state.component.setStyle({
top: setop(state.distance, state.type),
opacity: 1,
transition: "none",
})
// ins.triggerEvent("refresh")
}
}
module.exports = {
touchStart: touchStart,
touchMove: touchMove,
touchEnd: touchEnd,
onRefreshed: onRefreshed,
onRefreshing: onRefreshing,
}
/* eslint-enable */