index.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <script lang="ts" setup>
  2. import { reactive } from 'vue';
  3. import { Page } from '@vben/common-ui';
  4. import { Motion, MotionGroup, MotionPresets } from '@vben/plugins/motion';
  5. import { refAutoReset, watchDebounced } from '@vueuse/core';
  6. import {
  7. Button,
  8. Card,
  9. Col,
  10. Form,
  11. FormItem,
  12. InputNumber,
  13. Row,
  14. Select,
  15. } from 'antdv-next';
  16. // 本例子用不到visible类型的动画。带有VisibleOnce和Visible的类型会在组件进入视口被显示时执行动画,
  17. const presets = MotionPresets.filter((v) => !v.includes('Visible'));
  18. const showCard1 = refAutoReset(true, 100);
  19. const showCard2 = refAutoReset(true, 100);
  20. const showCard3 = refAutoReset(true, 100);
  21. const motionProps = reactive({
  22. delay: 0,
  23. duration: 300,
  24. enter: { scale: 1 },
  25. hovered: { scale: 1.1, transition: { delay: 0, duration: 50 } },
  26. preset: 'fade',
  27. tapped: { scale: 0.9, transition: { delay: 0, duration: 50 } },
  28. });
  29. const motionGroupProps = reactive({
  30. delay: 0,
  31. duration: 300,
  32. enter: { scale: 1 },
  33. hovered: { scale: 1.1, transition: { delay: 0, duration: 50 } },
  34. preset: 'fade',
  35. tapped: { scale: 0.9, transition: { delay: 0, duration: 50 } },
  36. });
  37. watchDebounced(
  38. motionProps,
  39. () => {
  40. showCard2.value = false;
  41. },
  42. { debounce: 200, deep: true },
  43. );
  44. watchDebounced(
  45. motionGroupProps,
  46. () => {
  47. showCard3.value = false;
  48. },
  49. { debounce: 200, deep: true },
  50. );
  51. function openDocPage() {
  52. window.open('https://motion.vueuse.org/', '_blank');
  53. }
  54. </script>
  55. <template>
  56. <Page title="Motion">
  57. <template #description>
  58. <span>一个易于使用的为其它组件赋予动画效果的组件。</span>
  59. <Button type="link" @click="openDocPage">查看文档</Button>
  60. </template>
  61. <Card title="使用指令" :styles="{ body: { minHeight: '5rem' } }">
  62. <template #extra>
  63. <Button type="primary" @click="showCard1 = false">重载</Button>
  64. </template>
  65. <div>
  66. <div class="relative flex gap-2 overflow-hidden" v-if="showCard1">
  67. <Button v-motion-fade-visible>fade</Button>
  68. <Button v-motion-pop-visible :duration="500">pop</Button>
  69. <Button v-motion-slide-left>slide-left</Button>
  70. <Button v-motion-slide-right>slide-right</Button>
  71. <Button v-motion-slide-bottom>slide-bottom</Button>
  72. <Button v-motion-slide-top>slide-top</Button>
  73. </div>
  74. </div>
  75. </Card>
  76. <Card
  77. class="mt-2"
  78. title="使用组件(将内部作为一个整体添加动画)"
  79. :styles="{ body: { padding: 0 } }"
  80. >
  81. <div class="relative flex-center min-h-32 gap-2 overflow-hidden">
  82. <Motion
  83. v-bind="motionProps"
  84. v-if="showCard2"
  85. class="flex items-center gap-2"
  86. >
  87. <Button size="large">这个按钮在显示时会有动画效果</Button>
  88. <span>附属组件,会作为整体处理动画</span>
  89. </Motion>
  90. </div>
  91. <div class="relative flex-center min-h-32 gap-2 overflow-hidden">
  92. <div v-if="showCard2" class="flex items-center gap-2">
  93. <span>顺序延迟</span>
  94. <Motion
  95. v-bind="{
  96. ...motionProps,
  97. delay: motionProps.delay + 100 * i,
  98. }"
  99. v-for="i in 5"
  100. :key="i"
  101. >
  102. <Button size="large">按钮{{ i }}</Button>
  103. </Motion>
  104. </div>
  105. </div>
  106. <div>
  107. <Form :model="motionProps" :label-col="{ span: 10 }">
  108. <Row>
  109. <Col :span="8">
  110. <FormItem prop="preset" label="动画效果">
  111. <Select
  112. v-model:value="motionProps.preset"
  113. :options="presets.map((p) => ({ label: p, value: p }))"
  114. />
  115. </FormItem>
  116. </Col>
  117. <Col :span="8">
  118. <FormItem prop="duration" label="持续时间">
  119. <InputNumber v-model:value="motionProps.duration" />
  120. </FormItem>
  121. </Col>
  122. <Col :span="8">
  123. <FormItem prop="delay" label="延迟动画">
  124. <InputNumber v-model:value="motionProps.delay" />
  125. </FormItem>
  126. </Col>
  127. <Col :span="8">
  128. <FormItem prop="hovered.scale" label="Hover缩放">
  129. <InputNumber v-model:value="motionProps.hovered.scale" />
  130. </FormItem>
  131. </Col>
  132. <Col :span="8">
  133. <FormItem prop="hovered.tapped" label="按下时缩放">
  134. <InputNumber v-model:value="motionProps.tapped.scale" />
  135. </FormItem>
  136. </Col>
  137. </Row>
  138. </Form>
  139. </div>
  140. </Card>
  141. <Card
  142. class="mt-2"
  143. title="分组动画(每个子元素都会应用相同的独立动画)"
  144. :styles="{ body: { padding: 0 } }"
  145. >
  146. <div class="relative flex-center min-h-32 gap-2 overflow-hidden">
  147. <MotionGroup v-bind="motionGroupProps" v-if="showCard3">
  148. <Button size="large">按钮1</Button>
  149. <Button size="large">按钮2</Button>
  150. <Button size="large">按钮3</Button>
  151. <Button size="large">按钮4</Button>
  152. <Button size="large">按钮5</Button>
  153. </MotionGroup>
  154. </div>
  155. <div>
  156. <Form :model="motionGroupProps" :label-col="{ span: 10 }">
  157. <Row>
  158. <Col :span="8">
  159. <FormItem prop="preset" label="动画效果">
  160. <Select
  161. v-model:value="motionGroupProps.preset"
  162. :options="presets.map((p) => ({ label: p, value: p }))"
  163. />
  164. </FormItem>
  165. </Col>
  166. <Col :span="8">
  167. <FormItem prop="duration" label="持续时间">
  168. <InputNumber v-model:value="motionGroupProps.duration" />
  169. </FormItem>
  170. </Col>
  171. <Col :span="8">
  172. <FormItem prop="delay" label="延迟动画">
  173. <InputNumber v-model:value="motionGroupProps.delay" />
  174. </FormItem>
  175. </Col>
  176. <Col :span="8">
  177. <FormItem prop="hovered.scale" label="Hover缩放">
  178. <InputNumber v-model:value="motionGroupProps.hovered.scale" />
  179. </FormItem>
  180. </Col>
  181. <Col :span="8">
  182. <FormItem prop="hovered.tapped" label="按下时缩放">
  183. <InputNumber v-model:value="motionGroupProps.tapped.scale" />
  184. </FormItem>
  185. </Col>
  186. </Row>
  187. </Form>
  188. </div>
  189. </Card>
  190. </Page>
  191. </template>