UNPKG

drip-ui

Version:

Lightweight Mobile UI Components built on Vue

291 lines (249 loc) 9.81 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import create from '../utils/create-basic'; var HtmlFontSize = document.documentElement.style.fontSize || 37.5; // 获取当前HTML的字体大小 var getNumber = parseFloat(HtmlFontSize); // 获取浮点数 var cardinalNumber = 750 / (getNumber * 10); // 算出图纸和真机之间的系数 var defaultCoefficient = +parseFloat(20 / cardinalNumber).toFixed(2); // 左右边距 var dialogMargin = +parseFloat(26 / cardinalNumber).toFixed(2) * 1; // 上下边距 var documentW = document.documentElement.clientWidth; // 获取浏览器的宽 var documentH = document.documentElement.clientHeight; // 获取浏览器的高 export default create({ render: function render() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "risk-desc" }, [_c('div', { staticClass: "risk-desc-wrap" }, [_c('span', { ref: "iconMark", staticClass: "risk-desc-iconSize", on: { "click": _vm.tooltipShow } }, [_vm._t("icon", [_c('img', { attrs: { "src": "//store.sdbao.com/product/detail/riskDescMark.png" } })])], 2), _c('div', { directives: [{ name: "show", rawName: "v-show", value: _vm.visible, expression: "visible" }], ref: "icon", staticClass: "risk-desc-icon", "class": !_vm.isAuto ? "risk-desc-icon-" + _vm.type : '', style: _extends({}, _vm.iconStyle, { borderColor: "transparent transparent " + _vm.backgroundColor }) }), _c('div', { directives: [{ name: "show", rawName: "v-show", value: _vm.visible, expression: "visible" }], ref: "tooltip", staticClass: "risk-desc-container", "class": !_vm.isAuto ? "risk-desc-container-" + _vm.type : '', style: _extends({}, _vm.dialogDescStyle, { backgroundColor: _vm.backgroundColor }) }, [_vm._t("container")], 2)])]); }, name: 'tooltip', props: { visible: { type: Boolean, "default": false }, type: { type: String, "default": 'auto' }, backgroundColor: { type: String, "default": '#fff' } }, data: function data() { return { isdiff: false, dialogDescStyle: {}, iconStyle: {}, tooltipLocation: {}, // 弹框数据 tooltipIcon: {} }; }, computed: { isAuto: function isAuto() { var type = ['top', 'right', 'bottom', 'left']; return !type.includes(this.type); } }, watch: { // 当弹框隐藏的时候初始化方便下次计算 visible: function visible(_visible) { if (!_visible) { this.initDom(); } } }, mounted: function mounted() { var _this = this; this.listenerDescMark = this.throttle(function (e) { // 如果是false 就不计算了 if (!_this.visible) return; // 判断当前点击 var isParentClassName = _this.getParentName(e.target, 'risk-desc'); if (!isParentClassName) { _this.$emit('update:visible', false); } }, 100, {}, this); this.tooltipShow = this.throttle(this.tooltipShow, 100, {}, this); document.addEventListener('click', this.listenerDescMark); }, methods: { init: function init() { if (!this.isAuto) return; var dom = this.$refs.tooltip; // 获取弹框dom var iconDom = this.$refs.icon; // 获取小三角的dom this.tooltipLocation = dom.getBoundingClientRect(); this.tooltipIcon = iconDom.getBoundingClientRect(); // 获取小三角距离左上角个个参数 this.iconMarkWidth = this.$refs.iconMark.offsetWidth; // 获取问号的宽 this.iconMarkHeight = this.$refs.iconMark.offsetHeight; // 获取问号的高 this.bottomFlag = documentH - dialogMargin < this.tooltipLocation.top + this.tooltipLocation.height * 2; // 底部判断如果弹框超出当前底部视口 this.riskDescX = -defaultCoefficient; // 弹框初始化 translateX的距离 this.riskDescY = this.tooltipLocation.height + dialogMargin; // 弹框初始化 translateY的距离 this.iconX = this.iconMarkWidth / 2 - this.tooltipIcon.width / 2; // ?icon的宽度一半 减去 方框一半的宽度 this.iconY = dialogMargin; // 方框距离问号的距离 this.rotate = 'rotate(0deg)'; this.auto(); }, autoLeftRight: function autoLeftRight() { if (this.tooltipLocation.right + defaultCoefficient > documentW) { // 弹框右边超出 this.riskDescX = documentW - this.tooltipLocation.right - defaultCoefficient; // 浏览器宽度 减去 弹框右边距离浏览器左上角的距离 就是超出的距离 再减去 右边距离 就是弹框偏移量 } else if (this.tooltipLocation.left <= defaultCoefficient) { this.riskDescX = -this.tooltipLocation.left + defaultCoefficient; // 左边超出的距离 加上左边距 就是弹框偏移量 } }, auto: function auto() { this.autoLeftRight(); if (this.bottomFlag) { // 是否超出当前窗口底部 this.riskDescY = -this.iconMarkHeight - dialogMargin; // 问号高度 减去当前上边距 就是弹框偏移量 this.iconY = -this.iconMarkHeight - dialogMargin + this.tooltipIcon.height; this.rotate = 'rotate(180deg)'; } this.setPositon(); }, setPositon: function setPositon() { this.dialogDescStyle = { transform: "translate3D(" + this.riskDescX + "px, " + this.riskDescY + "px, 0)" }; this.iconStyle = { transform: "translate3D(" + this.iconX + "px, " + this.iconY + "px, 0) " + this.rotate }; }, /** * underscore 节流函数,返回函数连续调用时,func 执行频率限定为 次 / wait * * @param {function} func 回调函数 * @param {number} wait 表示时间窗口的间隔 * @param {object} options 如果想忽略开始函数的的调用,传入{leading: false}。 * 如果想忽略结尾函数的调用,传入{trailing: false} * 两者不能共存,否则函数不能执行 * @return {function} 返回客户调用函数 */ throttle: function throttle(func, wait, options, ctx) { var context, args, result; var timeout = null; // 之前的时间戳 var previous = 0; // 如果 options 没传则设为空对象 if (!options) options = {}; // 定时器回调函数 var later = function later() { // 如果设置了 leading,就将 previous 设为 0 // 用于下面函数的第一个 if 判断 previous = options.leading === false ? 0 : +new Date(); // 置空一是为了防止内存泄漏,二是为了下面的定时器判断 timeout = null; result = func.apply(context, args); if (!timeout) context = args = null; }; return function () { // 获得当前时间戳 var now = +new Date(); // 首次进入前者肯定为 true // 如果需要第一次不执行函数 // 就将上次时间戳设为当前的 // 这样在接下来计算 remaining 的值时会大于0 if (!previous && options.leading === false) previous = now; // 计算剩余时间 var remaining = wait - (now - previous); context = ctx; args = arguments; // 如果当前调用已经大于上次调用时间 + wait // 或者用户手动调了时间 // 如果设置了 trailing,只会进入这个条件 // 如果没有设置 leading,那么第一次会进入这个条件 // 还有一点,你可能会觉得开启了定时器那么应该不会进入这个 if 条件了 // 其实还是会进入的,因为定时器的延时 // 并不是准确的时间,很可能你设置了2秒 // 但是他需要2.2秒才触发,这时候就会进入这个条件 if (remaining <= 0 || remaining > wait) { // 如果存在定时器就清理掉否则会调用二次回调 if (timeout) { clearTimeout(timeout); timeout = null; } previous = now; result = func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && options.trailing !== false) { // 判断是否设置了定时器和 trailing // 没有的话就开启一个定时器 // 并且不能不能同时设置 leading 和 trailing timeout = setTimeout(later, remaining); } return result; }; }, initDom: function initDom() { this.dialogDescStyle = { transform: '' }; this.iconStyle = { transform: '' }; }, // 弹框显示 tooltipShow: function tooltipShow() { var _this2 = this; this.$emit('change'); this.$nextTick(function () { if (!_this2.visible) return; _this2.init(); }); }, /** * 判断当前元素祖父元素是否有某个class * @param {obj} 子元素 * @param {name} 祖父元素className */ getParentName: function getParentName(obj, name) { var parentNodes = obj; var flag = false; while (parentNodes) { if (parentNodes.className && parentNodes.className.split(' ').includes(name)) { flag = true; parentNodes = null; } else { parentNodes = parentNodes.parentNode; } } return flag; } }, destroyed: function destroyed() { document.removeEventListener('click', this.listenerDescMark); } });