v-antm

useAnimationList.ts

javascript 复制代码
import { ref } from 'vue'

export interface Timedtask {
  time: number
  method: (...arg: any[]) => void
}

const binaryInsert = (arr: { key: number; time: number }[], value: number) => {
  let left = 0
  let right = arr.length - 1
  let item: { key: number; time: number } = { key: 0, time: 0 }
  while (left <= right) {
    const mid = Math.floor((left + right) / 2)
    if (arr[mid].time === value) {
      item = { key: mid, time: value }
      arr.splice(mid, 0, item) // 如果找到相同的值,插入在该位置
      return item
    } else if (arr[mid].time < value) {
      left = mid + 1 // 在右半部分继续查找
    } else {
      right = mid - 1 // 在左半部分继续查找
    }
  }
  item = { key: left, time: value }
  arr.splice(left, 0, item) // 如果未找到相同的值,插入在合适的位置
  return item
}

export const animationList = () => {
  const tiskNumArray: { key: number; time: number }[] = []
  const tiskArray = new Map<any, Timedtask>()
  let intervalIndex: number | null = null
  let timeNum = 0
  const implementMethod = (item: (typeof tiskNumArray)[0]) => {
    const method = tiskArray.get(item)?.method
    console.log('执行', item.time, tiskNumArray)

    method && method()
    tiskArray.delete(item)
    tiskNumArray.shift()
    if (tiskNumArray.length === 0) clearIntervalM()
  }
  const clearIntervalM = () => {
    timeNum = 0
    intervalIndex && clearInterval(intervalIndex)
    intervalIndex = null
  }
  const diffTimeValue = (timeNum: number) => {
    if (timeNum >= tiskNumArray[0].time) {
      implementMethod(tiskNumArray[0])
      tiskNumArray.length > 0 && diffTimeValue(timeNum)
    }
  }
  const initInterval = () => {
    if (intervalIndex === null) {
      diffTimeValue(timeNum)
      intervalIndex = setInterval(() => {
        timeNum += 100
        diffTimeValue(timeNum)
      }, 100)
    }
  }

  const setTimedtask = (time: number, method: (...arg: any[]) => void) => {
    let index = 0
    let value = { key: index, time }
    if (tiskNumArray.length === 0) tiskNumArray.push(value)
    else {
      value = binaryInsert(tiskNumArray, time)
    }
    tiskArray.set(value, { time, method })
    if (tiskNumArray.length !== 0) initInterval()
  }

  return {
    setTimedtask
  }
}

directives.ts

javascript 复制代码
import { animationList } from './useAnimationList'

const { setTimedtask } = animationList()

function callback(entries: any) {
  for (let i of entries) {
    if (i.isIntersecting) {
      let img = i.target
      let trueSrc = img.getAttribute('data-src')
      img.setAttribute('src', trueSrc)
      observer?.unobserve(img)
    }
  }
}
let observer: IntersectionObserver | null = null
try {
  observer = new IntersectionObserver(callback)
} catch (error) {
  observer = null
}

export const LazyImg = {
  beforeMount(el: Element, binding: { value: boolean }) {
    if (!observer || binding.value === false) return
    let trueSrc = el.getAttribute('src')
    el.setAttribute('src', null as unknown as string)
    el.setAttribute('data-src', trueSrc as string)
    observer.observe(el)
  },
  beforeUnmount(el: Element) {
    observer?.unobserve(el)
  }
}
const antmBindingObjs: { [key: number]: antmType } = {}
function antmCallback(entries: any) {
  for (let i of entries) {
    if (i.isIntersecting) {
      antmObserver?.unobserve(i.target)
      const uuid: number = Number(i.target.getAttribute('antm-id'))
      if (antmBindingObjs[uuid].child_node === true) {
        const flag = typeof antmBindingObjs[uuid].time === 'number'
        i.target.childNodes.forEach((childNode: any, index: number) => {
          setTimedtask(
            flag
              ? (antmBindingObjs[uuid].time as number) * ++index
              : (antmBindingObjs[uuid].time as number[])[index],
            () => {
              childNode.classList.add(antmBindingObjs[uuid].after)
              if (antmBindingObjs[uuid].opacity) childNode.style.opacity = 1
            }
          )
        })
      } else
        setTimedtask((antmBindingObjs[uuid].time as number[])[0], () => {
          i.target.classList.add(antmBindingObjs[uuid].after)
          if (antmBindingObjs[uuid].opacity) i.target.style.opacity = 1
        })
    }
  }
}
let antmObserver: IntersectionObserver | null = null
try {
  antmObserver = new IntersectionObserver(antmCallback)
} catch (error) {
  antmObserver = null
}
const initBinding = (value: number | antmType) => {
  const initObj = {
    time: [0],
    child_node: false,
    before: '',
    after: 'animation_start',
    opacity: true
  }
  if (typeof value === 'number') {
    initObj.time = [value]
    return initObj
  } else
    return {
      ...initObj,
      ...value,
      time: typeof value.time === 'number' && !value.child_node ? [value.time] : value.time
    }
}
export interface antmType {
  time: number | number[] //当child_node 为true的时候 值为间隔
  child_node?: boolean //是否将所有子节点加入
  before?: string | string[] //触发前 class
  after?: string | string[] //触发后 class
  opacity?: boolean //触发前透明
}

