import {
|
publishHandler
|
} from 'uni-platform/view/bridge'
|
|
export function disableScroll (evt) {
|
evt.preventDefault()
|
}
|
|
export function pageScrollTo ({
|
scrollTop,
|
selector,
|
duration
|
}) {
|
if (typeof scrollTop === 'undefined') {
|
const el = document.querySelector(selector)
|
if (el) {
|
const { top, height } = el.getBoundingClientRect()
|
scrollTop = top + window.pageYOffset
|
if (__PLATFORM__ === 'h5') {
|
scrollTop -= height
|
}
|
}
|
}
|
const documentElement = document.documentElement
|
|
const {
|
clientHeight,
|
scrollHeight
|
} = documentElement
|
|
scrollTop = Math.min(scrollTop, scrollHeight - clientHeight)
|
|
if (duration === 0) {
|
// 部分浏览器(比如微信)中 scrollTop 的值需要通过 document.body 来控制
|
documentElement.scrollTop = document.body.scrollTop = scrollTop
|
return
|
}
|
|
if (window.scrollY === scrollTop) {
|
return
|
}
|
|
function scrollTo (duration) {
|
if (duration <= 0) {
|
window.scrollTo(0, scrollTop)
|
return
|
}
|
const distaince = scrollTop - window.scrollY
|
requestAnimationFrame(function () {
|
window.scrollTo(0, window.scrollY + distaince / duration * 10)
|
scrollTo(duration - 10)
|
})
|
}
|
|
scrollTo(duration)
|
// TODO 暂不使用 transform 会导致 fixed 元素不可见
|
// const body = document.body
|
// const bodyStyle = body.style
|
//
|
// function webkitTransitionEnd() {
|
// bodyStyle.webkitTransition = ''
|
// bodyStyle.webkitTransform = ''
|
// documentElement.scrollTop = scrollTop
|
// body.removeEventListener('webkitTransitionEnd', webkitTransitionEnd)
|
// }
|
//
|
// body.addEventListener('webkitTransitionEnd', webkitTransitionEnd)
|
// bodyStyle.webkitTransition = `-webkit-transform ${duration}ms ease-out`
|
// bodyStyle.webkitTransform = `translateY(${documentElement.scrollTop}px) translateZ(0)`
|
}
|
|
let testReachBottomTimer
|
let lastScrollHeight = 0
|
|
export function createScrollListener (pageId, {
|
enablePageScroll,
|
enablePageReachBottom,
|
onReachBottomDistance,
|
enableTransparentTitleNView
|
}) {
|
let ticking = false
|
|
let hasReachBottom = false
|
|
let onReachBottom = true
|
|
function isReachBottom () {
|
const {
|
scrollHeight
|
} = document.documentElement
|
// 部分浏览器窗口高度变化后document.documentelement.clientheight不会变化,采用window.innerHeight
|
const windowHeight = window.innerHeight
|
const scrollY = window.scrollY
|
const isBottom = scrollY > 0 && scrollHeight > windowHeight && (scrollY + windowHeight + onReachBottomDistance) >= scrollHeight
|
// 兼容部分浏览器滚动时scroll事件不触发
|
const heightChanged = Math.abs(scrollHeight - lastScrollHeight) > onReachBottomDistance
|
if (isBottom && (!hasReachBottom || heightChanged)) {
|
lastScrollHeight = scrollHeight
|
hasReachBottom = true
|
return true
|
}
|
|
if (!isBottom && hasReachBottom) {
|
hasReachBottom = false
|
}
|
return false
|
}
|
|
function trigger () {
|
const pages = getCurrentPages()
|
if (!pages.length || pages[pages.length - 1].$page.id !== pageId) {
|
return
|
}
|
// publish
|
const scrollTop = window.pageYOffset
|
if (enablePageScroll) { // 向 Service 发送 onPageScroll 事件
|
publishHandler('onPageScroll', {
|
scrollTop
|
}, pageId)
|
}
|
|
if (enableTransparentTitleNView) {
|
UniViewJSBridge.emit('onPageScroll', {
|
scrollTop
|
})
|
}
|
function testReachBottom () {
|
if (isReachBottom()) {
|
publishHandler('onReachBottom', {}, pageId)
|
onReachBottom = false
|
setTimeout(function () {
|
onReachBottom = true
|
}, 350)
|
return true
|
}
|
}
|
if (enablePageReachBottom && onReachBottom) {
|
if (testReachBottom()) {
|
} else {
|
// 解决部分浏览器滚动中js获取窗口高度不准确导致的问题
|
testReachBottomTimer = setTimeout(testReachBottom, 300)
|
}
|
}
|
ticking = false
|
}
|
|
return function onScroll () {
|
clearTimeout(testReachBottomTimer)
|
if (!ticking) {
|
requestAnimationFrame(trigger)
|
}
|
ticking = true
|
}
|
}
|