feat: add wave effect

This commit is contained in:
aibayanyu 2023-03-18 21:16:41 +08:00
parent 69388270af
commit 9243370f1c
3 changed files with 84 additions and 7 deletions

View File

@ -20,7 +20,7 @@ const Wave = defineComponent({
const [, hashId] = useStyle(prefixCls)
const showWave = useWave(
containerRef,
computed(() => classNames(prefixCls, hashId))
computed(() => classNames(prefixCls.value, hashId.value))
)
const onClick = (e: MouseEvent) => {

View File

@ -1,15 +1,91 @@
import type { ComputedRef, Ref } from 'vue'
import { unrefElement } from '@vueuse/core'
import { defineComponent, render } from 'vue'
import { objectType } from '@v-c/utils'
import { unrefElement, useResizeObserver } from '@vueuse/core'
import { computed, defineComponent, onMounted, render, shallowRef, toRef } from 'vue'
import { classNames, delayTimer, objectType, safeNextick, useState } from '@v-c/utils'
import { getTargetWaveColor } from './util'
function validateNum(value: number) {
return Number.isNaN(value) ? 0 : value
}
export const WaveEffect = defineComponent({
name: 'WaveEffect',
props: {
target: objectType<HTMLElement>()
},
setup() {
return () => null
setup(props, { attrs }) {
const divRef = shallowRef<HTMLDivElement | undefined>(undefined)
const [color, setWaveColor] = useState<string | null>(null)
const [borderRadius, setBorderRadius] = useState<number[]>([])
const [left, setLeft] = useState(0)
const [top, setTop] = useState(0)
const [width, setWidth] = useState(0)
const [height, setHeight] = useState(0)
const [enabled, setEnabled] = useState(false)
const [active, setActive] = useState(false)
const waveStyle = computed(() => {
const style: Record<string, any> = {
left: `${left.value}px`,
top: `${top.value}px`,
width: `${width.value}px`,
height: `${height.value}px`,
borderRadius: borderRadius.value.map(radius => `${radius}px`).join(' ')
}
if (color.value) {
style['--wave-color'] = color.value
}
return style
})
function syncPos() {
const { target } = props
const nodeStyle = getComputedStyle(target)
// Get wave color from target
setWaveColor(getTargetWaveColor(target))
const isStatic = nodeStyle.position === 'static'
// Rect
const { borderLeftWidth, borderTopWidth } = nodeStyle
setLeft(isStatic ? target.offsetLeft : validateNum(-parseFloat(borderLeftWidth)))
setTop(isStatic ? target.offsetTop : validateNum(-parseFloat(borderTopWidth)))
setWidth(target.offsetWidth)
setHeight(target.offsetHeight)
// Get border radius
const { borderTopLeftRadius, borderTopRightRadius, borderBottomLeftRadius, borderBottomRightRadius } = nodeStyle
setBorderRadius([borderTopLeftRadius, borderTopRightRadius, borderBottomRightRadius, borderBottomLeftRadius].map(radius => validateNum(parseFloat(radius))))
}
onMounted(async () => {
syncPos()
setEnabled(true)
await safeNextick()
setActive(true)
await delayTimer(5000)
const holder = divRef.value?.parentElement
holder!.parentElement?.removeChild(holder!)
})
const motionClassName = computed(() =>
classNames({
'wave-motion-appear': enabled.value,
'wave-motion': true
})
)
const motionClassNameActive = computed(() => ({
'wave-motion-appear-active': active.value
}))
useResizeObserver(toRef(props, 'target'), syncPos)
return () => {
if (!enabled.value) return null
return (
<div
ref={divRef}
class={[attrs.class, motionClassName.value, motionClassNameActive.value]}
style={waveStyle.value}
/>
)
}
}
})

View File

@ -12,6 +12,7 @@ title: 基础按钮
<template>
<div>
<a-button>这是按钮</a-button>
<div style="height: 10px"></div>
</div>
</template>