| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 | import { isHidden } from '../utils/dom/style';import { unitToPx } from '../utils/format/unit';import { createNamespace, isDef, isServer } from '../utils';import { getScrollTop, getElementTop, getScroller } from '../utils/dom/scroll';import { BindEventMixin } from '../mixins/bind-event';var _createNamespace = createNamespace('sticky'),    createComponent = _createNamespace[0],    bem = _createNamespace[1];export default createComponent({  mixins: [BindEventMixin(function (bind, isBind) {    if (!this.scroller) {      this.scroller = getScroller(this.$el);    }    if (this.observer) {      var method = isBind ? 'observe' : 'unobserve';      this.observer[method](this.$el);    }    bind(this.scroller, 'scroll', this.onScroll, true);    this.onScroll();  })],  props: {    zIndex: [Number, String],    container: null,    offsetTop: {      type: [Number, String],      default: 0    }  },  data: function data() {    return {      fixed: false,      height: 0,      transform: 0    };  },  computed: {    offsetTopPx: function offsetTopPx() {      return unitToPx(this.offsetTop);    },    style: function style() {      if (!this.fixed) {        return;      }      var style = {};      if (isDef(this.zIndex)) {        style.zIndex = this.zIndex;      }      if (this.offsetTopPx && this.fixed) {        style.top = this.offsetTopPx + "px";      }      if (this.transform) {        style.transform = "translate3d(0, " + this.transform + "px, 0)";      }      return style;    }  },  watch: {    fixed: function fixed(isFixed) {      this.$emit('change', isFixed);    }  },  created: function created() {    var _this = this;    // compatibility: https://caniuse.com/#feat=intersectionobserver    if (!isServer && window.IntersectionObserver) {      this.observer = new IntersectionObserver(function (entries) {        // trigger scroll when visibility changed        if (entries[0].intersectionRatio > 0) {          _this.onScroll();        }      }, {        root: document.body      });    }  },  methods: {    onScroll: function onScroll() {      var _this2 = this;      if (isHidden(this.$el)) {        return;      }      this.height = this.$el.offsetHeight;      var container = this.container,          offsetTopPx = this.offsetTopPx;      var scrollTop = getScrollTop(window);      var topToPageTop = getElementTop(this.$el);      var emitScrollEvent = function emitScrollEvent() {        _this2.$emit('scroll', {          scrollTop: scrollTop,          isFixed: _this2.fixed        });      }; // The sticky component should be kept inside the container element      if (container) {        var bottomToPageTop = topToPageTop + container.offsetHeight;        if (scrollTop + offsetTopPx + this.height > bottomToPageTop) {          var distanceToBottom = this.height + scrollTop - bottomToPageTop;          if (distanceToBottom < this.height) {            this.fixed = true;            this.transform = -(distanceToBottom + offsetTopPx);          } else {            this.fixed = false;          }          emitScrollEvent();          return;        }      }      if (scrollTop + offsetTopPx > topToPageTop) {        this.fixed = true;        this.transform = 0;      } else {        this.fixed = false;      }      emitScrollEvent();    }  },  render: function render() {    var h = arguments[0];    var fixed = this.fixed;    var style = {      height: fixed ? this.height + "px" : null    };    return h("div", {      "style": style    }, [h("div", {      "class": bem({        fixed: fixed      }),      "style": this.style    }, [this.slots()])]);  }});
 |