UNPKG

lwj-scroll-nav

Version:
218 lines (207 loc) 8.4 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.LUtils = factory()); })(this, (function () { 'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var ScrollNav = /*#__PURE__*/function () { function ScrollNav() { var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _classCallCheck(this, ScrollNav); _defineProperty(this, "scrollContainer", null); _defineProperty(this, "scrollItemList", []); _defineProperty(this, "navItemList", []); _defineProperty(this, "activeNavItemClass", ''); _defineProperty(this, "indexKey", ''); _defineProperty(this, "offset", 0); _defineProperty(this, "scrollTop", 0); _defineProperty(this, "option", null); this.option = { scrollContainer: obj.scrollContainer || '.scroll-container', scrollItem: obj.scrollItem || '.scroll-container .scroll-item', navItem: obj.navItem || '.nav .nav-item', activeNavItemClass: obj.activeNavItemClass || 'active', indexKey: obj.indexKey || 'value-key', offset: obj.offset || 10 }; // 滚动容器(overflow: auto) this.scrollContainer = document.querySelector(this.option.scrollContainer); // 滚动项 this.scrollItemList = Array.from(document.querySelectorAll(this.option.scrollItem)); // 导航项 this.navItemList = Array.from(document.querySelectorAll(this.option.navItem)); // 导航被激活的class this.activeNavItemClass = this.option.activeNavItemClass; // 导航索引 this.indexKey = this.option.indexKey; // 偏移距离 this.offset = this.option.offset; // 滚动距离 this.scrollTop = 0; this.addEventListener(); this.handleScroll(); // 根据当前滚动距离激活默认菜单 } // 添加事件监听 _createClass(ScrollNav, [{ key: "addEventListener", value: function addEventListener() { var _this = this; if (this.scrollContainer) this.scrollContainer.addEventListener('scroll', this.handleScroll.bind(this)); // 导航栏点击事件 if (this.navItemList && this.navItemList.length) { this.navItemList.forEach(function (item, index) { item.onclick = function () { _this.handleNavClick(item, index); }; }); } } // 移除事件监听 }, { key: "removeEventListener", value: function removeEventListener() { if (this.scrollContainer) this.scrollContainer.removeEventListener('scroll', this.handleScroll.bind(this)); } // 滚动事件 }, { key: "handleScroll", value: function handleScroll() { var _this2 = this; var offset = this.scrollContainer.offsetTop; this.scrollItemList.forEach(function (scrollItem, index) { var offsetTop = _this2.scrollItemList[index].offsetTop - offset - _this2.scrollContainer.scrollTop; var navItem = _this2.getNavItemByScrollItem(scrollItem, index); if (offsetTop < _this2.offset && navItem) { _this2.navItemList.forEach(function (item) { item.classList.remove(_this2.activeNavItemClass); }); navItem.classList.add(_this2.activeNavItemClass); } }); this.scrollTop = this.scrollContainer.scrollTop; } // nav 点击事件 }, { key: "handleNavClick", value: function handleNavClick(item, index) { var _this3 = this; var scrollItem = this.getScrollItemByNavItem(item, index); this.scrollToElement(scrollItem); setTimeout(function () { // 若滚动距离不够,已经到底 if (!item.classList.contains(_this3.activeNavItemClass)) { _this3.navItemList.forEach(function (navItem) { navItem.classList.remove(_this3.activeNavItemClass); }); item.classList.add(_this3.activeNavItemClass); } }, 50); } // 根据navItem查找对应的scrollItem }, { key: "getScrollItemByNavItem", value: function getScrollItemByNavItem(navItem, index) { var _this4 = this; // 没有指定元素唯一值,则使用索引确定元素 if (!this.indexKey) return this.scrollItemList[index]; var indexKey = navItem.getAttribute(this.indexKey); if (!indexKey) return this.scrollItemList[index]; // 指定了元素唯一值,则使用唯一值确定元素 var scrollItem = null; Array.prototype.forEach.call(this.scrollItemList, function (item) { if (item.getAttribute(_this4.indexKey) === indexKey) scrollItem = item; }); return scrollItem; } // 根据scrollItem查找对应的navItem }, { key: "getNavItemByScrollItem", value: function getNavItemByScrollItem(scrollItem, index) { var _this5 = this; // 没有指定元素唯一值,则使用索引确定元素 if (!this.indexKey) return this.navItemList[index]; var indexKey = scrollItem.getAttribute(this.indexKey); if (!indexKey) return this.navItemList[index]; // 指定了元素唯一值,则使用唯一值确定元素 var navItem = null; Array.prototype.forEach.call(this.navItemList, function (item) { if (item.getAttribute(_this5.indexKey) === indexKey) navItem = item; }); return navItem; } // 获取当前激活的导航 }, { key: "getActiveNavItem", value: function getActiveNavItem() { return document.querySelector("".concat(this.option.navItem, ".").concat(this.option.activeNavItemClass)); } // 滚动至目标项 }, { key: "scrollToElement", value: function scrollToElement(scrollItem) { if (!scrollItem) return; this.scrollTop = scrollItem.offsetTop - this.scrollContainer.offsetTop; this.scrollContainer.scrollTop = this.scrollTop; } }]); return ScrollNav; }(); return ScrollNav; }));