/***
*
* 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,
}
}