committed by
GitHub
11 changed files with 338 additions and 0 deletions
@ -0,0 +1,8 @@ |
|||||
|
export * from './types'; |
||||
|
|
||||
|
export { |
||||
|
MotionComponent as Motion, |
||||
|
MotionDirective, |
||||
|
MotionGroupComponent as MotionGroup, |
||||
|
MotionPlugin, |
||||
|
} from '@vueuse/motion'; |
||||
@ -0,0 +1,26 @@ |
|||||
|
export const MotionPresets = [ |
||||
|
'fade', |
||||
|
'fadeVisible', |
||||
|
'fadeVisibleOnce', |
||||
|
'rollBottom', |
||||
|
'rollLeft', |
||||
|
'rollRight', |
||||
|
'rollTop', |
||||
|
'rollVisibleBottom', |
||||
|
'rollVisibleLeft', |
||||
|
'rollVisibleRight', |
||||
|
'rollVisibleTop', |
||||
|
'pop', |
||||
|
'popVisible', |
||||
|
'popVisibleOnce', |
||||
|
'slideBottom', |
||||
|
'slideLeft', |
||||
|
'slideRight', |
||||
|
'slideTop', |
||||
|
'slideVisibleBottom', |
||||
|
'slideVisibleLeft', |
||||
|
'slideVisibleRight', |
||||
|
'slideVisibleTop', |
||||
|
] as const; |
||||
|
|
||||
|
export type MotionPreset = (typeof MotionPresets)[number]; |
||||
@ -0,0 +1,213 @@ |
|||||
|
<script lang="ts" setup> |
||||
|
import { reactive } from 'vue'; |
||||
|
|
||||
|
import { Page } from '@vben/common-ui'; |
||||
|
import { Motion, MotionGroup, MotionPresets } from '@vben/plugins/motion'; |
||||
|
|
||||
|
import { refAutoReset, watchDebounced } from '@vueuse/core'; |
||||
|
import { |
||||
|
Button, |
||||
|
Card, |
||||
|
Col, |
||||
|
Form, |
||||
|
FormItem, |
||||
|
InputNumber, |
||||
|
Row, |
||||
|
Select, |
||||
|
} from 'ant-design-vue'; |
||||
|
// 本例子用不到visible类型的动画。带有VisibleOnce和Visible的类型会在组件进入视口被显示时执行动画, |
||||
|
const presets = MotionPresets.filter((v) => !v.includes('Visible')); |
||||
|
const showCard1 = refAutoReset(true, 100); |
||||
|
const showCard2 = refAutoReset(true, 100); |
||||
|
const showCard3 = refAutoReset(true, 100); |
||||
|
const motionProps = reactive({ |
||||
|
delay: 0, |
||||
|
duration: 300, |
||||
|
enter: { scale: 1 }, |
||||
|
hovered: { scale: 1.1, transition: { delay: 0, duration: 50 } }, |
||||
|
preset: 'fade', |
||||
|
tapped: { scale: 0.9, transition: { delay: 0, duration: 50 } }, |
||||
|
}); |
||||
|
|
||||
|
const motionGroupProps = reactive({ |
||||
|
delay: 0, |
||||
|
duration: 300, |
||||
|
enter: { scale: 1 }, |
||||
|
hovered: { scale: 1.1, transition: { delay: 0, duration: 50 } }, |
||||
|
preset: 'fade', |
||||
|
tapped: { scale: 0.9, transition: { delay: 0, duration: 50 } }, |
||||
|
}); |
||||
|
|
||||
|
watchDebounced( |
||||
|
motionProps, |
||||
|
() => { |
||||
|
showCard2.value = false; |
||||
|
}, |
||||
|
{ debounce: 200, deep: true }, |
||||
|
); |
||||
|
|
||||
|
watchDebounced( |
||||
|
motionGroupProps, |
||||
|
() => { |
||||
|
showCard3.value = false; |
||||
|
}, |
||||
|
{ debounce: 200, deep: true }, |
||||
|
); |
||||
|
|
||||
|
function openDocPage() { |
||||
|
window.open('https://motion.vueuse.org/', '_blank'); |
||||
|
} |
||||
|
</script> |
||||
|
<template> |
||||
|
<Page title="Motion"> |
||||
|
<template #description> |
||||
|
<span>一个易于使用的为其它组件赋予动画效果的组件。</span> |
||||
|
<Button type="link" @click="openDocPage">查看文档</Button> |
||||
|
</template> |
||||
|
<Card title="使用指令" :body-style="{ minHeight: '5rem' }"> |
||||
|
<template #extra> |
||||
|
<Button type="primary" @click="showCard1 = false">重载</Button> |
||||
|
</template> |
||||
|
<div> |
||||
|
<div class="relative flex gap-2 overflow-hidden" v-if="showCard1"> |
||||
|
<Button v-motion-fade-visible>fade</Button> |
||||
|
<Button v-motion-pop-visible :duration="500">pop</Button> |
||||
|
<Button v-motion-slide-left>slide-left</Button> |
||||
|
<Button v-motion-slide-right>slide-right</Button> |
||||
|
<Button v-motion-slide-bottom>slide-bottom</Button> |
||||
|
<Button v-motion-slide-top>slide-top</Button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</Card> |
||||
|
<Card |
||||
|
class="mt-2" |
||||
|
title="使用组件(将内部作为一个整体添加动画)" |
||||
|
:body-style="{ padding: 0 }" |
||||
|
> |
||||
|
<div |
||||
|
class="relative flex min-h-32 items-center justify-center gap-2 overflow-hidden" |
||||
|
> |
||||
|
<Motion |
||||
|
v-bind="motionProps" |
||||
|
v-if="showCard2" |
||||
|
class="flex items-center gap-2" |
||||
|
> |
||||
|
<Button size="large">这个按钮在显示时会有动画效果</Button> |
||||
|
<span>附属组件,会作为整体处理动画</span> |
||||
|
</Motion> |
||||
|
</div> |
||||
|
<div |
||||
|
class="relative flex min-h-32 items-center justify-center gap-2 overflow-hidden" |
||||
|
> |
||||
|
<div v-if="showCard2" class="flex items-center gap-2"> |
||||
|
<span>顺序延迟</span> |
||||
|
<Motion |
||||
|
v-bind="{ |
||||
|
...motionProps, |
||||
|
delay: motionProps.delay + 100 * i, |
||||
|
}" |
||||
|
v-for="i in 5" |
||||
|
:key="i" |
||||
|
> |
||||
|
<Button size="large">按钮{{ i }}</Button> |
||||
|
</Motion> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div> |
||||
|
<Form :model="motionProps" :label-col="{ span: 10 }"> |
||||
|
<Row> |
||||
|
<Col :span="8"> |
||||
|
<FormItem prop="preset" label="动画效果"> |
||||
|
<Select v-model:value="motionProps.preset"> |
||||
|
<Select.Option |
||||
|
:value="preset" |
||||
|
v-for="preset in presets" |
||||
|
:key="preset" |
||||
|
> |
||||
|
{{ preset }} |
||||
|
</Select.Option> |
||||
|
</Select> |
||||
|
</FormItem> |
||||
|
</Col> |
||||
|
<Col :span="8"> |
||||
|
<FormItem prop="duration" label="持续时间"> |
||||
|
<InputNumber v-model:value="motionProps.duration" /> |
||||
|
</FormItem> |
||||
|
</Col> |
||||
|
<Col :span="8"> |
||||
|
<FormItem prop="delay" label="延迟动画"> |
||||
|
<InputNumber v-model:value="motionProps.delay" /> |
||||
|
</FormItem> |
||||
|
</Col> |
||||
|
<Col :span="8"> |
||||
|
<FormItem prop="hovered.scale" label="Hover缩放"> |
||||
|
<InputNumber v-model:value="motionProps.hovered.scale" /> |
||||
|
</FormItem> |
||||
|
</Col> |
||||
|
<Col :span="8"> |
||||
|
<FormItem prop="hovered.tapped" label="按下时缩放"> |
||||
|
<InputNumber v-model:value="motionProps.tapped.scale" /> |
||||
|
</FormItem> |
||||
|
</Col> |
||||
|
</Row> |
||||
|
</Form> |
||||
|
</div> |
||||
|
</Card> |
||||
|
<Card |
||||
|
class="mt-2" |
||||
|
title="分组动画(每个子元素都会应用相同的独立动画)" |
||||
|
:body-style="{ padding: 0 }" |
||||
|
> |
||||
|
<div |
||||
|
class="relative flex min-h-32 items-center justify-center gap-2 overflow-hidden" |
||||
|
> |
||||
|
<MotionGroup v-bind="motionGroupProps" v-if="showCard3"> |
||||
|
<Button size="large">按钮1</Button> |
||||
|
<Button size="large">按钮2</Button> |
||||
|
<Button size="large">按钮3</Button> |
||||
|
<Button size="large">按钮4</Button> |
||||
|
<Button size="large">按钮5</Button> |
||||
|
</MotionGroup> |
||||
|
</div> |
||||
|
<div> |
||||
|
<Form :model="motionGroupProps" :label-col="{ span: 10 }"> |
||||
|
<Row> |
||||
|
<Col :span="8"> |
||||
|
<FormItem prop="preset" label="动画效果"> |
||||
|
<Select v-model:value="motionGroupProps.preset"> |
||||
|
<Select.Option |
||||
|
:value="preset" |
||||
|
v-for="preset in presets" |
||||
|
:key="preset" |
||||
|
> |
||||
|
{{ preset }} |
||||
|
</Select.Option> |
||||
|
</Select> |
||||
|
</FormItem> |
||||
|
</Col> |
||||
|
<Col :span="8"> |
||||
|
<FormItem prop="duration" label="持续时间"> |
||||
|
<InputNumber v-model:value="motionGroupProps.duration" /> |
||||
|
</FormItem> |
||||
|
</Col> |
||||
|
<Col :span="8"> |
||||
|
<FormItem prop="delay" label="延迟动画"> |
||||
|
<InputNumber v-model:value="motionGroupProps.delay" /> |
||||
|
</FormItem> |
||||
|
</Col> |
||||
|
<Col :span="8"> |
||||
|
<FormItem prop="hovered.scale" label="Hover缩放"> |
||||
|
<InputNumber v-model:value="motionGroupProps.hovered.scale" /> |
||||
|
</FormItem> |
||||
|
</Col> |
||||
|
<Col :span="8"> |
||||
|
<FormItem prop="hovered.tapped" label="按下时缩放"> |
||||
|
<InputNumber v-model:value="motionGroupProps.tapped.scale" /> |
||||
|
</FormItem> |
||||
|
</Col> |
||||
|
</Row> |
||||
|
</Form> |
||||
|
</div> |
||||
|
</Card> |
||||
|
</Page> |
||||
|
</template> |
||||
Loading…
Reference in new issue