From f8001cad76264fbe02abe427561426cf58dd5fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E4=BA=91=E8=8B=8D=E7=8B=97?= <31614024+MaLuns@users.noreply.github.com> Date: Mon, 14 Apr 2025 05:20:33 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=8A=A8=E7=94=BB?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E5=B0=81=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/styles/animate.scss | 166 +++++++++++++++++++++++++++++++++ src/configs/animation.ts | 40 ++++++++ src/main.ts | 2 +- 3 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 src/assets/styles/animate.scss diff --git a/src/assets/styles/animate.scss b/src/assets/styles/animate.scss new file mode 100644 index 000000000..4b5163b58 --- /dev/null +++ b/src/assets/styles/animate.scss @@ -0,0 +1,166 @@ +@use "sass:map"; +@import "animate.css"; + +//#region 动画创建 mixin + +/* +* 创建动画 +* $name: 动画名称 +*/ +@mixin base_animate_mixin($name) { + @-webkit-keyframes #{$name} { + @content ('keyframes'); + } + @keyframes #{$name} { + @content ('keyframes'); + } + .animate__#{$name} { + -webkit-animation-duration: var(--animate-duration); + animation-duration: var(--animate-duration); + -webkit-animation-name: #{$name}; + animation-name: #{$name}; + @content ('animate'); + } +} + +/* +* 创建入场和出场动画 +* $name: 动画名称 +* $reverse: 入场或出场 (In,Out, 与 animate.css 一致) +* $type: 动画类型 (style_map 中对应 key ) +* $style_map: 动画样式 +*/ +@mixin create_animate_mixin($name, $reverse: "", $type: "", $style_map: ()) { + $animate_name: $name + $reverse + $type; + $style: map.get($style_map, $type); + + @if ($style == null) { + @error '#{$type} is not in style map'; + } + + @include base_animate_mixin($animate_name) using ($content_type) { + @if $content_type == "animate" { + @if $reverse == "Out" { + animation-direction: reverse; + } + @content; + } + @if $content_type == "keyframes" { + @each $state, $properties in $style { + #{$state} { + @each $property, $value in $properties { + #{$property}: $value; + } + } + } + } + } +} + +/* +* 创建入场和出场动画 - 根据 style_map 创建动画 +* $name: 动画名称 +* $style_map: 动画样式 +* $isCreateReverse: 是否创建反向动画 +* $forwardKey: 正向动画的 key +* $reverseKey: 反向动画的 key +*/ +@mixin create_animate_mixin_with_map( + $name, + $style_map: (), + $isCreateReverse: false, + $forwardKey: "In", + $reverseKey: "Out" +) { + @each $key, $properties in $style_map { + @if $isCreateReverse { + @include create_animate_mixin($name, $forwardKey, $key, $style_map); + @include create_animate_mixin($name, $reverseKey, $key, $style_map); + } @else { + @include create_animate_mixin($name, "", $key, $style_map); + } + } +} + +//#endregion + +//#region erase 擦除动画 + +$erase_map: ( + "Left": ( + "from": ( + clip-path: polygon(0% 0%, 0% 0%, 0% 100%, 0 100%) + ), + "to": ( + clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0 100%) + ) + ), + "Right": ( + "from": ( + clip-path: polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%) + ), + "to": ( + clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%) + ) + ), + "Top": ( + "from": ( + clip-path: polygon(0% 0%, 100% 0%, 100% 0%, 0 0%) + ), + "to": ( + clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0 100%) + ) + ), + "Bottom": ( + "from": ( + clip-path: polygon(0% 100%, 100% 100%, 100% 100%, 0 100%) + ), + "to": ( + clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0 100%) + ) + ) +); + +@include create_animate_mixin_with_map("erase", $erase_map, true); + +//#endregion + +//#region split 裂开动画 +$split_map: ( + "ToCenter": ( + "from": ( + clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0 100%, 0% 100%, 100% 100%, 100% 0%, 0% 0%, 0 100%) + ), + "to": ( + clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0 100%, 0% 50%, 100% 50%, 100% 50%, 0% 50%, 0% 100%) + ) + ), + "FromCenter": ( + "from": ( + clip-path: polygon(0 50%, 100% 50%, 100% 50%, 0 50%) + ), + "to": ( + clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0 100%) + ) + ), + "ToBetween": ( + "from": ( + clip-path: polygon(0% 0%, 0% 100%, 100% 100%, 100% 0%, 100% 0%, 100% 100%, 0% 100%, 0% 0%) + ), + "to": ( + clip-path: polygon(0% 0%, 0% 100%, 100% 100%, 100% 0%, 50% 0%, 50% 100%, 50% 100%, 50% 0%) + ) + ), + "FromBetween": ( + "from": ( + clip-path: polygon(50% 0%, 50% 0%, 50% 100%, 50% 100%) + ), + "to": ( + clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0 100%) + ) + ) +); + +@include create_animate_mixin_with_map("split", $split_map, true); + +//#endregion diff --git a/src/configs/animation.ts b/src/configs/animation.ts index 858a376b5..340aad4e9 100644 --- a/src/configs/animation.ts +++ b/src/configs/animation.ts @@ -93,6 +93,26 @@ export const ENTER_ANIMATIONS = [ { name: '从左飞入', value: 'lightSpeedInLeft' }, ], }, + { + type: 'erase', + name: '擦除', + children: [ + { name: '从左侧擦除', value: 'eraseInLeft' }, + { name: '从右侧擦除', value: 'eraseInRight' }, + { name: '从顶部擦除', value: 'eraseInTop' }, + { name: '从底部擦除', value: 'eraseInBottom' } + ] + }, + { + type: 'split', + name: '裂开', + children: [ + { name: '上下向中央收缩', value: 'splitInToCenter' }, + { name: '中央向上下展开', value: 'splitInFromCenter' }, + { name: '左右向中央收缩', value: 'splitInToBetween' }, + { name: '中央向左右展开', value: 'splitInFromBetween' } + ] + }, ] export const EXIT_ANIMATIONS = [ @@ -184,6 +204,26 @@ export const EXIT_ANIMATIONS = [ { name: '从左飞出', value: 'lightSpeedOutLeft' }, ], }, + { + type: 'erase', + name: '擦除', + children: [ + { name: '向左擦除', value: 'eraseOutLeft' }, + { name: '向右擦除', value: 'eraseOutRight' }, + { name: '向上擦除', value: 'eraseOutTop' }, + { name: '向下擦除', value: 'eraseOutBottom' } + ] + }, + { + type: 'split', + name: '裂开', + children: [ + { name: '中央向上下收缩', value: 'splitOutToCenter' }, + { name: '上下向中央收缩', value: 'splitOutFromCenter' }, + { name: '中央向左右收缩', value: 'splitOutToBetween' }, + { name: '左右向中央收缩', value: 'splitOutFromBetween' } + ] + }, ] export const ATTENTION_ANIMATIONS = [ diff --git a/src/main.ts b/src/main.ts index b316dcda0..6fcef8db5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,7 +4,7 @@ import App from './App.vue' import '@icon-park/vue-next/styles/index.css' import 'prosemirror-view/style/prosemirror.css' -import 'animate.css' +import '@/assets/styles/animate.scss' import '@/assets/styles/prosemirror.scss' import '@/assets/styles/global.scss' import '@/assets/styles/font.scss'