'f'
mh-two-thousand-and-two
2024-04-12 26f2711ef9461961fb953e2b497bd314ef95e345
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
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
  }
}