页面顶部下拉展示动画,包含刷新功能。改进自原代码作者:路灯下的豆子不结籽
// ==UserScript==
// @name 页面下拉刷新 1.30
// @namespace https://example.com
// @version 1.30
// @description 页面顶部下拉展示动画,包含刷新功能。改进自原代码作者:路灯下的豆子不结籽
// @match *://*/*
// @exclude https://greasyfork.org/*
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
// 设置下拉的比例,这里设为 10%
const pullDownRatio = 0.1;
// 用于记录触摸开始时手指在 Y 轴上的坐标
let startY = 0;
// 标记是否处于触摸拖动状态,初始为 false
let isDragging = false;
// 设置下挪和回弹动画的持续时间,单位为秒,固定为 0.3 秒
const animationDuration = 0.3;
// 设置动画的缓动函数,这里使用 'ease' 使动画更自然平滑
const easeFunction = 'ease';
// 用于记录当前下拉的距离
let currentDistance = 0;
// 获取页面的 body 元素,后续用于操作页面的位移来实现动画效果
const body = document.querySelector('body');
// 计算下拉的阈值(基于页面高度的比例)
const threshold = window.innerHeight * pullDownRatio;
// 开始下拉动画的函数
function startPullDownAnimation() {
// 明确设置 transform 的初始值为 translateY(0),确保动画起始状态正确
body.style.transform = 'translateY(0)';
// 设置页面 body 的过渡动画属性,包括持续时间和缓动函数
body.style.transition = `transform ${animationDuration}s ${easeFunction}`;
// 将页面 body 向下平移计算出的阈值距离,实现下拉动画效果
body.style.transform = `translateY(${threshold}px)`;
}
// 开始回弹动画的函数
function startReboundAnimation() {
// 明确设置 transform 的目标值为 translateY(0),确保动画结束状态正确
body.style.transform = `translateY(${threshold}px)`;
// 设置页面 body 的过渡动画属性,包括持续时间和缓动函数
body.style.transition = `transform ${animationDuration}s ${easeFunction}`;
// 将页面 body 移回初始位置(Y 轴位移为 0),实现回弹动画效果
body.style.transform = 'translateY(0)';
}
// 监听触摸开始事件
document.addEventListener('touchstart', function (e) {
// 判断页面是否在最顶部(滚动条 Y 轴位置为 0)
if (window.scrollY === 0) {
// 记录触摸开始时手指的 Y 坐标
startY = e.touches[0].clientY;
// 标记进入触摸拖动状态
isDragging = true;
// 开始拖动时取消过渡动画,使拖动操作更流畅
body.style.transition = 'none';
// 在控制台打印日志,显示触摸开始时记录的 Y 坐标
console.log('touchstart: startY set to', startY);
}
});
// 监听触摸移动事件
document.addEventListener('touchmove', function (e) {
// 判断页面是否在最顶部(滚动条 Y 轴位置为 0)
if (window.scrollY === 0 && isDragging) {
// 获取当前触摸点的 Y 坐标
const currentY = e.touches[0].clientY;
// 计算触摸点移动的距离
currentDistance = currentY - startY;
// 如果移动距离大于 0,则直接控制页面的位移
if (currentDistance > 0) {
// 直接设置页面的位移
body.style.transform = `translateY(${currentDistance}px)`;
}
// 当移动距离超过阈值时,直接触发回弹动画
if (currentDistance > threshold) {
startReboundAnimation();
// 监听回弹动画结束事件,在动画结束后刷新页面
body.addEventListener('transitionend', function onTransitionEnd() {
// 移除事件监听器,避免重复执行
body.removeEventListener('transitionend', onTransitionEnd);
// 执行页面刷新
console.log('Reloading page...');
location.reload();
}, { once: true });
// 重置拖动状态
isDragging = false;
// 重置当前下拉距离
currentDistance = 0;
}
}
});
// 监听触摸结束事件
document.addEventListener('touchend', function () {
if (isDragging) {
// 如果下拉距离超过阈值,触发回弹动画
if (currentDistance > threshold) {
startReboundAnimation();
// 监听回弹动画结束事件,在动画结束后刷新页面
body.addEventListener('transitionend', function onTransitionEnd() {
// 移除事件监听器,避免重复执行
body.removeEventListener('transitionend', onTransitionEnd);
// 执行页面刷新
console.log('Reloading page...');
location.reload();
}, { once: true });
} else {
// 如果下拉距离未超过阈值,也执行回弹动画使页面回到初始位置
startReboundAnimation();
}
}
// 重置触摸开始时记录的 Y 坐标为 0
startY = 0;
// 重置拖动状态
isDragging = false;
// 重置当前下拉距离
currentDistance = 0;
});
// 监听触摸取消事件
document.addEventListener('touchcancel', function () {
if (isDragging) {
// 执行回弹动画函数,使页面回到初始位置
startReboundAnimation();
// 监听回弹动画结束事件,在动画结束后刷新页面
body.addEventListener('transitionend', function onTransitionEnd() {
// 移除事件监听器,避免重复执行
body.removeEventListener('transitionend', onTransitionEnd);
// 执行页面刷新
console.log('Reloading page...');
location.reload();
}, { once: true });
// 重置触摸开始时记录的 Y 坐标为 0
startY = 0;
// 重置拖动状态
isDragging = false;
// 重置当前下拉距离
currentDistance = 0;
}
});
})();