UNPKG

captain-ui

Version:

有赞vue wap业务组件库

197 lines (170 loc) 6.27 kB
var _components; import Utils from '../../../common/scroll'; import Nav from './nav'; import { NAV_STATE } from '../constants'; window.requestAnimFrame = function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); }; }(); export default { render: function render() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "cap-category" }, [_c('cap-category-nav', { ref: "nav", attrs: { "nav-list": _vm.navList, "window-height": _vm.windowHeight, "state": _vm.navState, "active": _vm.currentActive }, on: { "click": _vm.handleNavClick } }), _c('div', { staticClass: "cap-category-container" }, [_c('h1', { staticClass: "cap-category-container__active-title", class: { 'cap-category-container__active-title--fixed': _vm.groupTitleFixed } }, [_vm._v("\n " + _vm._s(_vm.navList[_vm.currentTitleActive].title) + "\n ")]), _vm._t("default")], 2)], 1); }, name: 'cap-category-base', components: (_components = {}, _components[Nav.name] = Nav, _components), props: { navList: { type: Array, default: function _default() { return []; } } }, data: function data() { return { navState: NAV_STATE.NORMAL, windowHeight: window.innerHeight, currentActive: 0, currentTitleActive: 0, shouldCheckNav: true }; }, computed: { groupTitleFixed: function groupTitleFixed() { // 当前主分类的名称是否吸顶 return this.navState !== NAV_STATE.NORMAL; } }, mounted: function mounted() { this.scrollEl = Utils.getScrollEventTarget(this.$el); // 滚动元素 this.navScrollEl = Utils.getScrollEventTarget(this.$refs.nav.$el); // 左侧导航栏滚动元素 this.scrollEl.addEventListener('scroll', this.handleScroll); this.init(); }, destroyed: function destroyed() { this.scrollEl.removeEventListener('scroll', this.handleScroll); }, methods: { init: function init() { var _this = this; this.$nextTick(function () { _this.getDOMHeight(); _this.handleScroll(); }); }, getDOMHeight: function getDOMHeight() { this.groups = [].slice.call(this.$slots.default[0].elm.childNodes); this.elHeight = Utils.getVisibleHeight(this.$el); this.navHeight = Utils.getVisibleHeight(this.$refs.nav.$el); this.groupHeightList = this.groups.map(function (group) { return Utils.getVisibleHeight(group); }); // 各分组的高度 }, // 处理滚动 handleScroll: function handleScroll() { var elHeight = this.elHeight, navHeight = this.navHeight; var elToTop = Utils.getElementTop(this.$el); // 文档顶部到元素的距离 var scrollTop = Utils.getScrollTop(this.scrollEl); // 滚动距离 var navState = NAV_STATE.NORMAL; if (navHeight + scrollTop - elToTop - elHeight > 0) { // 如果(左侧导航栏高度 + 滚动高度) > (右侧到文档顶部距离 + 右侧内容高度),则滚出屏幕 navState = NAV_STATE.SCROLL_OUT; } else if (scrollTop - elToTop > 0) { // 如果滚动高度 > 元素到文档顶部距离,则吸顶 navState = NAV_STATE.FIXED; } this.navState = navState; var oldActive = this.currentActive; if (this.shouldCheckNav) { // 如果是滚动导致的 active 改变,则更新左侧导航栏的 active this.updateActive(scrollTop - elToTop); } if (this.navState === NAV_STATE.FIXED && oldActive !== this.currentActive) { // 如果导航栏已经吸顶,并且 active 已改变,则调整导航栏的位置 this.setActiveNavVisible(this.currentActive); } }, // 更新导航栏 active 项 updateActive: function updateActive(scrollTop) { var _this2 = this; var totalHeight = 0; this.groupHeightList.some(function (groupHeight, index) { totalHeight += groupHeight; if (totalHeight > scrollTop) { _this2.currentActive = index; _this2.currentTitleActive = index; return true; } }); }, // 使导航栏的 active 分类保持在屏幕中部位置 setActiveNavVisible: function setActiveNavVisible(activeIndex) { var activeNav = this.$refs.nav.$refs.badges[activeIndex].$el; var _activeNav$getBoundin = activeNav.getBoundingClientRect(), top = _activeNav$getBoundin.top, bottom = _activeNav$getBoundin.bottom; if (top < 0 || bottom > this.windowHeight / 3) { this.scrollAnim(this.navScrollEl, this.$refs.nav.$el.scrollTop, activeNav.offsetTop - this.windowHeight / 3); } }, handleNavClick: function handleNavClick(index) { var _this3 = this; var groupToTop = Utils.getElementTop(this.groups[index]); var scrollTop = Utils.getScrollTop(this.scrollEl); var navList = this.navList, windowHeight = this.windowHeight; var lastIndex = navList.length - 1; var lastGroup = document.querySelectorAll('.cap-category-container__group')[lastIndex]; var offsetHeight = lastGroup.offsetHeight; if (index === navList.length - 1 && offsetHeight < windowHeight) { this.currentTitleActive = index - 1; } else { this.currentTitleActive = index; } this.currentActive = index; this.shouldCheckNav = false; this.scrollAnim(this.scrollEl, scrollTop, groupToTop); setTimeout(function () { _this3.shouldCheckNav = true; }, 300); }, // 滚动切换动画 scrollAnim: function scrollAnim(element, scrollTop, targetTop) { var progress = 0; // 进度 var diff = targetTop - scrollTop; // 距离 var anim = function anim() { progress += 8; Utils.setScrollTop(element, scrollTop + diff * Math.min(progress / 100, 1)); if (progress < 100) { window.requestAnimFrame(anim); } }; anim(); } } };