UNPKG

sg-scroll

Version:
102 lines (90 loc) 3.06 kB
/** * @param {Event} e */ const sgScroll = function ({ target }) { // 判断滚动容器的top内边距是否缓存 if (target.sgPaddingTop === undefined) { target.sgPaddingTop = parseInt(getComputedStyle(target).paddingTop) || 0; } const paddingTop = target.sgPaddingTop; const scrollTop = target.scrollTop; // 暂不考虑一开始设置到滚动容器的内联样式 target.style.paddingTop = ""; // 重置元素的内联样式 let stickyEl = target.sgStickyEl; if (stickyEl) { stickyEl.style.width = ""; stickyEl.style.position = ""; stickyEl.style.top = ""; stickyEl.classList.remove("sg-sticking"); } // 获取所有能够粘滞的元素 const children = [...target.children].filter((el) => { return el.classList.contains("sg-sticky-item"); }); // 找到最后一个产生粘滞的元素 let index = -1; for (let i = children.length - 1; i >= 0; i--) { if (children[i].offsetTop - scrollTop < paddingTop) { index = i; break; } } if (index === -1) { return; } stickyEl = children[index]; const stickyClientHeight = stickyEl.clientHeight; // 判断下一个即将粘滞的元素,用于粘滞元素过渡计算 const nextIndex = index + 1; let nextPadding = 0; if (nextIndex < children.length) { const offset = children[nextIndex].offsetTop - scrollTop - paddingTop; if (offset < stickyClientHeight) { nextPadding = stickyClientHeight - offset; } } // 先获取高度后再设置定位 stickyEl.style.width = stickyEl.clientWidth + "px"; stickyEl.style.position = "absolute"; // stickyEl.style.top = paddingTop + scrollTop - nextPadding + "px"; stickyEl.style.top = paddingTop - nextPadding + "px"; stickyEl.classList.add("sg-sticking"); target.sgStickyEl = stickyEl; // 判断缓存元素的上下间隔 if (target.sgStickElMargin === undefined) { const style = getComputedStyle(stickyEl); target.sgStickElMargin = parseInt(style.marginTop) + parseInt(style.marginBottom); } // 设置滚动容器的top边距 target.style.paddingTop = paddingTop + stickyClientHeight + target.sgStickElMargin + "px"; } const rootEl = document.body export default { init: function () { if (rootEl._sgIsStickyInit) { return } rootEl._sgIsStickyInit = true const actionStartEvent = function (e) { let scrollEl = e.target while(scrollEl) { if (scrollEl.getAttribute("sg-sticky") === "sg-sticky-item") { if (scrollEl._sgIsStickyInit) { return } scrollEl._sgIsStickyInit = true scrollEl.parentElement.style.position = 'relative' scrollEl.addEventListener('scroll', sgScroll) break } scrollEl = scrollEl.parentElement } } rootEl.addEventListener('touchstart', actionStartEvent) rootEl.addEventListener('mousedown', actionStartEvent) } }