itemUtil.js 5.3 KB

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