mirror of
https://github.com/antd-tiny-vue/antd-tiny-vue.git
synced 2024-11-10 09:39:15 +08:00
feat: add wave effect
This commit is contained in:
parent
69388270af
commit
9243370f1c
@ -20,7 +20,7 @@ const Wave = defineComponent({
|
|||||||
const [, hashId] = useStyle(prefixCls)
|
const [, hashId] = useStyle(prefixCls)
|
||||||
const showWave = useWave(
|
const showWave = useWave(
|
||||||
containerRef,
|
containerRef,
|
||||||
computed(() => classNames(prefixCls, hashId))
|
computed(() => classNames(prefixCls.value, hashId.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
const onClick = (e: MouseEvent) => {
|
const onClick = (e: MouseEvent) => {
|
||||||
|
@ -1,15 +1,91 @@
|
|||||||
import type { ComputedRef, Ref } from 'vue'
|
import type { ComputedRef, Ref } from 'vue'
|
||||||
import { unrefElement } from '@vueuse/core'
|
import { unrefElement, useResizeObserver } from '@vueuse/core'
|
||||||
import { defineComponent, render } from 'vue'
|
import { computed, defineComponent, onMounted, render, shallowRef, toRef } from 'vue'
|
||||||
import { objectType } from '@v-c/utils'
|
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({
|
export const WaveEffect = defineComponent({
|
||||||
name: 'WaveEffect',
|
name: 'WaveEffect',
|
||||||
props: {
|
props: {
|
||||||
target: objectType<HTMLElement>()
|
target: objectType<HTMLElement>()
|
||||||
},
|
},
|
||||||
setup() {
|
setup(props, { attrs }) {
|
||||||
return () => null
|
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}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ title: 基础按钮
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<a-button>这是按钮</a-button>
|
<a-button>这是按钮</a-button>
|
||||||
|
<div style="height: 10px"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user