UNPKG

vui-design

Version:

A high quality UI Toolkit based on Vue.js

169 lines (143 loc) 5.21 kB
import PropTypes from "../../utils/prop-types"; import is from "../../utils/is"; import throttle from "../../utils/throttle"; import scrollTo from "../../utils/scrollTo"; import addEventListener from "../../utils/addEventListener"; import getClassNamePrefix from "../../utils/getClassNamePrefix"; export const createProps = () => { return { classNamePrefix: PropTypes.string, threshold: PropTypes.number.def(400), right: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).def(40), bottom: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).def(40), duration: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).def(500), scrollContainer: PropTypes.any, animation: PropTypes.string.def("vui-backtop-fade") }; }; export default { name: "vui-backtop", props: createProps(), data() { const state = { visibility: false }; return { state }; }, methods: { getContainer() { const { $el: el, $props: props } = this; const scrollContainer = props.scrollContainer; let container; if (is.string(scrollContainer)) { container = document.querySelector(scrollContainer); } else if (is.element(scrollContainer)) { container = scrollContainer; } else if (is.function(scrollContainer)) { container = scrollContainer(el); } else { container = window; } return container; }, getContainerScrollTop() { const container = this.getContainer(); if (!container) { return 0; } if (container === window) { return window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop; } return container.scrollTop; }, addScrollListener() { if (is.server) { return; } const container = this.getContainer(); if (!container) { return; } this.container = container; this.scrollHandler = throttle(this.handleScroll, 200); this.scrollEvent = addEventListener(container, "scroll", this.scrollHandler); this.handleScroll(); }, removeScrollListener() { if (is.server) { return; } const { container, scrollHandler, scrollEvent } = this; if (!container || !scrollHandler || !scrollEvent) { return; } this.scrollEvent.remove(); this.container = null; this.scrollHandler = null; this.scrollEvent = null; }, handleScroll(e) { const { $props: props } = this; const scrollTop = this.getContainerScrollTop(); this.state.visibility = scrollTop >= props.threshold; }, handleClick(e) { this.$emit("click", e); const { $props: props } = this; const container = this.getContainer(); if (!container) { return; } const start = this.getContainerScrollTop(); const end = 0; scrollTo(container, start, end, props.duration); } }, mounted() { this.addScrollListener(); }, beforeDestroy() { this.removeScrollListener(); }, render(h) { const { $slots: slots, $props: props, state, handleClick } = this; // class const classNamePrefix = getClassNamePrefix(props.classNamePrefix, "backtop"); let classes = {}; classes.el = `${classNamePrefix}`; classes.elContent = `${classNamePrefix}-content`; // style let styles = {}; styles.el = { right: is.string(props.right) ? props.right : `${props.right}px`, bottom: is.string(props.bottom) ? props.bottom : `${props.bottom}px` }; // render let btnBacktop; if (state.visibility) { btnBacktop = ( <div class={classes.el} style={styles.el} onClick={handleClick}> { slots.default ? slots.default : ( <div class={classes.elContent}> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1024 1024"> <path d="M772.551111 493.174949c-7.938586 7.951515-18.010505 11.649293-28.069495 11.649293-10.05899 0-20.130909-3.710707-28.069495-11.649293l-165.236363-165.236363v264.261818c0 21.721212-18.010505 39.718788-39.718788 39.718788s-39.718788-17.997576-39.718788-39.718788V327.938586l-165.223435 165.236363c-15.36 15.36-40.77899 15.36-56.138989 0-15.36-15.36-15.36-40.77899 0-56.138989L483.400404 204.024242c15.36-15.36 40.77899-15.36 56.13899 0l233.024646 233.011718c15.347071 15.36 15.347071 40.248889-0.012929 56.138989zM511.469899 733.595152c-20.66101 0-37.598384-16.937374-37.598384-38.128485 0-20.66101 16.937374-38.128485 37.598384-38.128485 20.648081 0 37.598384 16.950303 37.598384 38.128485 0 21.191111-16.950303 38.128485-37.598384 38.128485M511.469899 833.163636c-20.66101 0-37.598384-16.937374-37.598384-38.128484 0-20.66101 16.937374-38.128485 37.598384-38.128485 20.648081 0 37.598384 16.937374 37.598384 38.128485 0 21.178182-16.950303 38.128485-37.598384 38.128484"></path> </svg> </div> ) } </div> ); } return ( <transition appear name={props.animation}> {btnBacktop} </transition> ); } };