let uuid: number = 0
export const antm = {
  beforeMount(el: Element, binding: { value: number | antmType }) {
    const bindingM = initBinding(binding.value)
    antmBindingObjs[uuid] = bindingM
    if (bindingM.child_node)
      bindingM.opacity &&
        el.childNodes.forEach((childNode: any) => {
          childNode.style.opacity = 0
        })
    else bindingM.opacity && (el.style.opacity = 0)
    el.setAttribute('antm-id', uuid as unknown as string)
    ++uuid
    antmObserver?.observe(el)
  },
  beforeUnmount(el: Element) {
    antmObserver?.unobserve(el)
  }
}

transition.scss

javascript 复制代码
/* fade */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.28s;
}

.fade-enter,
.fade-leave-active {
  opacity: 0;
}

/* fade-transform */
.fade-transform-leave-active,
.fade-transform-enter-active {
  transition: all 0.3s;
}

.fade-transform-enter-from {
  opacity: 0;
  transform: translateX(-30px);
}

.fade-transform-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

/* breadcrumb transition */
.breadcrumb-enter-active {
  transition: all 0.4s;
}

.breadcrumb-leave-active {
  position: absolute;
  transition: all 0.3s;
}

.breadcrumb-enter-from,
.breadcrumb-leave-active {
  opacity: 0;
  transform: translateX(20px);
}

/**
 * @description 重置el-menu的展开收起动画时长
 */
.outer-most .el-collapse-transition-leave-active,
.outer-most .el-collapse-transition-enter-active {
  transition: 0.2s all ease-in-out !important;
}

.horizontal-collapse-transition {
  transition: var(--pure-transition-duration) all !important;
}

@keyframes downUp {
  0% {
    opacity: 0;
    transform: translateY(calc(100% + 400px));
  }

  30% {
    transform: translateY(-30px);
  }

  60% {
    transform: translateY(10px);
  }

  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

.animation_start {
  animation: downUp 2s;
}


@keyframes animation_left {
  0% {
    opacity: 0;
    transform: translateX(calc(-100% - 400px));
  }

  100% {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes animation_right {
  0% {
    opacity: 0;
    transform: translateX(calc(100% + 400px));
  }

  100% {
    opacity: 1;
    transform: translateX(0);
  }
}

.animation_left {
  animation: animation_left 1s;
}

.animation_right {
  animation: animation_right 1s;
}

main

javascript 复制代码
app.directive('lazy', LazyImg)
app.directive('antm', antm)

App.vue

javascript 复制代码
 <div v-antm="{time: 100,child_node: true}"></div>
相关推荐
理想不理想v几秒前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云10 分钟前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:1379712058713 分钟前
web端手机录音
前端
齐 飞18 分钟前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
神仙别闹35 分钟前
基于tensorflow和flask的本地图片库web图片搜索引擎
前端·flask·tensorflow
aPurpleBerry1 小时前
JS常用数组方法 reduce filter find forEach
javascript
GIS程序媛—椰子1 小时前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_0012 小时前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端2 小时前
Content Security Policy (CSP)
前端·javascript·面试
乐闻x2 小时前
ESLint 使用教程(一):从零配置 ESLint
javascript·eslint