逛掘金很久了一直没发文,今天来分享一下最近封装的一个方法
应用场景是有个类似购物车的按钮悬挂在屏幕上,然后点击物品加入购物车,会把物品所在的这一块收缩抛到按钮那去
直接上代码
/**
* 将一个元素抛到试题篮
* @param el [必传]目标元素,一般是触发点击事件的元素👉(e.currentTarget)
* @param options 配置参数
*/
export default function throwToBasket(el, options = {}) {
/**
* top:要抛到的位置的top
* left:要抛到的位置的left
* targetFatherSelector:如果你是要从el向上查到指定父级就把父级选择器传过来
*/
const TIMEOUT = 700
const {
top = '400px',
left = 'calc(100vw - 36px)',
targetFatherSelector = ''
} = options
let targetEl
if (targetFatherSelector) {
targetEl = el?.closest(targetFatherSelector) ?? el
} else {
targetEl = el
}
const { top: originTop, left: originLeft } = targetEl.getBoundingClientRect()
const { height, width } = targetEl.parentNode.getBoundingClientRect()
let tempEl = targetEl.cloneNode(true)
tempEl.style.margin = 0
tempEl.style.position = 'static'
let div = document.createElement('div')
div.style.height = height + 'px'
div.style.width = width + 'px'
div.style.position = 'fixed'
div.style.top = `${originTop}px`
div.style.left = `${originLeft}px`
div.style.transform = 'translate(0, 0) scale(1)'
div.style.transition = `transform ${TIMEOUT}ms ease-out, top ${TIMEOUT}ms ${originTop < parseInt(top) ? 'ease-in' : 'cubic-bezier(.31,1.24,.86,1.7)'}, left ${TIMEOUT}ms linear`
div.style.zIndex = 9999
div.style.opacity = 1
div.appendChild(tempEl)
document.body.appendChild(div)
let ob
try {
// 监听被添加到页面上
ob = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
startAnimation()
}
})
},
{
root: div,
threshold: 0
}
)
ob.observe(tempEl)
} catch {
setTimeout(() => {
startAnimation()
}, 100)
}
function startAnimation() {
div.style.top = top
div.style.left = left
div.style.transform = 'translate(-50%, -50%) scale(.05)'
setTimeout(() => {
document.body.removeChild(div)
tempEl = null
div = null
ob = null
}, TIMEOUT + 10)
}
}
内网复制到外网好累,不知道有没有缺胳膊少腿