工具方法:将一个元素抛到指定位置

172 阅读1分钟

逛掘金很久了一直没发文,今天来分享一下最近封装的一个方法

应用场景是有个类似购物车的按钮悬挂在屏幕上,然后点击物品加入购物车,会把物品所在的这一块收缩抛到按钮那去

直接上代码

/**
 * 将一个元素抛到试题篮
 * @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)
    }
}

内网复制到外网好累,不知道有没有缺胳膊少腿