index.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // @ts-nocheck
  2. // #ifdef UNI-APP-X && APP
  3. // export * from './uvue.uts'
  4. export { getRect, getAllRect } from './uvue.uts'
  5. // #endif
  6. // #ifndef UNI-APP-X && APP
  7. // export * from './vue.ts'
  8. export { getRect, getAllRect } from './vue.ts'
  9. // #endif
  10. /**
  11. * 获取视口滚动条位置信息
  12. */
  13. export function getViewportScrollInfo() : Promise<any> {
  14. return new Promise(resolve => {
  15. uni.createSelectorQuery()
  16. .selectViewport()
  17. .scrollOffset((res) => {
  18. resolve(res);
  19. }).exec();
  20. })
  21. }
  22. /**
  23. ```
  24. page
  25. ╭───────────────╮ viewport
  26. ╭─│─ ─ ─ ─ ─ ─ ─ ─│─╮ ╱
  27. │ │ ╭───────────╮ │ │
  28. │ │ │ element │ │ │
  29. │ │ ╰───────────╯ │ │
  30. ╰─│─ ─ ─ ─ ─ ─ ─ ─│─╯
  31. │ │
  32. │ │
  33. ╰───────────────╯
  34. ```
  35. # 参数
  36. - viewportHeight: viewport 高度
  37. - viewportScrollTop: viewport 垂直滚动值
  38. - elementHeight: element 高度
  39. - elementOffsetTop: element 距离页面顶部距离
  40. # 选项
  41. - position: element 在视窗中的位置(start, center, end, nearest)
  42. - startOffset: element 距离视窗顶部的偏移量
  43. - endOffset: element 距离视窗底部的偏移量
  44. # 结果值
  45. - viewportScrollTop: viewport 新的垂直滚动值
  46. */
  47. export type ScrollIntoViewOptions = {
  48. /** 元素顶部需要保留的缓冲距离(默认 0) */
  49. startOffset ?: number;
  50. /** 元素底部需要保留的缓冲距离(默认 0) */
  51. endOffset ?: number;
  52. /** 滚动对齐方式:start/center/end/nearest(默认 nearest) */
  53. position ?: 'start' | 'center' | 'end' | 'nearest';
  54. }
  55. /**
  56. * 计算元素需要滚动到可视区域的目标滚动位置
  57. * @param viewportHeight 视口高度(像素)
  58. * @param viewportScrollTop 当前滚动位置(像素)
  59. * @param elementHeight 元素高度(像素)
  60. * @param elementOffsetTop 元素相对于父容器顶部的偏移量(像素)
  61. * @param options 配置选项
  62. * @returns 计算后的目标滚动位置(像素)
  63. *
  64. * @example
  65. * // 示例:将元素滚动到视口顶部对齐
  66. * const scrollTop = getScrollIntoViewValue(
  67. * 500, // 视口高度
  68. * 200, // 当前滚动位置
  69. * 100, // 元素高度
  70. * 300, // 元素偏移量
  71. * { position: 'start' }
  72. * );
  73. */
  74. export function getScrollIntoViewValue(
  75. viewportHeight : number,
  76. viewportScrollTop : number,
  77. elementHeight : number,
  78. elementOffsetTop : number,
  79. options : ScrollIntoViewOptions = {}
  80. ) : number {
  81. let { startOffset = 0, endOffset = 0, position = 'nearest'} = options;
  82. // 计算元素相对于视口的上下偏移量
  83. const elementToViewportTopOffset = elementOffsetTop - viewportScrollTop - startOffset;
  84. const elementToViewportBottomOffset =
  85. elementOffsetTop +
  86. elementHeight -
  87. viewportScrollTop -
  88. viewportHeight +
  89. endOffset;
  90. // 处理 nearest 模式,自动选择最近边缘
  91. if (position == 'nearest') {
  92. if (elementToViewportTopOffset >= 0 && elementToViewportBottomOffset <= 0) {
  93. return viewportScrollTop;
  94. }
  95. position =
  96. Math.abs(elementToViewportTopOffset) > Math.abs(elementToViewportBottomOffset)
  97. ? 'end'
  98. : 'start';
  99. }
  100. // 根据不同的对齐位置计算目标滚动位置
  101. let nextScrollTop = 0;
  102. switch (position) {
  103. case 'start':
  104. // 顶部对齐:元素顶部对齐视口顶部(考虑顶部缓冲)
  105. nextScrollTop = elementOffsetTop - startOffset;
  106. break;
  107. case 'center':
  108. // 居中对齐:元素中心对齐视口中心(考虑上下缓冲)
  109. nextScrollTop =
  110. elementOffsetTop -
  111. (viewportHeight - elementHeight - endOffset - startOffset) / 2 +
  112. startOffset;
  113. break;
  114. case 'end':
  115. // 底部对齐:元素底部对齐视口底部(考虑底部缓冲)
  116. nextScrollTop =
  117. elementOffsetTop + elementHeight - viewportHeight + endOffset;
  118. break;
  119. }
  120. return nextScrollTop;
  121. }