Skip to content

Commit

Permalink
fix: 修复 f-collapse-animation 组件初始展开关闭时动画失效的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyh2001 committed Jun 16, 2023
1 parent 0d30bf3 commit f8b0713
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 181 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- 新增 `f-dialog` 组件 `mask-background` `mask-opacity` `show-header` 配置项
- 新增 `f-drawer` 组件 `mask-background` `mask-opacity` `show-header` 配置项
- 修复 `f-up-load` 继续多选重置之前文件的问题
- 修复 `f-collapse-animation` 组件初始展开关闭时动画失效的问题

## 0.41.0 (2023-06-04)

Expand Down
1 change: 1 addition & 0 deletions packages/fighting-design/_hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ export * from './use-count-down'
export * from './use-trigger'
export * from './use-form-check'
export * from './use-transition'
export * from './use-collapse-animation'
126 changes: 126 additions & 0 deletions packages/fighting-design/_hooks/use-collapse-animation/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { computed } from 'vue'
import { isNumber } from '../../_utils'
import { useRun } from '..'
import type { CollapseAnimationProps } from '../../collapse-animation'

export interface UseCollapseAnimationReturn {
after: (el: Element) => void
before: (el: Element) => void
ing: (el: Element) => void
}

const { run } = useRun()

export const useCollapseAnimation = (prop: CollapseAnimationProps): UseCollapseAnimationReturn => {
/** 动画样式 */
const transitionStyle = computed((): string => {
if (isNumber(prop.animationTime)) {
return `${prop.animationTime}s all ease-in-out`
}
return '0.747s all ease-in-out'
})

/**
* 在动画开始之前,加点样式
*
* @param { Object } el 元素节点
*/
const before = (el: Element): void => {
const node = el as HTMLElement

node.style.transition = transitionStyle.value
node.style.width = 'auto'

if (prop.opened) {
node.style.height = '0'

run(prop.onOpen, el)

} else {
node.style.height = node.scrollHeight + 'px'

if (prop.widthAnimation) {
/** 获取父节点 */
const parent = node.parentElement as HTMLElement
/**
* 获取父节点的宽度
*
* @see HTMLElement.offsetWidth https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/offsetWidth
* @see Element.clientWidth https://developer.mozilla.org/zh-CN/docs/Web/API/Element/clientWidth
*/
const parentWidth: number = parent.offsetWidth || parent.clientWidth

node.style.width = `${parentWidth}px`
}

run(prop.onClose, el)
}
}

/**
* 在打开和关闭完成之后,移除样式
*
* @param { Object } el 元素节点
*/
const after = (el: Element): void => {
const node = el as HTMLElement

node.style.transition = ''
node.style.height = ''
node.style.width = ''

if (prop.opened) {
run(prop.onOpenEnd, el)

} else {
run(prop.onCloseEnd, el)
}
}

/**
* 运动过程中干点事儿
*
* @param { Object } el 元素节点
*/
const ing = (el: Element): void => {
const node = el as HTMLElement

node.style.overflow = 'hidden'

if (prop.opened) {
/** 开启执行 */
node.style.height = node.scrollHeight + 'px'

/** 如果需要宽度过度 */
if (prop.widthAnimation) {
node.style.width = '0'

/** 获取父节点 */
const parent = node.parentElement as HTMLElement
/**
* 获取父节点的宽度
*
* @see HTMLElement.offsetWidth https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/offsetWidth
* @see Element.clientWidth https://developer.mozilla.org/zh-CN/docs/Web/API/Element/clientWidth
*/
const parentWidth: number = parent.offsetWidth || parent.clientWidth

/** 如果两个方法都没有获取到宽度,使用 auto */
node.style.width = isNumber(parentWidth) ? `${parentWidth}px` : 'auto'
}
} else {
/** 关闭执行 */
node.style.height = '0'

if (prop.widthAnimation) {
node.style.width = '0'
}
}
}

return {
after,
before,
ing
}
}
173 changes: 14 additions & 159 deletions packages/fighting-design/collapse-animation/src/collapse-animation.vue
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
<script lang="ts" setup>
import { Props } from './props'
import { computed } from 'vue'
import { useRun } from '../../_hooks'
import { isNumber } from '../../_utils'
defineOptions({ name: 'FCollapseAnimation' })
const prop = defineProps(Props)
const { run } = useRun()
import { useCollapseAnimation } from '../../_hooks'
/**
* 该组件 2023-02-24 重构一次
*
* 以往版本实现可参考:
* 旧版本
*
* @see collapse-animation https://github.com/FightingDesign/fighting-design/tree/474f6f19c2b034d5f2839c110e02b8987af24a9a/packages/fighting-design/collapse-animation
*
* 新版本使用 Transition 来实现
*
* @see javascript-hooks https://cn.vuejs.org/guide/built-ins/transition.html#javascript-hooks
*/
defineOptions({ name: 'FCollapseAnimation' })
const prop = defineProps(Props)
const { after, before, ing } = useCollapseAnimation(prop)
/** 获取当前的展示状态 */
const open: boolean = prop.opened
Expand All @@ -35,154 +28,16 @@
const isOpened = computed((): boolean => {
return prop.disabled ? open : prop.opened
})
/** 动画样式 */
const transitionStyle = computed((): string => {
if (isNumber(prop.animationTime)) {
return `${prop.animationTime}s all ease-in-out`
}
return '0.747s all ease-in-out'
})
/**
* 打开动画开始的回调
*
* @param { Object } el 元素节点
*/
const onBeforeEnter = (el: Element): void => {
const node = el as HTMLElement
node.style.transition = transitionStyle.value
node.style.height = '0'
node.style.width = 'auto'
run(prop.onOpen, el)
}
/**
* 在元素被插入到 DOM 之后的下一帧被调用
*
* 用这个来开始进入动画
*
* @param { Object } el 元素节点
*/
const onEnter = (el: Element): void => {
const node = el as HTMLElement
if (node.scrollHeight !== 0) {
node.style.height = `${node.scrollHeight}px`
} else {
node.style.height = ''
}
/** 如果需要宽度过度 */
if (prop.widthAnimation) {
node.style.width = '0'
/** 获取父节点 */
const parent = node.parentElement as HTMLElement
/**
* 获取父节点的宽度
*
* @see HTMLElement.offsetWidth https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/offsetWidth
* @see Element.clientWidth https://developer.mozilla.org/zh-CN/docs/Web/API/Element/clientWidth
*/
const parentWidth: number = parent.offsetWidth || parent.clientWidth
/** 如果两个方法都没有获取到宽度,使用 auto */
node.style.width = isNumber(parentWidth) ? `${parentWidth}px` : 'auto'
}
node.style.overflow = 'hidden'
}
/**
* 打开动画结束的回调
*
* @param { Object } el 元素节点
*/
const onAfterEnter = (el: Element): void => {
const node = el as HTMLElement
node.style.transition = ''
node.style.height = ''
node.style.width = ''
run(prop.onOpenEnd, el)
}
/**
* 关闭动画开始的回调
*
* @param { Object } el 元素节点
*/
const onBeforeLeave = (el: Element): void => {
const node = el as HTMLElement
node.style.height = `${node.scrollHeight}px`
if (prop.widthAnimation) {
/** 获取父节点 */
const parent = node.parentElement as HTMLElement
/**
* 获取父节点的宽度
*
* @see HTMLElement.offsetWidth https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/offsetWidth
* @see Element.clientWidth https://developer.mozilla.org/zh-CN/docs/Web/API/Element/clientWidth
*/
const parentWidth: number = parent.offsetWidth || parent.clientWidth
node.style.width = `${parentWidth}px`
}
run(prop.onClose, el)
}
/**
* 在离开过渡开始时调用
*
* 用这个来开始离开动画
*
* @param { Object } el 元素节点
*/
const onLeave = (el: Element): void => {
const node = el as HTMLElement
if (node.scrollHeight !== 0) {
node.style.transition = transitionStyle.value
node.style.height = '0'
}
if (prop.widthAnimation) {
node.style.transition = transitionStyle.value
node.style.width = '0'
}
}
/**
* 关闭动画结束的回调
*
* @param { Object } el 元素节点
*/
const onAfterLeave = (el: Element): void => {
const node = el as HTMLElement
node.style.transition = ''
node.style.height = ''
node.style.width = ''
run(prop.onCloseEnd, el)
}
</script>

<template>
<transition
@before-enter="onBeforeEnter"
@enter="onEnter"
@after-enter="onAfterEnter"
@before-leave="onBeforeLeave"
@leave="onLeave"
@after-leave="onAfterLeave"
@before-enter="before"
@enter="ing"
@after-enter="after"
@before-leave="before"
@leave="ing"
@after-leave="after"
>
<div v-show="isOpened" class="f-collapse-animation">
<slot />
Expand Down
24 changes: 2 additions & 22 deletions start/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
<script lang="ts" setup>
import { ref } from 'vue'
<script lang="ts" setup></script>

const isOpen = ref(false)
</script>

<template>
<f-switch v-model="isOpen" />

<f-collapse-animation :opened="isOpen">
<p>11111</p>
<p>11111</p>
<p>11111</p>
<p>11111</p>
<p>11111</p>
<p>11111</p>
<p>11111</p>
<p>11111</p>
<p>11111</p>
<p>11111</p>
<p>222222</p>
</f-collapse-animation>
</template>
<template></template>

0 comments on commit f8b0713

Please sign in to comment.