itemUtil.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.GHOST_ITEM_KEY = void 0;
  6. exports.alignScrollTop = alignScrollTop;
  7. exports.getCompareItemRelativeTop = getCompareItemRelativeTop;
  8. exports.getElementScrollPercentage = getElementScrollPercentage;
  9. exports.getItemAbsoluteTop = getItemAbsoluteTop;
  10. exports.getItemRelativeTop = getItemRelativeTop;
  11. exports.getNodeHeight = getNodeHeight;
  12. exports.getRangeIndex = getRangeIndex;
  13. exports.getScrollPercentage = getScrollPercentage;
  14. exports.requireVirtual = requireVirtual;
  15. var __rest = void 0 && (void 0).__rest || function (s, e) {
  16. var t = {};
  17. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
  18. if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  19. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
  20. }
  21. return t;
  22. };
  23. /**
  24. * Our algorithm have additional one ghost item
  25. * whose index as `data.length` to simplify the calculation
  26. */
  27. const GHOST_ITEM_KEY = exports.GHOST_ITEM_KEY = '__vc_ghost_item__';
  28. /**
  29. * Safari has the elasticity effect which provides negative `scrollTop` value.
  30. * We should ignore it since will make scroll animation shake.
  31. */
  32. function alignScrollTop(scrollTop, scrollRange) {
  33. if (scrollTop < 0) {
  34. return 0;
  35. }
  36. if (scrollTop >= scrollRange) {
  37. return scrollRange;
  38. }
  39. return scrollTop;
  40. }
  41. /**
  42. * Get node `offsetHeight`. We prefer node is a dom element directly.
  43. * But if not provided, downgrade to `findDOMNode` to get the real dom element.
  44. */
  45. function getNodeHeight(node) {
  46. return node ? node.offsetHeight : 0;
  47. }
  48. /**
  49. * Calculate the located item absolute top with whole scroll height
  50. */
  51. function getItemAbsoluteTop(_a) {
  52. var {
  53. scrollTop
  54. } = _a,
  55. rest = __rest(_a, ["scrollTop"]);
  56. return scrollTop + getItemRelativeTop(rest);
  57. }
  58. /**
  59. * Calculate the located item related top with current window height
  60. */
  61. function getItemRelativeTop(_ref) {
  62. let {
  63. itemIndex,
  64. itemOffsetPtg,
  65. itemElementHeights,
  66. scrollPtg,
  67. clientHeight,
  68. getItemKey
  69. } = _ref;
  70. const locatedItemHeight = itemElementHeights[getItemKey(itemIndex)] || 0;
  71. const locatedItemTop = scrollPtg * clientHeight;
  72. const locatedItemOffset = itemOffsetPtg * locatedItemHeight;
  73. return Math.floor(locatedItemTop - locatedItemOffset);
  74. }
  75. function getCompareItemRelativeTop(_ref2) {
  76. let {
  77. locatedItemRelativeTop,
  78. locatedItemIndex,
  79. compareItemIndex,
  80. startIndex,
  81. endIndex,
  82. getItemKey,
  83. itemElementHeights
  84. } = _ref2;
  85. let originCompareItemTop = locatedItemRelativeTop;
  86. const compareItemKey = getItemKey(compareItemIndex);
  87. if (compareItemIndex <= locatedItemIndex) {
  88. for (let index = locatedItemIndex; index >= startIndex; index -= 1) {
  89. const key = getItemKey(index);
  90. if (key === compareItemKey) {
  91. break;
  92. }
  93. const prevItemKey = getItemKey(index - 1);
  94. originCompareItemTop -= itemElementHeights[prevItemKey] || 0;
  95. }
  96. } else {
  97. for (let index = locatedItemIndex; index <= endIndex; index += 1) {
  98. const key = getItemKey(index);
  99. if (key === compareItemKey) {
  100. break;
  101. }
  102. originCompareItemTop += itemElementHeights[key] || 0;
  103. }
  104. }
  105. return originCompareItemTop;
  106. }
  107. function getScrollPercentage(_ref3) {
  108. let {
  109. scrollTop,
  110. scrollHeight,
  111. clientHeight
  112. } = _ref3;
  113. if (scrollHeight <= clientHeight) {
  114. return 0;
  115. }
  116. const scrollRange = scrollHeight - clientHeight;
  117. const alignedScrollTop = alignScrollTop(scrollTop, scrollRange);
  118. const scrollTopPtg = alignedScrollTop / scrollRange;
  119. return scrollTopPtg;
  120. }
  121. function getElementScrollPercentage(element) {
  122. if (!element) {
  123. return 0;
  124. }
  125. return getScrollPercentage(element);
  126. }
  127. /**
  128. * Get location item and its align percentage with the scroll percentage.
  129. * We should measure current scroll position to decide which item is the location item.
  130. * And then fill the top count and bottom count with the base of location item.
  131. *
  132. * `total` should be the real count instead of `total - 1` in calculation.
  133. */
  134. function getLocationItem(scrollPtg, total) {
  135. const itemIndex = Math.floor(scrollPtg * total);
  136. const itemTopPtg = itemIndex / total;
  137. const itemBottomPtg = (itemIndex + 1) / total;
  138. const itemOffsetPtg = (scrollPtg - itemTopPtg) / (itemBottomPtg - itemTopPtg);
  139. return {
  140. index: itemIndex,
  141. offsetPtg: itemOffsetPtg
  142. };
  143. }
  144. /**
  145. * Get display items start, end, located item index. This is pure math calculation
  146. */
  147. function getRangeIndex(scrollPtg, itemCount, visibleCount) {
  148. const {
  149. index,
  150. offsetPtg
  151. } = getLocationItem(scrollPtg, itemCount);
  152. const beforeCount = Math.ceil(scrollPtg * visibleCount);
  153. const afterCount = Math.ceil((1 - scrollPtg) * visibleCount);
  154. return {
  155. itemIndex: index,
  156. itemOffsetPtg: offsetPtg,
  157. startIndex: Math.max(0, index - beforeCount),
  158. endIndex: Math.min(itemCount - 1, index + afterCount)
  159. };
  160. }
  161. function requireVirtual(height, itemHeight, count, virtual) {
  162. return virtual !== false && typeof height === 'number' && count * itemHeight > height;
  163. }