/*** * * js媒体查询 * @param opt * @return {{}} * @example: createMediaList({ 480(ctx){ console.log('is 480',ctx) }, 880(ctx){ console.log('is 880',ctx) }, 1220(ctx){ console.log('is 1220',ctx) }, 1440(ctx){ console.log('is 1440',ctx) }, }) * */ import {debounce} from "~/utils/utils"; export function createMediaList(opt) { for (let optKey in opt) { let mediaCtx = window !== undefined ? window.matchMedia(`(max-width: ${optKey}px)`) : global.matchMedia(`(max-width: ${optKey}px)`) if (mediaCtx?.matches) { opt[optKey](mediaCtx) } mediaCtx.addListener(opt[optKey]) } } /** * * 对象转换成css样式变量 * @param obj * @param prefix * @return {{}} */ export function conversionStyleVal(obj, prefix) { let res = {} for (let key in obj) { if (obj[key] instanceof Object) { !prefix ? res[key] = conversionStyleVal(obj[key], key) : Object.assign(res, conversionStyleVal(obj[key], key)) } else { prefix ? res['--' + prefix + key] = obj[key] : res['--' + key] = obj[key] } } return res } /** * 滑动到指定位置触发动画 * 需要放到onMounted使用 * @param {*} tagDom (需要触发的class盒子,可读取子级,一般填最外层盒子) * author: hyw * * 用法: *
* htmlAddAnimations('box') * * 参数说明: * data-animation: 填写需要添加的动画效果class名 (https://animate.style/)(https://blog.csdn.net/a1056244734/article/details/113884374) * op0:除 /可视区域/ 外在class加上此class名 */ export function htmlAddAnimations(opt) { let oTagDomList = opt?.tagDom ? [...document.getElementsByClassName(opt.tagDom)[0].querySelectorAll('*')] : [...document.body.querySelectorAll('*')], domAnimationInfoPool = [] oTagDomList.map((domItem, idx) => { let animationName = domItem.getAttribute('data-animation') if (animationName) { domAnimationInfoPool.push({ dom: domItem, animationName }) } }) let windowScrollEvent = function (e) { for (let i = domAnimationInfoPool.length - 1; i >= 0; i--) { let infoItem = domAnimationInfoPool[i] if (infoItem.dom.getBoundingClientRect().top < window.innerHeight * (opt?.preload || 1)) { infoItem.dom.classList.remove('op0') infoItem.animationName.split(' ').map(item => { if (item) { infoItem.dom.classList.add(item) } }) } else if (opt?.isRe) { infoItem.dom.classList.add('op0') infoItem.animationName.split(' ').map(item => { if (item) { infoItem.dom.classList.remove(item) } }) } } } window.addEventListener('scroll', opt?.openDelay ? debounce(windowScrollEvent,opt?.debounceNumber || 60) : windowScrollEvent, false) windowScrollEvent() } /** * * @param opt * opt:{ * 触发的分辨率:要减少的字体 * } * 需要放到onMounted使用 * @example: * 使用前要在对应的容器加上类名:font-size-box * fontSizeReactive({ * 880:1, * 480:2 * }) * 这里要注意的是,减少的字体是会叠加减少的,例如: * 我初始字体是15px,我的配置项为 * { * 880:1, * 480:2 * },一般来说按照这个配置项的话,我字体在屏幕小于880px的时候会变成14px,在小于480的时候会变成13px * 但实际的话是在小于880的时候会变成14px,小于480的时候会变成12px,也就是会把880也算上 */ export function fontSizeReactive(opt = { 880: 1, 480: 1, }) { return let oBox = document.getElementsByClassName('font-size-box')[0] let tag = oBox ? [...oBox.querySelectorAll('*')] : [...document.querySelectorAll('*')] tag.map(item => { let fontSize = getComputedStyle(item, null)['fontSize'].replace('px', '') item.style.setProperty('font-size', fontSize + 'px') }) let fnTpl = '' for (let key in opt) { fnTpl += ` ${key}(ctx) { if (ctx.matches) { tag.map(item => { item.style.fontSize = item.style.fontSize.replace('px', '') - ${opt[key]} + 'px' }) } else { tag.map(item => { item.style.fontSize = Number(item.style.fontSize.replace('px', '')) + ${opt[key]} + 'px' }) } },` } (new Function('fn,tag', ` fn({ ${fnTpl} }) `))(function (opt) { for (let optKey in opt) { let mediaCtx = window !== undefined ? window.matchMedia(`(max-width: ${optKey}px)`) : global.matchMedia(`(max-width: ${optKey}px)`) if (mediaCtx?.matches) { opt[optKey](mediaCtx) } mediaCtx.addListener(opt[optKey]) } }, tag) } /** * * @param element * @returns {{top: number, left: number}} */ export function getElementPosition(element) { let top = element.offsetTop //这是获取元素距父元素顶部的距离 let left = element.offsetLeft var current = element.offsetParent //这是获取父元素 while (current !== null) { //当它上面有元素时就继续执行 top += current.offsetTop //这是获取父元素距它的父元素顶部的距离累加起来 left += current.offsetLeft current = current.offsetParent //继续找父元素 } return { top, left, } }