index.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. "use strict";
  2. exports.__esModule = true;
  3. exports.default = void 0;
  4. var _style = require("../utils/dom/style");
  5. var _unit = require("../utils/format/unit");
  6. var _utils = require("../utils");
  7. var _scroll = require("../utils/dom/scroll");
  8. var _bindEvent = require("../mixins/bind-event");
  9. var _createNamespace = (0, _utils.createNamespace)('sticky'),
  10. createComponent = _createNamespace[0],
  11. bem = _createNamespace[1];
  12. var _default = createComponent({
  13. mixins: [(0, _bindEvent.BindEventMixin)(function (bind, isBind) {
  14. if (!this.scroller) {
  15. this.scroller = (0, _scroll.getScroller)(this.$el);
  16. }
  17. if (this.observer) {
  18. var method = isBind ? 'observe' : 'unobserve';
  19. this.observer[method](this.$el);
  20. }
  21. bind(this.scroller, 'scroll', this.onScroll, true);
  22. this.onScroll();
  23. })],
  24. props: {
  25. zIndex: [Number, String],
  26. container: null,
  27. offsetTop: {
  28. type: [Number, String],
  29. default: 0
  30. }
  31. },
  32. data: function data() {
  33. return {
  34. fixed: false,
  35. height: 0,
  36. transform: 0
  37. };
  38. },
  39. computed: {
  40. offsetTopPx: function offsetTopPx() {
  41. return (0, _unit.unitToPx)(this.offsetTop);
  42. },
  43. style: function style() {
  44. if (!this.fixed) {
  45. return;
  46. }
  47. var style = {};
  48. if ((0, _utils.isDef)(this.zIndex)) {
  49. style.zIndex = this.zIndex;
  50. }
  51. if (this.offsetTopPx && this.fixed) {
  52. style.top = this.offsetTopPx + "px";
  53. }
  54. if (this.transform) {
  55. style.transform = "translate3d(0, " + this.transform + "px, 0)";
  56. }
  57. return style;
  58. }
  59. },
  60. watch: {
  61. fixed: function fixed(isFixed) {
  62. this.$emit('change', isFixed);
  63. }
  64. },
  65. created: function created() {
  66. var _this = this;
  67. // compatibility: https://caniuse.com/#feat=intersectionobserver
  68. if (!_utils.isServer && window.IntersectionObserver) {
  69. this.observer = new IntersectionObserver(function (entries) {
  70. // trigger scroll when visibility changed
  71. if (entries[0].intersectionRatio > 0) {
  72. _this.onScroll();
  73. }
  74. }, {
  75. root: document.body
  76. });
  77. }
  78. },
  79. methods: {
  80. onScroll: function onScroll() {
  81. var _this2 = this;
  82. if ((0, _style.isHidden)(this.$el)) {
  83. return;
  84. }
  85. this.height = this.$el.offsetHeight;
  86. var container = this.container,
  87. offsetTopPx = this.offsetTopPx;
  88. var scrollTop = (0, _scroll.getScrollTop)(window);
  89. var topToPageTop = (0, _scroll.getElementTop)(this.$el);
  90. var emitScrollEvent = function emitScrollEvent() {
  91. _this2.$emit('scroll', {
  92. scrollTop: scrollTop,
  93. isFixed: _this2.fixed
  94. });
  95. }; // The sticky component should be kept inside the container element
  96. if (container) {
  97. var bottomToPageTop = topToPageTop + container.offsetHeight;
  98. if (scrollTop + offsetTopPx + this.height > bottomToPageTop) {
  99. var distanceToBottom = this.height + scrollTop - bottomToPageTop;
  100. if (distanceToBottom < this.height) {
  101. this.fixed = true;
  102. this.transform = -(distanceToBottom + offsetTopPx);
  103. } else {
  104. this.fixed = false;
  105. }
  106. emitScrollEvent();
  107. return;
  108. }
  109. }
  110. if (scrollTop + offsetTopPx > topToPageTop) {
  111. this.fixed = true;
  112. this.transform = 0;
  113. } else {
  114. this.fixed = false;
  115. }
  116. emitScrollEvent();
  117. }
  118. },
  119. render: function render() {
  120. var h = arguments[0];
  121. var fixed = this.fixed;
  122. var style = {
  123. height: fixed ? this.height + "px" : null
  124. };
  125. return h("div", {
  126. "style": style
  127. }, [h("div", {
  128. "class": bem({
  129. fixed: fixed
  130. }),
  131. "style": this.style
  132. }, [this.slots()])]);
  133. }
  134. });
  135. exports.default = _default;