itemUtil.js 4.6 KB

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