UNPKG

lin-view-ui

Version:
585 lines (510 loc) 18 kB
import ResizeObserver from 'resize-observer-polyfill'; import Spinner from './spinner.js'; var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; var fails$2 = function (exec) { try { return !!exec(); } catch (error) { return true; } }; var fails$1 = fails$2; // Detect IE8's incomplete defineProperty implementation var descriptors = !fails$1(function () { // eslint-disable-next-line es/no-object-defineproperty -- required for testing return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7; }); var objectDefineProperty = {}; var check = function (it) { return it && it.Math == Math && it; }; // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 var global$2 = // eslint-disable-next-line es/no-global-this -- safe check(typeof globalThis == 'object' && globalThis) || check(typeof window == 'object' && window) || // eslint-disable-next-line no-restricted-globals -- safe check(typeof self == 'object' && self) || check(typeof commonjsGlobal == 'object' && commonjsGlobal) || // eslint-disable-next-line no-new-func -- fallback (function () { return this; })() || Function('return this')(); var isObject$3 = function (it) { return typeof it === 'object' ? it !== null : typeof it === 'function'; }; var global$1 = global$2; var isObject$2 = isObject$3; var document$1 = global$1.document; // typeof document.createElement is 'object' in old IE var EXISTS = isObject$2(document$1) && isObject$2(document$1.createElement); var documentCreateElement = function (it) { return EXISTS ? document$1.createElement(it) : {}; }; var DESCRIPTORS$2 = descriptors; var fails = fails$2; var createElement = documentCreateElement; // Thank's IE8 for his funny defineProperty var ie8DomDefine = !DESCRIPTORS$2 && !fails(function () { // eslint-disable-next-line es/no-object-defineproperty -- requied for testing return Object.defineProperty(createElement('div'), 'a', { get: function () { return 7; } }).a != 7; }); var isObject$1 = isObject$3; var anObject$1 = function (it) { if (!isObject$1(it)) { throw TypeError(String(it) + ' is not an object'); } return it; }; var isObject = isObject$3; // `ToPrimitive` abstract operation // https://tc39.es/ecma262/#sec-toprimitive // instead of the ES6 spec version, we didn't implement @@toPrimitive case // and the second argument - flag - preferred type is a string var toPrimitive$1 = function (input, PREFERRED_STRING) { if (!isObject(input)) return input; var fn, val; if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val; if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val; if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val; throw TypeError("Can't convert object to primitive value"); }; var DESCRIPTORS$1 = descriptors; var IE8_DOM_DEFINE = ie8DomDefine; var anObject = anObject$1; var toPrimitive = toPrimitive$1; // eslint-disable-next-line es/no-object-defineproperty -- safe var $defineProperty = Object.defineProperty; // `Object.defineProperty` method // https://tc39.es/ecma262/#sec-object.defineproperty objectDefineProperty.f = DESCRIPTORS$1 ? $defineProperty : function defineProperty(O, P, Attributes) { anObject(O); P = toPrimitive(P, true); anObject(Attributes); if (IE8_DOM_DEFINE) try { return $defineProperty(O, P, Attributes); } catch (error) { /* empty */ } if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported'); if ('value' in Attributes) O[P] = Attributes.value; return O; }; var DESCRIPTORS = descriptors; var defineProperty = objectDefineProperty.f; var FunctionPrototype = Function.prototype; var FunctionPrototypeToString = FunctionPrototype.toString; var nameRE = /^\s*function ([^ (]*)/; var NAME = 'name'; // Function instances `.name` property // https://tc39.es/ecma262/#sec-function-instances-name if (DESCRIPTORS && !(NAME in FunctionPrototype)) { defineProperty(FunctionPrototype, NAME, { configurable: true, get: function () { try { return FunctionPrototypeToString.call(this).match(nameRE)[1]; } catch (error) { return ''; } } }); } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var script = { name: "LinScrollBar", components: _defineProperty({}, Spinner.name, Spinner), props: { // 是否一直显示自定义滚动条 hover: { type: Boolean, default: false }, // 高度 height: { type: String, default: "100%" }, // 宽度 width: { type: String, default: "100%" }, // 最大高度 maxHeight: { type: String }, // 最小高度 minHeight: { type: String }, // 是否正在加载,显示加载动画 loading: { type: Boolean, default: false }, // 加载文案 loadingText: String, // 加载器大小 loadingSize: String }, data: function data() { return { // 自定义滚动条高度 barHeight: 0, // 自定义滚动条距离顶部距离 barTop: 0, // 是否显示滚动条 showBar: false, // 鼠标悬浮在容器中时候显示自定义滚动条 hoverBar: false }; }, mounted: function mounted() { // 内容容器高度 this.wrapperHeight = 0; // 内容高度 this.contentHeight = 0; // this.barWrapperHeight = 0; // 自定义滚动条一开始所在位置 this.startY = 0; // 观察DOM元素变化实例对象 this.observer = null; // 标志位,鼠标是否可以进行移动了(能否拖拽) this.isMove = false; // 鼠标是否离开容器 this.isLeave = false; // 初始化 this.init(); // 初始化DOM观察 this.initObserver(); }, methods: { initObserver: function initObserver() { var _this = this; // DOM元素大小(宽高)发生变化的时候 this.observer = new ResizeObserver(function () { _this.init(); }); this.observer.observe(this.$refs.content); }, init: function init() { this.initDom(); this.initBar(); }, // 获取相关DOM元素高度 initDom: function initDom() { this.wrapperHeight = this.$refs.wrapper.clientHeight; this.contentHeight = this.$refs.content.clientHeight; }, // 初始化自定义滚动条 initBar: function initBar() { var wrapperHeight = this.wrapperHeight, contentHeight = this.contentHeight; // const { contentHeight } = this; // 求 滚动条的高度 if (wrapperHeight / contentHeight < 1) { // 内容高度大于容器高度 // 滚动条高度/容器高度 = 容器高度/内容高度 this.barHeight = wrapperHeight / contentHeight * wrapperHeight; // 此时需要显示自定义滚动条 this.showBar = true; } else { this.showBar = false; } if (this.showBar) { // 如果需要显示自定义滚动条,要初始化滚动条的位置 var scrollTop = this.$refs.wrapper.scrollTop; // 算出自定义滚动条,相对于容器的y轴位置 var percent = scrollTop / contentHeight; var barTop = percent * wrapperHeight; this.barTop = barTop; } }, // 监听容器的滚动事件 onWrapperScroll: function onWrapperScroll(event) { var contentHeight = this.contentHeight, wrapperHeight = this.wrapperHeight; // const { wrapperHeight } = this; var scrollTop = event.target.scrollTop; // 算出自定义滚动条,相对于容器的y轴位置 var percent = scrollTop / (contentHeight - wrapperHeight); var barTop = percent * (wrapperHeight - this.barHeight); this.barTop = barTop; this.$emit("scroll", event); if (scrollTop + wrapperHeight >= contentHeight) { // 滚动到底部 this.$emit("scrollToBottom", event); } }, // 鼠标按下事件 onMouseDown: function onMouseDown(event) { // 标志位 this.isMove = true; // 给body添加样式,不能让鼠标在移动的时候选中文字,否则会造成鼠标抬起事件丢失 document.getElementsByTagName("body")[0].classList.add("user-no-select"); // 记录鼠标点击的初始位置 this.startY = event.clientY; // 监听鼠标移动事件和抬起事件 document.addEventListener("mousemove", this.onMousemove); document.addEventListener("mouseup", this.onMouseup); }, // 鼠标移动事件 onMousemove: function onMousemove(event) { // 纵轴坐标 var topY = event.clientY - this.startY; // 计算自定义滚动条应该距离顶部多少 var barTop = this.$refs.bar.offsetTop + topY; // 更新位置 this.updatePosition(barTop); this.startY = event.clientY; }, // 鼠标抬起事件 onMouseup: function onMouseup() { // 标志位,此时应该不能再进行拖拽了 this.isMove = false; if (this.isLeave) { this.hoverBar = false; } // 取消鼠标按下时添加的样式 document.getElementsByTagName("body")[0].classList.remove("user-no-select"); // 注销事件 document.removeEventListener("mousemove", this.onMousemove); document.removeEventListener("mouseup", this.onMouseup); }, updatePosition: function updatePosition(barTop) { var wrapperHeight = this.wrapperHeight, contentHeight = this.contentHeight; // const { contentHeight } = this; var barHeight = this.$refs.bar.clientHeight; // 边界情况处理 if (barTop >= wrapperHeight - barHeight) { barTop = wrapperHeight - barHeight; } if (barTop <= 0) { barTop = 0; } this.barTop = barTop; // 自定义滚动条位置发生了变化,容器也要相对应进行移动 var percent = barTop / wrapperHeight; var contentTop = percent * contentHeight; this.$refs.wrapper.scrollTop = contentTop; }, // 鼠标进入事件 onMouseEnter: function onMouseEnter() { this.hoverBar = true; this.isLeave = false; }, // 鼠标离开事件 onMouseLeave: function onMouseLeave() { this.isLeave = true; if (!this.isMove) { this.hoverBar = false; } }, // 点击自定义滚动条 onBarWrapperClick: function onBarWrapperClick(event) { // 获取点击位置 var clientY = event.clientY; // 获取容器距离页面的距离 var marginTop = this.$refs.wrapper.getBoundingClientRect().top; // 计算出鼠标点击的位置距离容器顶部的距离,this.barHeight / 2 是为了让滚动条移动后,鼠标位于滚动条中间 this.updatePosition(clientY - marginTop - this.barHeight / 2); } }, computed: { // 根节点样式 style: function style() { var style = {}; if (this.height) { style.height = this.height; } if (this.maxHeight) { style["max-height"] = this.maxHeight; } if (this.minHeight) { style["min-height"] = this.minHeight; } return style; } }, beforeDestroy: function beforeDestroy() { if (this.observer) { this.observer.disconnect(); this.observer = null; } document.removeEventListener("mousemove", this.onMousemove); document.removeEventListener("mouseup", this.onMouseup); } }; function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { if (typeof shadowMode !== 'boolean') { createInjectorSSR = createInjector; createInjector = shadowMode; shadowMode = false; } // Vue.extend constructor export interop. const options = typeof script === 'function' ? script.options : script; // render functions if (template && template.render) { options.render = template.render; options.staticRenderFns = template.staticRenderFns; options._compiled = true; // functional template if (isFunctionalTemplate) { options.functional = true; } } // scopedId if (scopeId) { options._scopeId = scopeId; } let hook; if (moduleIdentifier) { // server build hook = function (context) { // 2.3 injection context = context || // cached call (this.$vnode && this.$vnode.ssrContext) || // stateful (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional // 2.2 with runInNewContext: true if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { context = __VUE_SSR_CONTEXT__; } // inject component styles if (style) { style.call(this, createInjectorSSR(context)); } // register component module identifier for async chunk inference if (context && context._registeredComponents) { context._registeredComponents.add(moduleIdentifier); } }; // used by ssr in case component is cached and beforeCreate // never gets called options._ssrRegister = hook; } else if (style) { hook = shadowMode ? function (context) { style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot)); } : function (context) { style.call(this, createInjector(context)); }; } if (hook) { if (options.functional) { // register for functional component in vue file const originalRender = options.render; options.render = function renderWithStyleInjection(h, context) { hook.call(context); return originalRender(h, context); }; } else { // inject component registration as beforeCreate hook const existing = options.beforeCreate; options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; } } return script; } /* script */ const __vue_script__ = script; /* template */ var __vue_render__ = function() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "div", { staticClass: "lin-scroll-bar", style: Object.assign({}, _vm.style, { width: _vm.width }), on: { mouseenter: _vm.onMouseEnter, mouseleave: _vm.onMouseLeave } }, [ _c( "div", { ref: "wrapper", staticClass: "lin-scroll-bar-wrapper", style: _vm.style, on: { scroll: _vm.onWrapperScroll } }, [ _c( "div", { ref: "content", staticClass: "lin-scroll-bar-content" }, [ _vm._t("default"), _vm._v(" "), _vm.loading ? _c( "div", { staticClass: "lin-scroll-bar-spinner" }, [ _vm._t("loading", function() { return [ _c("lin-spinner", { attrs: { text: _vm.loadingText, size: _vm.loadingSize } }) ] }) ], 2 ) : _vm._e() ], 2 ) ] ), _vm._v(" "), _vm.showBar ? _c( "div", { staticClass: "lin-srcoll-bar-barwrapper", on: { click: _vm.onBarWrapperClick } }, [ _c("div", { directives: [ { name: "show", rawName: "v-show", value: _vm.hoverBar || _vm.hover, expression: "hoverBar || hover" } ], ref: "bar", staticClass: "lin-srcoll-bar-bar", style: { height: _vm.barHeight + "px", top: _vm.barTop + "px" }, on: { mousedown: _vm.onMouseDown } }) ] ) : _vm._e() ] ) }; var __vue_staticRenderFns__ = []; __vue_render__._withStripped = true; /* style */ const __vue_inject_styles__ = undefined; /* scoped */ const __vue_scope_id__ = undefined; /* module identifier */ const __vue_module_identifier__ = undefined; /* functional template */ const __vue_is_functional_template__ = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ const __vue_component__ = /*#__PURE__*/normalizeComponent( { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, false, undefined, undefined, undefined ); __vue_component__.install = function (Vue) { return Vue.component(__vue_component__.name, __vue_component__); }; export default __vue_component__;