Можно использовать и в мобильном приложении на cordova/phonegap
стили можно перенсти в style.css
| Код |
|---|
(function () {
if (!('ontouchstart' in window)) return; // Только на тач-устройствах
function initPullToRefresh() {
var startY = null;
var dist = 0;
var threshold = 70;
var maxDist = 150;
var pulling = false;
var refreshTriggered = false;
var spinner = document.createElement('div');
spinner.style.position = 'fixed';
spinner.style.top = '0';
spinner.style.left = '0';
spinner.style.right = '0';
spinner.style.height = '50px';
//spinner.style.background = 'white';
spinner.style.display = 'flex';
spinner.style.justifyContent = 'center';
spinner.style.alignItems = 'center';
spinner.style.fontSize = '24px';
spinner.style.color = '#007aff';
spinner.style.transform = 'translateY(-50px)';
spinner.style.transition = 'transform 0.3s ease, opacity 0.3s ease';
spinner.style.zIndex = '9999';
spinner.style.opacity = '0';
spinner.innerHTML = `
<svg style="width:24px; height:24px; animation: spin 1s linear infinite;" viewBox="0 0 50 50" >
<rect x="10" y="10" width="30" height="30" stroke="#007aff" stroke-width="5" fill="none" />
</svg>
`;
document.body.appendChild(spinner);
var styleEl = document.createElement('style');
styleEl.innerHTML = `
@keyframes spin {
0% { transform: rotate(0deg);}
100% { transform: rotate(360deg);}
}
`;
document.head.appendChild(styleEl);
// Проверяем, что прокрутка body/doc вверху
function canPullToRefresh() {
// Совместимый вариант для любых браузеров:
return (window.pageYOffset || document.documentElement.scrollTop) === 0;
}
function onTouchStart(e) {
if (canPullToRefresh() && !refreshTriggered) {
startY = e.touches[0].screenY;
pulling = true;
dist = 0;
spinner.style.transition = 'none';
spinner.style.opacity = '1';
}
}
function onTouchMove(e) {
if (!pulling) return;
var currentY = e.touches[0].screenY;
dist = currentY - startY;
if (dist > 0) {
e.preventDefault(); // Блокируем скролл вниз при протягивании
var moveDist = Math.min(dist, maxDist);
spinner.style.transform = 'translateY(' + (moveDist - 50) + 'px)';
if (moveDist > threshold) {
spinner.style.color = '#007aff';
} else {
spinner.style.color = '#999';
}
} else {
spinner.style.transform = 'translateY(-50px)';
spinner.style.opacity = '0';
pulling = false;
}
}
function onTouchEnd(e) {
if (!pulling) return;
spinner.style.transition = 'transform 0.3s ease, opacity 0.3s ease';
if (dist > threshold) {
refreshTriggered = true;
spinner.style.transform = 'translateY(0px)';
spinner.style.opacity = '1';
window.location.reload();
} else {
spinner.style.transform = 'translateY(-50px)';
spinner.style.opacity = '0';
}
pulling = false;
startY = null;
dist = 0;
}
window.addEventListener('touchstart', onTouchStart, {passive: false});
window.addEventListener('touchmove', onTouchMove, {passive: false});
window.addEventListener('touchend', onTouchEnd);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initPullToRefresh);
} else {
initPullToRefresh();
}
})(); |