Skip to content

Commit 68ffded

Browse files
committed
feat: 更新图标组件的切换动画,增加轻量缩放和模糊过渡效果
1 parent d0029c0 commit 68ffded

2 files changed

Lines changed: 46 additions & 19 deletions

File tree

packages/components/src/icon/README.md

100755100644
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ const isActive = ref(false)
123123
1. **图标尺寸**:图标默认尺寸为 `1em`,可通过父元素的 `font-size` 或图标的 `class` 控制
124124
2. **图标颜色**:使用 `currentColor`,继承父元素的文字颜色
125125
3. **加载状态**:使用图片 URL 时,加载失败会显示破损图片图标
126-
4. **切换动画**:默认图标切换时无动画,可通过 `transition` prop 开启翻转动画(0.2s
126+
4. **切换动画**:默认图标切换时无动画,可通过 `transition` prop 开启轻量的缩放 + blur 过渡动画(0.24s
127127

128128
## 典型使用场景
129129

packages/components/src/icon/index.vue

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,6 @@ const props = defineProps<{
1515
class?: HTMLAttributes['class']
1616
}>()
1717
18-
const IconWrapper = defineComponent({
19-
render() {
20-
const content = this.$slots.default?.()
21-
return props.transition
22-
? h(Transition, { name: 'icon-flip' }, () => content)
23-
: content
24-
},
25-
})
26-
2718
const outputType = computed(() => {
2819
if (!props.name) {
2920
return
@@ -44,6 +35,20 @@ const outputType = computed(() => {
4435
return 'svg'
4536
}
4637
})
38+
39+
const iconKey = computed(() => `${outputType.value ?? 'empty'}-${props.name}`)
40+
41+
const IconWrapper = defineComponent({
42+
render() {
43+
const content = this.$slots.default?.()
44+
return props.transition
45+
? h(Transition, { name: 'icon-switch' }, () => h('span', {
46+
key: iconKey.value,
47+
class: 'icon-switch-layer',
48+
}, content))
49+
: content
50+
},
51+
})
4752
</script>
4853

4954
<template>
@@ -71,21 +76,43 @@ const outputType = computed(() => {
7176
</template>
7277

7378
<style scoped>
74-
.icon-flip-enter-active {
75-
transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
79+
.icon-switch-layer {
80+
position: absolute;
81+
inset: 0;
82+
display: flex;
83+
align-items: center;
84+
justify-content: center;
7685
}
7786
78-
.icon-flip-leave-active {
79-
transition: all 0.2s cubic-bezier(0.36, 0, 0.66, -0.56);
87+
.icon-switch-enter-active,
88+
.icon-switch-leave-active {
89+
transform-origin: center;
90+
backface-visibility: hidden;
91+
transition:
92+
opacity 0.2s,
93+
transform 0.2s,
94+
filter 0.2s;
95+
will-change: opacity, transform, filter;
8096
}
8197
82-
.icon-flip-enter-from {
98+
.icon-switch-enter-from,
99+
.icon-switch-leave-to {
83100
opacity: 0;
84-
transform: scale(0.5) rotate(90deg);
101+
filter: blur(4px);
85102
}
86103
87-
.icon-flip-leave-to {
88-
opacity: 0;
89-
transform: scale(0.5) rotate(-90deg);
104+
.icon-switch-enter-from {
105+
transform: scale(0.6);
106+
}
107+
108+
.icon-switch-leave-to {
109+
transform: scale(0.6);
110+
}
111+
112+
.icon-switch-enter-to,
113+
.icon-switch-leave-from {
114+
opacity: 1;
115+
filter: blur(0);
116+
transform: scale(1);
90117
}
91118
</style>

0 commit comments

Comments
 (0)