From b7faece5575e106c627e00493469c411a17b4da3 Mon Sep 17 00:00:00 2001 From: Lyra <1170158548@qq.com> Date: Fri, 18 Jul 2025 11:38:19 +0800 Subject: [PATCH 1/7] feat(theme): [transition] add global animation configuration scheme (LESS-based) --- packages/theme/src/base/reset.less | 19 +- packages/theme/src/base/transition.less | 48 +-- packages/theme/src/chart-core/index.less | 43 +-- packages/theme/src/dialog-box/index.less | 171 +++++----- packages/theme/src/drawer/index.less | 323 +++++++++--------- packages/theme/src/fall-menu/index.less | 55 +-- packages/theme/src/grid/body.less | 17 +- packages/theme/src/grid/excel.less | 17 +- packages/theme/src/grid/icon.less | 19 +- packages/theme/src/grid/loading.less | 19 +- packages/theme/src/image/index.less | 59 ++-- packages/theme/src/motion/arrow.less | 116 +++++++ packages/theme/src/motion/bounce.less | 35 ++ packages/theme/src/motion/fade.less | 159 +++++++++ packages/theme/src/motion/index.less | 17 + packages/theme/src/motion/progress.less | 22 ++ packages/theme/src/motion/rotate.less | 30 ++ packages/theme/src/motion/scroll.less | 103 ++++++ packages/theme/src/motion/shine.less | 10 + packages/theme/src/motion/skeleton.less | 19 ++ packages/theme/src/motion/slide.less | 139 ++++++++ packages/theme/src/motion/stroke.less | 38 +++ packages/theme/src/motion/tab.less | 111 ++++++ packages/theme/src/motion/zoom.less | 69 ++++ packages/theme/src/popup/index.less | 43 +-- packages/theme/src/progress/index.less | 40 +-- packages/theme/src/scroll-text/index.less | 147 ++++---- packages/theme/src/tabs/index.less | 297 ++++++++-------- .../theme/src/transition/carousel-arrow.less | 53 +-- packages/theme/src/transition/icon.less | 59 ++-- packages/theme/src/transition/timepicker.less | 45 +-- packages/theme/src/tree/index.less | 46 +-- 32 files changed, 1639 insertions(+), 749 deletions(-) create mode 100644 packages/theme/src/motion/arrow.less create mode 100644 packages/theme/src/motion/bounce.less create mode 100644 packages/theme/src/motion/fade.less create mode 100644 packages/theme/src/motion/index.less create mode 100644 packages/theme/src/motion/progress.less create mode 100644 packages/theme/src/motion/rotate.less create mode 100644 packages/theme/src/motion/scroll.less create mode 100644 packages/theme/src/motion/shine.less create mode 100644 packages/theme/src/motion/skeleton.less create mode 100644 packages/theme/src/motion/slide.less create mode 100644 packages/theme/src/motion/stroke.less create mode 100644 packages/theme/src/motion/tab.less create mode 100644 packages/theme/src/motion/zoom.less diff --git a/packages/theme/src/base/reset.less b/packages/theme/src/base/reset.less index 5cd64b4f02..afed5060ce 100644 --- a/packages/theme/src/base/reset.less +++ b/packages/theme/src/base/reset.less @@ -12,22 +12,23 @@ @import '../custom.less'; @import './vars.less'; +@import '../motion/index.less'; // .tiny-icon-loading 类名的动画效果。 它出现在多个组件中,故抽取到一起。 .@{css-prefix-iconfont}-loading { line-height: 1; - animation: rotating 2s linear infinite; + animation: rotate-z 2s linear infinite; } -@keyframes rotating { - 0% { - transform: rotateZ(0deg); - } +// @keyframes rotating { +// 0% { +// transform: rotateZ(0deg); +// } - 100% { - transform: rotateZ(360deg); - } -} +// 100% { +// transform: rotateZ(360deg); +// } +// } // 高亮节点 .tiny-hl-query-node { diff --git a/packages/theme/src/base/transition.less b/packages/theme/src/base/transition.less index 2520f0e1ca..8fae75e43f 100644 --- a/packages/theme/src/base/transition.less +++ b/packages/theme/src/base/transition.less @@ -2,6 +2,7 @@ vue2的动画状态类: v-enter v-enter-to v-leave v-leave-to 以及 v-enter-active, v-leave-active vue3的动画状态类: v-enter-from v-enter-to v-leave-from v-leave-to 以及 v-enter-active, v-leave-active */ +@import '../motion/index.less'; .fade-in-linear-enter-active, .fade-in-linear-leave-active { @@ -245,26 +246,27 @@ vue3的动画状态类: v-enter-from v-enter-to v-leave-from v-leave-to 以 } // modal 的动画 -@keyframes modal-fade-in { - 0% { - transform: translate3d(0, -20px, 0); - opacity: 0; - } - - 100% { - transform: translate3d(0, 0, 0); - opacity: 1; - } -} - -@keyframes modal-fade-out { - 0% { - transform: translate3d(0, 0, 0); - opacity: 1; - } - - 100% { - transform: translate3d(0, -20px, 0); - opacity: 0; - } -} +// @keyframes modal-fade-in { +// 0% { +// transform: translate3d(0, -20px, 0); +// opacity: 0; +// } + +// 100% { +// transform: translate3d(0, 0, 0); +// opacity: 1; +// } +// } + + +// @keyframes modal-fade-out { +// 0% { +// transform: translate3d(0, 0, 0); +// opacity: 1; +// } + +// 100% { +// transform: translate3d(0, -20px, 0); +// opacity: 0; +// } +// } diff --git a/packages/theme/src/chart-core/index.less b/packages/theme/src/chart-core/index.less index 75b18d1df9..16d2aa5c2d 100644 --- a/packages/theme/src/chart-core/index.less +++ b/packages/theme/src/chart-core/index.less @@ -12,6 +12,7 @@ @import '../custom.less'; @import './vars.less'; +@import '../motion/index.less'; @chart-prefix-cls: ~'@{css-prefix}chart'; @@ -51,11 +52,11 @@ .circular { width: 42px; height: 42px; - animation: loading-rotate 2s linear infinite; + animation: rotate-spin 2s linear infinite; } .path { - animation: loading-dash 1.5s ease-in-out infinite; + animation: stroke-dash-loop 1.5s ease-in-out infinite; stroke-dasharray: 90, 150; stroke-dashoffset: 0; stroke-width: 2; @@ -69,25 +70,25 @@ } } -@keyframes loading-rotate { - 100% { - transform: rotate(360deg); - } -} +// @keyframes loading-rotate { +// 100% { +// transform: rotate(360deg); +// } +// } -@keyframes loading-dash { - 0% { - stroke-dasharray: 1, 200; - stroke-dashoffset: 0; - } +// @keyframes loading-dash { +// 0% { +// stroke-dasharray: 1, 200; +// stroke-dashoffset: 0; +// } - 50% { - stroke-dasharray: 90, 150; - stroke-dashoffset: -40px; - } +// 50% { +// stroke-dasharray: 90, 150; +// stroke-dashoffset: -40px; +// } - 100% { - stroke-dasharray: 90, 150; - stroke-dashoffset: -120px; - } -} +// 100% { +// stroke-dasharray: 90, 150; +// stroke-dashoffset: -120px; +// } +// } diff --git a/packages/theme/src/dialog-box/index.less b/packages/theme/src/dialog-box/index.less index 3832dbddbb..aa57196dd6 100644 --- a/packages/theme/src/dialog-box/index.less +++ b/packages/theme/src/dialog-box/index.less @@ -12,6 +12,7 @@ @import '../custom.less'; @import './vars.less'; +@import '../motion/index.less'; @dialog-box-prefix-cls: ~'@{css-prefix}dialog-box'; @@ -209,119 +210,119 @@ } .v-modal-enter { - animation: v-modal-in 0.2s ease; + animation: fade-in 0.2s ease; } .v-modal-leave { - animation: v-modal-out 0.2s ease forwards; + animation: fade-out 0.2s ease forwards; } -@keyframes v-modal-in { - 0% { - opacity: 0; - } -} +// @keyframes v-modal-in { +// 0% { +// opacity: 0; +// } +// } -@keyframes v-modal-out { - 100% { - opacity: 0; - } -} +// @keyframes v-modal-out { +// 100% { +// opacity: 0; +// } +// } .dialog-slideRight-enter-active { - animation: slideRight 0.5s ease-in forwards; + animation: slide-right-in 0.5s ease-in forwards; } .dialog-slideRight-leave-active { - animation: slideRightout 0.5s ease-in forwards; -} - -@keyframes slideRight { - 0% { - opacity: 0; - transform: translateX(100%); - } - - 50% { - opacity: 0.6; - transform: translateX(50%); - } - - 100% { - opacity: 1; - transform: translateX(0%); - } + animation: slide-right-out 0.5s ease-in forwards; } -@keyframes slideRightout { - 0% { - opacity: 1; - transform: translateX(0%); - } - - 50% { - opacity: 0.6; - transform: translateX(50%); - } - - 100% { - opacity: 0; - transform: translateX(100%); - } -} +// @keyframes slideRight { +// 0% { +// opacity: 0; +// transform: translateX(100%); +// } + +// 50% { +// opacity: 0.6; +// transform: translateX(50%); +// } + +// 100% { +// opacity: 1; +// transform: translateX(0%); +// } +// } + +// @keyframes slideRightout { +// 0% { +// opacity: 1; +// transform: translateX(0%); +// } + +// 50% { +// opacity: 0.6; +// transform: translateX(50%); +// } + +// 100% { +// opacity: 0; +// transform: translateX(100%); +// } +// } .dialog-fade-enter-active { - animation: dialog-fade-in 0.3s; + animation: fade-in-up 0.3s; } .dialog-fade-leave-active { .@{dialog-box-prefix-cls} { - animation: dialog-fade-out 3s; - } - animation: dialog-fade-out 0.3s; -} - -@keyframes dialog-fade-in { - 0% { - transform: translate3d(0, -20px, 0); - opacity: 0; - } - - 100% { - transform: translate3d(0, 0, 0); - opacity: 1; + animation: fade-out-up 3s; } + animation: fade-out-up 0.3s; } -@keyframes dialog-fade-out { - 0% { - transform: translate3d(0, 0, 0); - opacity: 1; - } - - 100% { - transform: translate3d(0, -20px, 0); - opacity: 0; - } -} +// @keyframes dialog-fade-in { +// 0% { +// transform: translate3d(0, -20px, 0); +// opacity: 0; +// } + +// 100% { +// transform: translate3d(0, 0, 0); +// opacity: 1; +// } +// } + +// @keyframes dialog-fade-out { +// 0% { +// transform: translate3d(0, 0, 0); +// opacity: 1; +// } + +// 100% { +// transform: translate3d(0, -20px, 0); +// opacity: 0; +// } +// } .enlarge-enter-active { animation: enlarge-in 350ms linear; } -@keyframes enlarge-in { - 0% { - transform: scale(0); - } +// @keyframes enlarge-in { +// 0% { +// transform: scale(0); +// } - 50% { - transform: scale(0.5); - } +// 50% { +// transform: scale(0.5); +// } - 100% { - transform: scale(1); - } -} +// 100% { +// transform: scale(1); +// } +// } @media (max-width: 480px) { .@{dialog-box-prefix-cls} { @@ -329,4 +330,4 @@ top: 0 !important; left: 0 !important; } -} +} \ No newline at end of file diff --git a/packages/theme/src/drawer/index.less b/packages/theme/src/drawer/index.less index ec8828fc2d..2bfe2359e4 100644 --- a/packages/theme/src/drawer/index.less +++ b/packages/theme/src/drawer/index.less @@ -1,5 +1,6 @@ @import '../custom.less'; @import './vars.less'; +@import '../motion/index.less'; @drawer-prefix-cls: ~'@{css-prefix}drawer'; @@ -213,197 +214,197 @@ } .drawer-slide-right-enter-active { - animation: slideRight 0.3s linear; + animation: slide-right-in 0.3s linear; } .drawer-slide-right-leave-active { - animation: slideRightout 0.3s linear; + animation: slide-right-out 0.3s linear; } -@keyframes slideRight { - 0% { - opacity: 0; - transform: translateX(100%); - } - - 50% { - opacity: 0.6; - transform: translateX(50%); - } - - 100% { - opacity: 1; - transform: translateX(0%); - } -} - -@keyframes slideRightout { - 0% { - opacity: 1; - transform: translateX(0%); - } - - 50% { - opacity: 0.6; - transform: translateX(50%); - } - - 100% { - opacity: 0; - transform: translateX(100%); - } -} +// @keyframes slideRight { +// 0% { +// opacity: 0; +// transform: translateX(100%); +// } + +// 50% { +// opacity: 0.6; +// transform: translateX(50%); +// } + +// 100% { +// opacity: 1; +// transform: translateX(0%); +// } +// } + +// @keyframes slideRightout { +// 0% { +// opacity: 1; +// transform: translateX(0%); +// } + +// 50% { +// opacity: 0.6; +// transform: translateX(50%); +// } + +// 100% { +// opacity: 0; +// transform: translateX(100%); +// } +// } .drawer-slide-left-enter-active { - animation: slideLeft 0.3s linear; + animation: slide-left-in 0.3s linear; } .drawer-slide-left-leave-active { - animation: slideLeftout 0.3s linear; + animation: slide-left-out 0.3s linear; } -@keyframes slideLeft { - 0% { - opacity: 0; - transform: translateX(-100%); - } - - 50% { - opacity: 0.6; - transform: translateX(-50%); - } - - 100% { - opacity: 1; - transform: translateX(0%); - } -} - -@keyframes slideLeftout { - 0% { - opacity: 1; - transform: translateX(0%); - } - - 50% { - opacity: 0.6; - transform: translateX(-50%); - } - - 100% { - opacity: 0; - transform: translateX(-100%); - } -} +// @keyframes slideLeft { +// 0% { +// opacity: 0; +// transform: translateX(-100%); +// } + +// 50% { +// opacity: 0.6; +// transform: translateX(-50%); +// } + +// 100% { +// opacity: 1; +// transform: translateX(0%); +// } +// } + +// @keyframes slideLeftout { +// 0% { +// opacity: 1; +// transform: translateX(0%); +// } + +// 50% { +// opacity: 0.6; +// transform: translateX(-50%); +// } + +// 100% { +// opacity: 0; +// transform: translateX(-100%); +// } +// } .drawer-slide-bottom-enter-active { - animation: slideBottom 0.3s linear; + animation: slide-bottom-in 0.3s linear; } .drawer-slide-bottom-leave-active { - animation: slideBottomout 0.3s linear; + animation: slide-bottom-out 0.3s linear; } -@keyframes slideBottom { - 0% { - opacity: 0; - transform: translateY(100%); - } - - 50% { - opacity: 0.6; - transform: translateY(50%); - } - - 100% { - opacity: 1; - transform: translateY(0%); - } -} - -@keyframes slideBottomout { - 0% { - opacity: 0; - transform: translateY(0%); - } - - 50% { - opacity: 0.6; - transform: translateY(50%); - } - - 100% { - opacity: 1; - transform: translateY(100%); - } -} +// @keyframes slideBottom { +// 0% { +// opacity: 0; +// transform: translateY(100%); +// } + +// 50% { +// opacity: 0.6; +// transform: translateY(50%); +// } + +// 100% { +// opacity: 1; +// transform: translateY(0%); +// } +// } + +// @keyframes slideBottomout { +// 0% { +// opacity: 0; +// transform: translateY(0%); +// } + +// 50% { +// opacity: 0.6; +// transform: translateY(50%); +// } + +// 100% { +// opacity: 1; +// transform: translateY(100%); +// } +// } .drawer-slide-top-enter-active { - animation: slideTop 0.3s linear; + animation: slide-top-in 0.3s linear; } .drawer-slide-top-leave-active { - animation: slideTopout 0.3s linear; -} - -@keyframes slideTop { - 0% { - opacity: 0; - transform: translateY(-100%); - } - - 50% { - opacity: 0.6; - transform: translateY(-50%); - } - - 100% { - opacity: 1; - transform: translateY(0%); - } + animation: slide-top-out 0.3s linear; } -@keyframes slideTopout { - 0% { - opacity: 0; - transform: translateY(0%); - } - - 50% { - opacity: 0.6; - transform: translateY(-50%); - } - - 100% { - opacity: 1; - transform: translateY(-100%); - } -} +// @keyframes slideTop { +// 0% { +// opacity: 0; +// transform: translateY(-100%); +// } + +// 50% { +// opacity: 0.6; +// transform: translateY(-50%); +// } + +// 100% { +// opacity: 1; +// transform: translateY(0%); +// } +// } + +// @keyframes slideTopout { +// 0% { +// opacity: 0; +// transform: translateY(0%); +// } + +// 50% { +// opacity: 0.6; +// transform: translateY(-50%); +// } + +// 100% { +// opacity: 1; +// transform: translateY(-100%); +// } +// } .drawer-fade-enter-active { - animation: drawer-fade-in 0.3s linear; + animation: fade-in 0.3s linear; } .drawer-fade-leave-active { - animation: drawer-fade-out 0.3s linear; + animation: fade-out 0.3s linear; } -@keyframes drawer-fade-in { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } -} - -@keyframes drawer-fade-out { - 0% { - opacity: 1; - } - - 100% { - opacity: 0; - } -} +// @keyframes drawer-fade-in { +// 0% { +// opacity: 0; +// } + +// 100% { +// opacity: 1; +// } +// } + +// @keyframes drawer-fade-out { +// 0% { +// opacity: 1; +// } + +// 100% { +// opacity: 0; +// } +// } diff --git a/packages/theme/src/fall-menu/index.less b/packages/theme/src/fall-menu/index.less index e5cf7e3057..ab5fb4814b 100644 --- a/packages/theme/src/fall-menu/index.less +++ b/packages/theme/src/fall-menu/index.less @@ -187,30 +187,31 @@ } } -@keyframes leftArrow { - 0% { - left: -17px; - } - - 50% { - left: -13px; - } - - 100% { - left: -17px; - } -} - -@keyframes rightArrow { - 0% { - right: -17px; - } - - 50% { - right: -13px; - } - - 100% { - right: -17px; - } -} +// notice: The following keyframes are commented out as they are not used in the current implementation. +// @keyframes leftArrow { +// 0% { +// left: -17px; +// } + +// 50% { +// left: -13px; +// } + +// 100% { +// left: -17px; +// } +// } + +// @keyframes rightArrow { +// 0% { +// right: -17px; +// } + +// 50% { +// right: -13px; +// } + +// 100% { +// right: -17px; +// } +// } diff --git a/packages/theme/src/grid/body.less b/packages/theme/src/grid/body.less index ecf2cc17d1..45aead1782 100644 --- a/packages/theme/src/grid/body.less +++ b/packages/theme/src/grid/body.less @@ -11,6 +11,7 @@ */ @import '../custom.less'; +@import '../motion/index.less'; @grid-prefix-cls: ~'@{css-prefix}grid'; @grid-body-prefix-cls: ~'@{css-prefix}grid-body'; @@ -93,12 +94,12 @@ } } -@keyframes shine { - 0% { - background-position: -1px -1px; - } +// @keyframes shine { +// 0% { +// background-position: -1px -1px; +// } - 100% { - background-position: -12px -12px; - } -} +// 100% { +// background-position: -12px -12px; +// } +// } diff --git a/packages/theme/src/grid/excel.less b/packages/theme/src/grid/excel.less index c7671b6ad4..d4093f3498 100644 --- a/packages/theme/src/grid/excel.less +++ b/packages/theme/src/grid/excel.less @@ -11,6 +11,7 @@ */ @import '../custom.less'; +@import '../motion/index.less'; @grid-prefix-cls: ~'@{css-prefix}grid'; @grid-cell-prefix-cls: ~'@{css-prefix}grid-cell'; @@ -80,12 +81,12 @@ } } -@keyframes shine { - 0% { - background-position: -1px -1px; - } +// @keyframes shine { +// 0% { +// background-position: -1px -1px; +// } - 100% { - background-position: -12px -12px; - } -} +// 100% { +// background-position: -12px -12px; +// } +// } diff --git a/packages/theme/src/grid/icon.less b/packages/theme/src/grid/icon.less index 3ffa3fda86..e09d4d2c61 100644 --- a/packages/theme/src/grid/icon.less +++ b/packages/theme/src/grid/icon.less @@ -13,6 +13,7 @@ @import './mixins/common.less'; @import './mixins/icon.less'; @import '../custom.less'; +@import '../motion/index.less'; @grid-icon-prefix-cls: ~'@{css-prefix}grid-icon'; @@ -286,7 +287,7 @@ } &.roll { - animation: rollCircle 1s infinite linear; + animation: rotate-spin 1s infinite linear; } } @@ -385,12 +386,12 @@ } } -@keyframes rollCircle { - 0% { - transform: rotate(0deg); - } +// @keyframes rollCircle { +// 0% { +// transform: rotate(0deg); +// } - 100% { - transform: rotate(360deg); - } -} +// 100% { +// transform: rotate(360deg); +// } +// } diff --git a/packages/theme/src/grid/loading.less b/packages/theme/src/grid/loading.less index 4a5dd55e31..4367bde5e6 100644 --- a/packages/theme/src/grid/loading.less +++ b/packages/theme/src/grid/loading.less @@ -11,6 +11,7 @@ */ @import '../custom.less'; +@import '../motion/index.less'; @grid-loading-prefix-cls: ~'@{css-prefix}grid-loading'; @loading-prefix-cls: ~'@{css-prefix}loading'; @@ -56,18 +57,18 @@ border-radius: 50%; background: linear-gradient(#000, #000); position: absolute; - animation: load 1.04s ease infinite; + animation: grid-loading 1.04s ease infinite; } - @keyframes load { - 0% { - opacity: 10; - } + // @keyframes load { + // 0% { + // opacity: 10; + // } - 100% { - opacity: 0.1; - } - } + // 100% { + // opacity: 0.1; + // } + // } span:nth-child(1) { top: 68%; diff --git a/packages/theme/src/image/index.less b/packages/theme/src/image/index.less index 3d8b558b14..ce377eae55 100644 --- a/packages/theme/src/image/index.less +++ b/packages/theme/src/image/index.less @@ -12,6 +12,7 @@ @import '../custom.less'; @import './vars.less'; +@import '../motion/index.less'; @image-prefix-cls: ~'@{css-prefix}image'; @@ -80,37 +81,37 @@ } .viewer-fade-enter-active { - animation: viewer-fade-in 0.3s; + animation: fade-in-up 0.3s; } .viewer-fade-leave-active { - animation: viewer-fade-out 0.3s; + animation: fade-out-up 0.3s; } -@keyframes viewer-fade-in { - 0% { - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - opacity: 0; - } - - 100% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - opacity: 1; - } -} - -@keyframes viewer-fade-out { - 0% { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - opacity: 1; - } - - 100% { - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - opacity: 0; - } -} +// @keyframes viewer-fade-in { +// 0% { +// -webkit-transform: translate3d(0, -20px, 0); +// transform: translate3d(0, -20px, 0); +// opacity: 0; +// } + +// 100% { +// -webkit-transform: translate3d(0, 0, 0); +// transform: translate3d(0, 0, 0); +// opacity: 1; +// } +// } + +// @keyframes viewer-fade-out { +// 0% { +// -webkit-transform: translate3d(0, 0, 0); +// transform: translate3d(0, 0, 0); +// opacity: 1; +// } + +// 100% { +// -webkit-transform: translate3d(0, -20px, 0); +// transform: translate3d(0, -20px, 0); +// opacity: 0; +// } +// } diff --git a/packages/theme/src/motion/arrow.less b/packages/theme/src/motion/arrow.less new file mode 100644 index 0000000000..14f13257b8 --- /dev/null +++ b/packages/theme/src/motion/arrow.less @@ -0,0 +1,116 @@ +/* =========================== + 箭头移动动画 + 来源: fall-menu carousel-arrow +=========================== */ +@keyframes arrow-left-pulse { + 0% { + left: -17px; + } + + 50% { + left: -13px; + } + + 100% { + left: -17px; + } +} + +@keyframes arrow-right-pulse { + 0% { + right: -17px; + } + + 50% { + right: -13px; + } + + 100% { + right: -17px; + } +} + +@keyframes arrow-right-carousel { + 0% { + opacity: 0; + right: 0; + } + + 100% { + opacity: 1; + transform: translateY(-50%); + right: 16px; + } +} + +@keyframes arrow-left-carousel { + 0% { + opacity: 0; + left: 0; + } + + 100% { + opacity: 1; + transform: translateY(-50%); + left: 16px; + } +} +/* =相关补充= */ + +/* =补充结束= */ + +@keyframes arrow-left-in { + 0% { + opacity: 0; + left: 0; + } + + 100% { + opacity: 1; + transform: translateY(-50%); + left: 16px; + } +} + +@keyframes arrow-right-in { + 0% { + opacity: 0; + right: 0; + } + + 100% { + opacity: 1; + transform: translateY(-50%); + right: 16px; + } +} + +/* =相关补充= */ + +@keyframes arrow-left-out { + 0% { + opacity: 1; + transform: translateY(-50%); + left: 16px; + } + + 100% { + opacity: 0; + left: 0; + } +} + +@keyframes arrow-right-out { + 0% { + opacity: 1; + transform: translateY(-50%); + right: 16px; + } + + 100% { + opacity: 0; + right: 0; + } +} + +/* =补充结束= */ \ No newline at end of file diff --git a/packages/theme/src/motion/bounce.less b/packages/theme/src/motion/bounce.less new file mode 100644 index 0000000000..4b83c892b8 --- /dev/null +++ b/packages/theme/src/motion/bounce.less @@ -0,0 +1,35 @@ +/* =========================== + 缩放弹入动画(统一 bounce-in / scale-in) + 来源: transition-icon +=========================== */ +@keyframes bounce-in { + 0% { + transform: scale(0); + } + + 50% { + transform: scale(1.2); + } + + 100% { + transform: scale(1); + } +} + +/* =相关补充= */ + +@keyframes bounce-out { + 0% { + transform: scale(1); + } + + 50% { + transform: scale(1.2); + } + + 100% { + transform: scale(0); + } +} + +/* =补充结束= */ diff --git a/packages/theme/src/motion/fade.less b/packages/theme/src/motion/fade.less new file mode 100644 index 0000000000..c933ba9c7b --- /dev/null +++ b/packages/theme/src/motion/fade.less @@ -0,0 +1,159 @@ +/* =========================== + 淡入淡出动画 (透明度) + 来源: dialog-box, popup, drawer +=========================== */ +@keyframes fade-in { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes fade-out { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +/* =========================== + 淡入淡出动画 + 向上位移 + 来源: dialog-box, image +=========================== */ +@keyframes fade-in-up { + 0% { + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + opacity: 0; + } + + 100% { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes fade-out-up { + 0% { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + opacity: 1; + } + + 100% { + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + opacity: 0; + } +} + +/* =相关补充= */ + +@keyframes fade-in-down { + 0% { + transform: translate3d(0, 20px, 0); + opacity: 0; + } + + 100% { + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes fade-out-down { + 0% { + transform: translate3d(0, 0, 0); + opacity: 1; + } + + 100% { + transform: translate3d(0, 20px, 0); + opacity: 0; + } +} + +@keyframes fade-in-left { + 0% { + transform: translate3d(-20px, 0, 0); + opacity: 0; + } + + 100% { + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes fade-out-left { + 0% { + transform: translate3d(0, 0, 0); + opacity: 1; + } + + 100% { + transform: translate3d(-20px, 0, 0); + opacity: 0; + } +} + +@keyframes fade-in-right { + 0% { + transform: translate3d(20px, 0, 0); + opacity: 0; + } + + 100% { + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes fade-out-right { + 0% { + transform: translate3d(0, 0, 0); + opacity: 1; + } + + 100% { + transform: translate3d(20px, 0, 0); + opacity: 0; + } +} + +/* =补充结束= */ + +/* =========================== + timepicker 面板进入动画 + 来源: transition-timepicker +=========================== */ +@keyframes fade-in-timepicker { + 0% { + transform: translateY(-200px); + z-index: -999; + } + + 100% { + transform: translateY(0); + z-index: 0; + } +} + +@keyframes fade-up-timepicker { + 0% { + transform: translateY(200px); + z-index: -999; + } + + 100% { + transform: translateY(0); + z-index: 0; + } +} \ No newline at end of file diff --git a/packages/theme/src/motion/index.less b/packages/theme/src/motion/index.less new file mode 100644 index 0000000000..adf531ea94 --- /dev/null +++ b/packages/theme/src/motion/index.less @@ -0,0 +1,17 @@ +@import './rotate.less'; +@import './fade.less'; +@import './zoom.less'; +@import './bounce.less'; + +@import './slide.less'; +@import './tab.less'; +@import './arrow.less'; + +@import './stroke.less'; +@import './scroll.less'; +@import './progress.less'; + +@import './skeleton.less'; +@import './shine.less'; + + diff --git a/packages/theme/src/motion/progress.less b/packages/theme/src/motion/progress.less new file mode 100644 index 0000000000..7991c73dbb --- /dev/null +++ b/packages/theme/src/motion/progress.less @@ -0,0 +1,22 @@ +/* =========================== + 进度条流动背景 + 来源: progress +=========================== */ +@keyframes progress-background { + 0% { + background-position: 0 0; + } + + 100% { + background-position: 32px 0; + } +} +@-webkit-keyframes progress-background { + 0% { + background-position: 0 0; + } + + 100% { + background-position: 32px 0; + } +} diff --git a/packages/theme/src/motion/rotate.less b/packages/theme/src/motion/rotate.less new file mode 100644 index 0000000000..312e473c94 --- /dev/null +++ b/packages/theme/src/motion/rotate.less @@ -0,0 +1,30 @@ +/* =========================== + 通用旋转 + 进度加载动画 + 来源: chart-core, tree +=========================== */ +@keyframes rotate-spin { + // chart-core:loading-rotate,tree:loading-rotate + 100% { + transform: rotate(360deg); + } +} + +@keyframes rotate-z { + 0% { + transform: rotateZ(0deg); + } + + 100% { + transform: rotateZ(360deg); + } +} + +/* ==========相关补充=========== */ + +@keyframes rotate-reverse { + 100% { + transform: rotate(-360deg); + } +} + +/* =========================== */ \ No newline at end of file diff --git a/packages/theme/src/motion/scroll.less b/packages/theme/src/motion/scroll.less new file mode 100644 index 0000000000..05d61bd9c5 --- /dev/null +++ b/packages/theme/src/motion/scroll.less @@ -0,0 +1,103 @@ +/* =========================== + 滚动文字动画 + 来源: scroll-text +=========================== */ +@keyframes scroll-left { + 0% { + transform: translateX(300px); + } + + 100% { + transform: translateX(-100%); + } +} + +@keyframes scroll-right { + 0% { + transform: translateX(-100%); + } + + 100% { + transform: translateX(300px); + } +} + +@keyframes scroll-up { + 0% { + transform: translateY(100%); + } + + 100% { + transform: translateY(-100%); + } +} + +@keyframes scroll-down { + 0% { + transform: translateY(-100%); + } + + 100% { + transform: translateY(100%); + } +} + +@keyframes scroll-left-adapt { + 0% { + transform: translateX(100%); + } + + 50% { + transform: translateX(0); + } + + 100% { + transform: translateX(-100%); + } +} + +@keyframes scroll-right-adapt { + 0% { + transform: translateX(-100%); + } + + 50% { + transform: translateX(0); + } + + 100% { + transform: translateX(100%); + } +} + +/* =相关补充= */ + +@keyframes scroll-up-adapt { + 0% { + transform: translateY(100%); + } + + 50% { + transform: translateY(0); + } + + 100% { + transform: translateY(-100%); + } +} + +@keyframes scroll-down-adapt { + 0% { + transform: translateY(-100%); + } + + 50% { + transform: translateY(0); + } + + 100% { + transform: translateY(100%); + } +} + +/* =补充结束= */ \ No newline at end of file diff --git a/packages/theme/src/motion/shine.less b/packages/theme/src/motion/shine.less new file mode 100644 index 0000000000..2df4609737 --- /dev/null +++ b/packages/theme/src/motion/shine.less @@ -0,0 +1,10 @@ +//grid-body +@keyframes shine { + 0% { + background-position: -1px -1px; + } + + 100% { + background-position: -12px -12px; + } +} \ No newline at end of file diff --git a/packages/theme/src/motion/skeleton.less b/packages/theme/src/motion/skeleton.less new file mode 100644 index 0000000000..b00c2c0ed1 --- /dev/null +++ b/packages/theme/src/motion/skeleton.less @@ -0,0 +1,19 @@ +/* =========================== + 骨架屏、加载等 + 来源: skeleton-item, grid-loading +=========================== */ +@keyframes skeleton-loading { + to { + background-position-x: -20%; + } +} + +@keyframes grid-loading { + 0% { + opacity: 10; + } + + 100% { + opacity: 0.1; + } +} diff --git a/packages/theme/src/motion/slide.less b/packages/theme/src/motion/slide.less new file mode 100644 index 0000000000..14363f94a0 --- /dev/null +++ b/packages/theme/src/motion/slide.less @@ -0,0 +1,139 @@ +/* =========================== + 抽屉/对话框 滑动方向动画 + 来源: dialog-box, drawer +=========================== */ +@keyframes slide-left-in { + 0% { + opacity: 0; + transform: translateX(-100%); + } + + 50% { + opacity: 0.6; + transform: translateX(-50%); + } + + 100% { + opacity: 1; + transform: translateX(0%); + } +} + +@keyframes slide-left-out { + 0% { + opacity: 1; + transform: translateX(0%); + } + + 50% { + opacity: 0.6; + transform: translateX(-50%); + } + + 100% { + opacity: 0; + transform: translateX(-100%); + } +} + +@keyframes slide-right-in { + 0% { + opacity: 0; + transform: translateX(100%); + } + + 50% { + opacity: 0.6; + transform: translateX(50%); + } + + 100% { + opacity: 1; + transform: translateX(0%); + } +} + +@keyframes slide-right-out { + 0% { + opacity: 1; + transform: translateX(0%); + } + + 50% { + opacity: 0.6; + transform: translateX(50%); + } + + 100% { + opacity: 0; + transform: translateX(100%); + } +} + +@keyframes slide-top-in { + 0% { + opacity: 0; + transform: translateY(-100%); + } + + 50% { + opacity: 0.6; + transform: translateY(-50%); + } + + 100% { + opacity: 1; + transform: translateY(0%); + } +} + +@keyframes slide-top-out { + 0% { + opacity: 0; + transform: translateY(0%); + } + + 50% { + opacity: 0.6; + transform: translateY(-50%); + } + + 100% { + opacity: 1; + transform: translateY(-100%); + } +} + +@keyframes slide-bottom-in { + 0% { + opacity: 0; + transform: translateY(100%); + } + + 50% { + opacity: 0.6; + transform: translateY(50%); + } + + 100% { + opacity: 1; + transform: translateY(0%); + } +} + +@keyframes slide-bottom-out { + 0% { + opacity: 0; + transform: translateY(0%); + } + + 50% { + opacity: 0.6; + transform: translateY(50%); + } + + 100% { + opacity: 1; + transform: translateY(100%); + } +} \ No newline at end of file diff --git a/packages/theme/src/motion/stroke.less b/packages/theme/src/motion/stroke.less new file mode 100644 index 0000000000..20e383f7ac --- /dev/null +++ b/packages/theme/src/motion/stroke.less @@ -0,0 +1,38 @@ +@keyframes stroke-dash-loop { + // chart-core:loading-dash,tree:loading-dash + 0% { + stroke-dasharray: 1, 200; + stroke-dashoffset: 0; + } + + 50% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -40px; + } + + 100% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -120px; + } +} + +/* =相关补充= */ + +@keyframes stroke-dash-reverse { + 0% { + stroke-dasharray: 1, 200; + stroke-dashoffset: 0; + } + + 50% { + stroke-dasharray: 90, 150; + stroke-dashoffset: 40px; + } + + 100% { + stroke-dasharray: 90, 150; + stroke-dashoffset: 120px; + } +} + +/* =补充结束= */ \ No newline at end of file diff --git a/packages/theme/src/motion/tab.less b/packages/theme/src/motion/tab.less new file mode 100644 index 0000000000..8cdc3502dd --- /dev/null +++ b/packages/theme/src/motion/tab.less @@ -0,0 +1,111 @@ +/* =========================== + Tab切换动画 (保留 enter/leave) + 来源: tabs +=========================== */ +@keyframes tab-slide-right-in { + 0% { + opacity: 0; + transform-origin: 0 0; + transform: translateX(100%); + } + + 100% { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes tab-slide-right-out { + 0% { + transform-origin: 0 0; + transform: translateX(0); + opacity: 1; + } + + 100% { + transform: translateX(100%); + opacity: 0; + } +} + +@keyframes tab-slide-left-in { + 0% { + opacity: 0; + transform-origin: 0 0; + transform: translateX(-100%); + } + + 100% { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes tab-slide-left-out { + 0% { + transform-origin: 0 0; + transform: translateX(0); + opacity: 1; + } + + 100% { + transform: translateX(-100%); + opacity: 0; + } +} + +/* =相关补充= */ + +@keyframes tab-slide-up-in { + 0% { + opacity: 0; + transform-origin: 0 0; + transform: translateY(100%); + } + + 100% { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes tab-slide-up-out { + 0% { + transform-origin: 0 0; + transform: translateY(0); + opacity: 1; + } + + 100% { + transform: translateY(100%); + opacity: 0; + } +} + +@keyframes tab-slide-down-in { + 0% { + opacity: 0; + transform-origin: 0 0; + transform: translateY(-100%); + } + + 100% { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes tab-slide-down-out { + 0% { + transform-origin: 0 0; + transform: translateY(0); + opacity: 1; + } + + 100% { + transform: translateY(-100%); + opacity: 0; + } +} + +/* =补充结束= */ \ No newline at end of file diff --git a/packages/theme/src/motion/zoom.less b/packages/theme/src/motion/zoom.less new file mode 100644 index 0000000000..339c3e9d25 --- /dev/null +++ b/packages/theme/src/motion/zoom.less @@ -0,0 +1,69 @@ +/* =========================== + 弹出缩放动画 + 来源: dialog-box +=========================== */ +@keyframes enlarge-in { + 0% { + transform: scale(0); + } + + 50% { + transform: scale(0.5); + } + + 100% { + transform: scale(1); + } +} + +/* =相关补充= */ + +@keyframes enlarge-in-fade { + 0% { + transform: scale(0); + opacity: 0; + } + + 50% { + transform: scale(0.5); + opacity: 0.5; + } + + 100% { + transform: scale(1); + opacity: 1; + } +} + +@keyframes shrink-out { + 0% { + transform: scale(1); + } + + 50% { + transform: scale(0.5); + } + + 100% { + transform: scale(0); + } +} + +@keyframes shrink-out-fade { + 0% { + transform: scale(1); + opacity: 1; + } + + 50% { + transform: scale(0.5); + opacity: 0.5; + } + + 100% { + transform: scale(0); + opacity: 0; + } +} + +/* =补充结束= */ \ No newline at end of file diff --git a/packages/theme/src/popup/index.less b/packages/theme/src/popup/index.less index 795112ee48..96df9ba9a2 100644 --- a/packages/theme/src/popup/index.less +++ b/packages/theme/src/popup/index.less @@ -11,6 +11,7 @@ */ @import '../custom.less'; +@import '../motion/index.less'; @fade-prefix-cls: ~'@{css-prefix}fade'; @popup-prefix-cls: ~'@{css-prefix}popup'; @@ -18,11 +19,11 @@ .@{fade-prefix-cls} { &-enter-active { - animation: 0.3s mobile-fade-in both ease-out; + animation: 0.3s fade-in both ease-out; } &-leave-active { - animation: 0.3s mobile-fade-out both ease-in; + animation: 0.3s fade-out both ease-in; } } @@ -158,22 +159,22 @@ } } -@keyframes mobile-fade-in { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -@keyframes mobile-fade-out { - from { - opacity: 1; - } - - to { - opacity: 0; - } -} +// @keyframes mobile-fade-in { +// from { +// opacity: 0; +// } + +// to { +// opacity: 1; +// } +// } + +// @keyframes mobile-fade-out { +// from { +// opacity: 1; +// } + +// to { +// opacity: 0; +// } +// } diff --git a/packages/theme/src/progress/index.less b/packages/theme/src/progress/index.less index ae3d9d8ec8..fe415eb822 100644 --- a/packages/theme/src/progress/index.less +++ b/packages/theme/src/progress/index.less @@ -12,6 +12,7 @@ @import '../custom.less'; @import './vars.less'; +@import '../motion/index.less'; @progress-prefix-cls: ~'@{css-prefix}progress'; @@ -146,22 +147,23 @@ } } -@-webkit-keyframes progress { - 0% { - background-position: 0 0; - } - - 100% { - background-position: 32px 0; - } -} - -@keyframes progress { - 0% { - background-position: 0 0; - } - - 100% { - background-position: 32px 0; - } -} +// notice: not used +// @-webkit-keyframes progress { +// 0% { +// background-position: 0 0; +// } + +// 100% { +// background-position: 32px 0; +// } +// } + +// @keyframes progress { +// 0% { +// background-position: 0 0; +// } + +// 100% { +// background-position: 32px 0; +// } +// } diff --git a/packages/theme/src/scroll-text/index.less b/packages/theme/src/scroll-text/index.less index 1e3d52123a..68263bf1b9 100644 --- a/packages/theme/src/scroll-text/index.less +++ b/packages/theme/src/scroll-text/index.less @@ -12,6 +12,7 @@ @import '../custom.less'; @import './vars.less'; +@import '../motion/index.less'; @scroll-text-prefix-cls: ~'@{css-prefix}scroll-text'; @@ -51,19 +52,19 @@ justify-content: center; &.left { - animation-name: moveLeft; + animation-name: scroll-left; } &.right { - animation-name: moveRight; + animation-name: scroll-right; } &.up { - animation-name: moveUp; + animation-name: scroll-up; } &.down { - animation-name: moveDown; + animation-name: scroll-down; } &.singleUp { @@ -98,81 +99,81 @@ > div.left { min-width: 100%; - animation-name: moveLeftWidthAdapt; + animation-name: scroll-left-adapt; } > div.right { min-width: 100%; - animation-name: moveRightWidthAdapt; + animation-name: scroll-right-adapt; } } } } -@keyframes moveLeft { - 0% { - transform: translateX(300px); - } - - 100% { - transform: translateX(-100%); - } -} - -@keyframes moveRight { - 0% { - transform: translateX(-100%); - } - - 100% { - transform: translateX(300px); - } -} - -@keyframes moveUp { - 0% { - transform: translateY(100%); - } - - 100% { - transform: translateY(-100%); - } -} - -@keyframes moveDown { - 0% { - transform: translateY(-100%); - } - - 100% { - transform: translateY(100%); - } -} - -@keyframes moveLeftWidthAdapt { - 0% { - transform: translateX(100%); - } - - 50% { - transform: translateX(0); - } - - 100% { - transform: translateX(-100%); - } -} - -@keyframes moveRightWidthAdapt { - 0% { - transform: translateX(-100%); - } - - 50% { - transform: translateX(0); - } - - 100% { - transform: translateX(100%); - } -} +// @keyframes moveLeft { +// 0% { +// transform: translateX(300px); +// } + +// 100% { +// transform: translateX(-100%); +// } +// } + +// @keyframes moveRight { +// 0% { +// transform: translateX(-100%); +// } + +// 100% { +// transform: translateX(300px); +// } +// } + +// @keyframes moveUp { +// 0% { +// transform: translateY(100%); +// } + +// 100% { +// transform: translateY(-100%); +// } +// } + +// @keyframes moveDown { +// 0% { +// transform: translateY(-100%); +// } + +// 100% { +// transform: translateY(100%); +// } +// } + +// @keyframes moveLeftWidthAdapt { +// 0% { +// transform: translateX(100%); +// } + +// 50% { +// transform: translateX(0); +// } + +// 100% { +// transform: translateX(-100%); +// } +// } + +// @keyframes moveRightWidthAdapt { +// 0% { +// transform: translateX(-100%); +// } + +// 50% { +// transform: translateX(0); +// } + +// 100% { +// transform: translateX(100%); +// } +// } diff --git a/packages/theme/src/tabs/index.less b/packages/theme/src/tabs/index.less index 28e432186a..066dec9bb2 100644 --- a/packages/theme/src/tabs/index.less +++ b/packages/theme/src/tabs/index.less @@ -12,6 +12,7 @@ @import '../custom.less'; @import './vars.less'; +@import '../motion/index.less'; @tabs-prefix-cls: ~'@{css-prefix}tabs'; @tab-pane-prefix-cls: ~'@{css-prefix}tab-pane'; @@ -1325,7 +1326,7 @@ .slideInRight-enter { -webkit-animation: slideInRight-enter 0.3s; - animation: slideInRight-enter 0.3s; + animation: tab-slide-right-in 0.3s; } .slideInRight-leave { @@ -1333,12 +1334,12 @@ left: 0; right: 0; -webkit-animation: slideInRight-leave 0.3s; - animation: slideInRight-leave 0.3s; + animation: tab-slide-right-out 0.3s; } .slideInLeft-enter { -webkit-animation: slideInLeft-enter 0.3s; - animation: slideInLeft-enter 0.3s; + animation: tab-slide-left-in 0.3s; } .slideInLeft-leave { @@ -1346,150 +1347,150 @@ left: 0; right: 0; -webkit-animation: slideInLeft-leave 0.3s; - animation: slideInLeft-leave 0.3s; + animation: tab-slide-left-out 0.3s; } - @-webkit-keyframes slideInRight-enter { - 0% { - opacity: 0; - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(100%); - transform: translateX(100%); - } - - to { - opacity: 1; - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(0); - transform: translateX(0); - } - } - - @keyframes slideInRight-enter { - 0% { - opacity: 0; - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(100%); - transform: translateX(100%); - } - - to { - opacity: 1; - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(0); - transform: translateX(0); - } - } - - @-webkit-keyframes slideInRight-leave { - 0% { - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(0); - transform: translateX(0); - opacity: 1; - } - - 100% { - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(100%); - transform: translateX(100%); - opacity: 0; - } - } - - @keyframes slideInRight-leave { - 0% { - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(0); - transform: translateX(0); - opacity: 1; - } - - 100% { - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(100%); - transform: translateX(100%); - opacity: 0; - } - } - - @-webkit-keyframes slideInLeft-enter { - 0% { - opacity: 0; - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(-100%); - transform: translateX(-100%); - } - - to { - opacity: 1; - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(0); - transform: translateX(0); - } - } - - @keyframes slideInLeft-enter { - 0% { - opacity: 0; - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(-100%); - transform: translateX(-100%); - } - - to { - opacity: 1; - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(0); - transform: translateX(0); - } - } - - @-webkit-keyframes slideInLeft-leave { - 0% { - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(0); - transform: translateX(0); - opacity: 1; - } - - 100% { - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(-100%); - transform: translateX(-100%); - opacity: 0; - } - } - - @keyframes slideInLeft-leave { - 0% { - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(0); - transform: translateX(0); - opacity: 1; - } - - 100% { - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - -webkit-transform: translateX(-100%); - transform: translateX(-100%); - opacity: 0; - } - } -} \ No newline at end of file +// @-webkit-keyframes slideInRight-enter { +// 0% { +// opacity: 0; +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(100%); +// transform: translateX(100%); +// } + +// to { +// opacity: 1; +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(0); +// transform: translateX(0); +// } +// } + +// @keyframes slideInRight-enter { +// 0% { +// opacity: 0; +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(100%); +// transform: translateX(100%); +// } + +// to { +// opacity: 1; +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(0); +// transform: translateX(0); +// } +// } + +// @-webkit-keyframes slideInRight-leave { +// 0% { +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(0); +// transform: translateX(0); +// opacity: 1; +// } + +// 100% { +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(100%); +// transform: translateX(100%); +// opacity: 0; +// } +// } + +// @keyframes slideInRight-leave { +// 0% { +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(0); +// transform: translateX(0); +// opacity: 1; +// } + +// 100% { +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(100%); +// transform: translateX(100%); +// opacity: 0; +// } +// } + +// @-webkit-keyframes slideInLeft-enter { +// 0% { +// opacity: 0; +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(-100%); +// transform: translateX(-100%); +// } + +// to { +// opacity: 1; +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(0); +// transform: translateX(0); +// } +// } + +// @keyframes slideInLeft-enter { +// 0% { +// opacity: 0; +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(-100%); +// transform: translateX(-100%); +// } + +// to { +// opacity: 1; +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(0); +// transform: translateX(0); +// } +// } + +// @-webkit-keyframes slideInLeft-leave { +// 0% { +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(0); +// transform: translateX(0); +// opacity: 1; +// } + +// 100% { +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(-100%); +// transform: translateX(-100%); +// opacity: 0; +// } +// } + +// @keyframes slideInLeft-leave { +// 0% { +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(0); +// transform: translateX(0); +// opacity: 1; +// } + +// 100% { +// -webkit-transform-origin: 0 0; +// transform-origin: 0 0; +// -webkit-transform: translateX(-100%); +// transform: translateX(-100%); +// opacity: 0; +// } +// } +// } \ No newline at end of file diff --git a/packages/theme/src/transition/carousel-arrow.less b/packages/theme/src/transition/carousel-arrow.less index b6faacb839..c2547fc74b 100644 --- a/packages/theme/src/transition/carousel-arrow.less +++ b/packages/theme/src/transition/carousel-arrow.less @@ -11,6 +11,7 @@ */ @import '../custom.less'; +@import '../motion/index.less'; .@{css-prefix}transition-carousel-arrow-left-enter, .@{css-prefix}transition-carousel-arrow-left-enter-from, @@ -20,11 +21,11 @@ } .@{css-prefix}transition-carousel-arrow-left-enter-active { - animation: animation-left 0.3s; + animation: arrow-left-carousel 0.3s; } .@{css-prefix}transition-carousel-arrow-left-leave-active { - animation: animation-left 0.3s reverse; + animation: arrow-left-carousel 0.3s reverse; } .@{css-prefix}transition-carousel-arrow-right-enter, @@ -35,35 +36,35 @@ } .@{css-prefix}transition-carousel-arrow-right-enter-active { - animation: animation-right 0.3s; + animation: arrow-right-carousel 0.3s; } .@{css-prefix}transition-carousel-arrow-right-leave-active { - animation: animation-right 0.3s reverse; + animation: arrow-right-carousel 0.3s reverse; } -@keyframes animation-right { - 0% { - opacity: 0; - right: 0; - } +// @keyframes animation-right { +// 0% { +// opacity: 0; +// right: 0; +// } - 100% { - opacity: 1; - transform: translateY(-50%); - right: 16px; - } -} +// 100% { +// opacity: 1; +// transform: translateY(-50%); +// right: 16px; +// } +// } -@keyframes animation-left { - 0% { - opacity: 0; - left: 0; - } +// @keyframes animation-left { +// 0% { +// opacity: 0; +// left: 0; +// } - 100% { - opacity: 1; - transform: translateY(-50%); - left: 16px; - } -} +// 100% { +// opacity: 1; +// transform: translateY(-50%); +// left: 16px; +// } +// } diff --git a/packages/theme/src/transition/icon.less b/packages/theme/src/transition/icon.less index 6a94e8c0e1..c1cdcf5348 100644 --- a/packages/theme/src/transition/icon.less +++ b/packages/theme/src/transition/icon.less @@ -11,6 +11,7 @@ */ @import '../custom.less'; +@import '../motion/index.less'; // input右边icon显示隐藏动画 .@{css-prefix}transition-icon-out-in-enter-active { @@ -22,37 +23,37 @@ } .@{css-prefix}transition-icon-scale-in-enter-active { - animation: scale-in 0.3s; + animation: bounce-in 0.3s; } .@{css-prefix}transition-icon-scale-in-leave-active { - animation: scale-in 0.3s reverse; -} - -@keyframes bounce-in { - 0% { - transform: scale(0); - } - - 50% { - transform: scale(1.2); - } - - 100% { - transform: scale(1); - } + animation: bounce-in 0.3s reverse; } -@keyframes scale-in { - 0% { - transform: scale(0); - } - - 50% { - transform: scale(1.2); - } - - 100% { - transform: scale(1); - } -} +// @keyframes bounce-in { +// 0% { +// transform: scale(0); +// } + +// 50% { +// transform: scale(1.2); +// } + +// 100% { +// transform: scale(1); +// } +// } + +// @keyframes scale-in { +// 0% { +// transform: scale(0); +// } + +// 50% { +// transform: scale(1.2); +// } + +// 100% { +// transform: scale(1); +// } +// } diff --git a/packages/theme/src/transition/timepicker.less b/packages/theme/src/transition/timepicker.less index 81d25ce8c9..1d2548e607 100644 --- a/packages/theme/src/transition/timepicker.less +++ b/packages/theme/src/transition/timepicker.less @@ -11,35 +11,36 @@ */ @import '../custom.less'; +@import '../motion/index.less'; .@{css-prefix}transition-timepicker { - animation: fadein 0.3s; + animation: fade-in-timepicker 0.3s; } .@{css-prefix}transition-timepicker-up { - animation: fadeup 0.3s; + animation: fade-up-timepicker 0.3s; } -@keyframes fadein { - 0% { - transform: translateY(-200px); - z-index: -999; - } +// @keyframes fadein { +// 0% { +// transform: translateY(-200px); +// z-index: -999; +// } - 100% { - transform: translateY(0); - z-index: 0; - } -} +// 100% { +// transform: translateY(0); +// z-index: 0; +// } +// } -@keyframes fadeup { - 0% { - transform: translateY(200px); - z-index: -999; - } +// @keyframes fadeup { +// 0% { +// transform: translateY(200px); +// z-index: -999; +// } - 100% { - transform: translateY(0); - z-index: 0; - } -} +// 100% { +// transform: translateY(0); +// z-index: 0; +// } +// } diff --git a/packages/theme/src/tree/index.less b/packages/theme/src/tree/index.less index 37e209ab28..fa2ce9769b 100644 --- a/packages/theme/src/tree/index.less +++ b/packages/theme/src/tree/index.less @@ -12,6 +12,7 @@ @import '../custom.less'; @import './vars.less'; +@import '../motion/index.less'; @tree-prefix-cls: ~'@{css-prefix}tree'; @tree-node-prefix-cls: ~'@{css-prefix}tree-node'; @@ -477,25 +478,26 @@ } } -@keyframes loading-rotate { - 100% { - transform: rotate(360deg); - } -} - -@keyframes loading-dash { - 0% { - stroke-dasharray: 1, 200; - stroke-dashoffset: 0; - } - - 50% { - stroke-dasharray: 90, 150; - stroke-dashoffset: -40px; - } - - 100% { - stroke-dasharray: 90, 150; - stroke-dashoffset: -120px; - } -} +// notice: not used +// @keyframes { +// 100% { +// transform: rotate(360deg); +// } +// } + +// @keyframes loading-dash { +// 0% { +// stroke-dasharray: 1, 200; +// stroke-dashoffset: 0; +// } + +// 50% { +// stroke-dasharray: 90, 150; +// stroke-dashoffset: -40px; +// } + +// 100% { +// stroke-dasharray: 90, 150; +// stroke-dashoffset: -120px; +// } +// } From bb8ea19589291d2b75fc2d96563daaae3419fee2 Mon Sep 17 00:00:00 2001 From: Lyra <1170158548@qq.com> Date: Thu, 14 Aug 2025 21:36:10 +0800 Subject: [PATCH 2/7] fix(tag): fix the index.less --- packages/theme/src/tabs/index.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/theme/src/tabs/index.less b/packages/theme/src/tabs/index.less index 066dec9bb2..58d5053840 100644 --- a/packages/theme/src/tabs/index.less +++ b/packages/theme/src/tabs/index.less @@ -1349,7 +1349,7 @@ -webkit-animation: slideInLeft-leave 0.3s; animation: tab-slide-left-out 0.3s; } - +} // @-webkit-keyframes slideInRight-enter { // 0% { // opacity: 0; From cac59e841c280157e24cd59538772d003b3db190 Mon Sep 17 00:00:00 2001 From: Lyra <1170158548@qq.com> Date: Sun, 31 Aug 2025 22:41:58 +0800 Subject: [PATCH 3/7] feat(theme): [motion] add global animation variables --- packages/theme/src/base/reset.less | 3 +- packages/theme/src/base/vars.less | 97 ++++++++ packages/theme/src/chart-core/index.less | 5 +- packages/theme/src/dialog-box/index.less | 17 +- packages/theme/src/drawer/index.less | 16 +- packages/theme/src/grid/body.less | 24 +- packages/theme/src/grid/icon.less | 2 +- packages/theme/src/grid/loading.less | 3 +- packages/theme/src/image/index.less | 4 +- ...50\346\225\210\351\205\215\347\275\256.md" | 224 ++++++++++++++++++ ...15\347\275\256\347\273\264\346\212\244.md" | 135 +++++++++++ packages/theme/src/motion/ants.less | 39 +++ packages/theme/src/motion/arrow.less | 54 ++--- packages/theme/src/motion/bounce.less | 31 +-- packages/theme/src/motion/fade.less | 58 ++--- packages/theme/src/motion/index.less | 15 +- packages/theme/src/motion/loading.less | 26 ++ packages/theme/src/motion/progress.less | 14 +- packages/theme/src/motion/rotate.less | 20 +- packages/theme/src/motion/scroll.less | 55 ++--- packages/theme/src/motion/shine.less | 18 +- packages/theme/src/motion/skeleton.less | 19 -- packages/theme/src/motion/slide.less | 86 ++++--- packages/theme/src/motion/stroke.less | 50 ++-- packages/theme/src/motion/tab.less | 93 ++++---- packages/theme/src/motion/zoom.less | 61 +++-- packages/theme/src/popup/index.less | 4 +- packages/theme/src/skeleton-item/index.less | 9 +- packages/theme/src/tabs/index.less | 28 +-- .../theme/src/transition/carousel-arrow.less | 4 +- packages/theme/src/transition/icon.less | 8 +- packages/theme/src/transition/timepicker.less | 4 +- 32 files changed, 859 insertions(+), 367 deletions(-) create mode 100644 "packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256.md" create mode 100644 "packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256\347\273\264\346\212\244.md" create mode 100644 packages/theme/src/motion/ants.less create mode 100644 packages/theme/src/motion/loading.less delete mode 100644 packages/theme/src/motion/skeleton.less diff --git a/packages/theme/src/base/reset.less b/packages/theme/src/base/reset.less index afed5060ce..4905b39ced 100644 --- a/packages/theme/src/base/reset.less +++ b/packages/theme/src/base/reset.less @@ -16,8 +16,9 @@ // .tiny-icon-loading 类名的动画效果。 它出现在多个组件中,故抽取到一起。 .@{css-prefix-iconfont}-loading { + --tv-motion-rotate-speed: 2s; line-height: 1; - animation: rotate-z 2s linear infinite; + animation: rotate-z var(--tv-motion-rotate-speed) linear infinite; } // @keyframes rotating { diff --git a/packages/theme/src/base/vars.less b/packages/theme/src/base/vars.less index 4339ba352e..1e1ec03888 100644 --- a/packages/theme/src/base/vars.less +++ b/packages/theme/src/base/vars.less @@ -522,4 +522,101 @@ --tv-color-bg-scrollbar-thumb-hover: var(--tv-base-color-common-6); // #dbdbdb 滑块hover背景色 --tv-color-bg-scrollbar-thumb-active: var(--tv-base-color-common-6); // #dbdbdb 滑块active背景色 --tv-color-bg-scrollbar-track: var(--tv-base-color-common-1); // #fff 轨道背景色 + + /** 10. 动画变量 **/ + /* ---------- 蚂蚁线 (ants.less) ---------- */ + --tv-motion-ants-shift: 8px; /* 单次偏移距离 */ + --tv-motion-ants-speed: 0.8s; /* 动画时长 */ + + /* ---------- 箭头移动 (arrow.less) ---------- */ + --tv-motion-arrow-offset: 16px; /* 箭头最终位移 */ + --tv-motion-arrow-left-init: -17px; /* 左侧初始位置 */ + --tv-motion-arrow-left-mid: -13px; /* 左侧 pulse 中间位置 */ + --tv-motion-arrow-right-init: -17px; /* 右侧初始位置 */ + --tv-motion-arrow-right-mid: -13px; /* 右侧 pulse 中间位置 */ + --tv-motion-arrow-speed: 0.3s; /* 箭头动画时长 */ + + /* ---------- 缩放弹入 (bounce.less) ---------- */ + --tv-motion-bounce-scale-min: 0; /* 初始缩小比例 */ + --tv-motion-bounce-scale-mid: 1.2; /* 弹入/弹出中间比例 */ + --tv-motion-bounce-scale-max: 1; /* 最终展开比例 */ + --tv-motion-bounce-speed: 0.3s; /* 动画时长 */ + + /* ---------- 淡入淡出 (fade.less) ---------- */ + --tv-motion-fade-offset-x: 20px; /* X轴位移 */ + --tv-motion-fade-offset-y: 20px; /* Y轴位移 */ + --tv-motion-fade-speed: 0.3s; /* 动画时长 */ + + /* ---------- 加载动画 (loading.less) ---------- */ + /* 骨架屏 */ + --tv-motion-skeleton-speed: 1.5s; /* 骨架屏动画时长 */ + --tv-motion-skeleton-background-offset: -20%; /* 背景流动偏移 */ + /* 网格加载 */ + --tv-motion-grid-loading-speed: 1.5s; /* 网格加载动画时长 */ + --tv-motion-grid-loading-opacity: 0.1; /* 网格加载最终透明度 */ + + /* ---------- 进度条背景 (progress.less) ---------- */ + --tv-motion-progress-background-shift: 32px; /* 背景流动位移 */ + --tv-motion-progress-speed: 1s; /* 动画时长 */ + + /* ---------- 通用旋转 (rotate.less) ---------- */ + --tv-motion-rotate-speed: 1s; /* 旋转动画时长 */ + --tv-motion-rotate-degrees: 360deg; /* 旋转角度 */ + + /* ---------- 滚动文字 (scroll.less) ---------- */ + --tv-motion-scroll-speed: 3s; /* 动画时长 */ + --tv-motion-scroll-offset-x: 300px; /* X轴初始位移 */ + --tv-motion-scroll-offset-x-end: -100%; /* X轴结束位移 */ + --tv-motion-scroll-offset-y: 100%; /* Y轴初始位移 */ + --tv-motion-scroll-offset-y-end: -100%; /* Y轴结束位移 */ + + /* ---------- 光泽闪烁 (shine.less) ---------- */ + --tv-motion-shine-speed: 1s; /* 动画时长 */ + --tv-motion-shine-offset-x: -12px; /* X轴背景位移 */ + --tv-motion-shine-offset-y: -12px; /* Y轴背景位移 */ + + /* ---------- 滑动方向 (slide.less) ---------- */ + --tv-motion-slide-speed: 0.3s; /* 动画时长 */ + --tv-motion-slide-opacity-mid: 0.6; /* 中间透明度 */ + /* X轴偏移 */ + --tv-motion-slide-offset-left: -100%; /* 左侧初始位移 */ + --tv-motion-slide-offset-left-mid: -50%; /* 左侧中间位移 */ + --tv-motion-slide-offset-right: 100%; /* 右侧初始位移 */ + --tv-motion-slide-offset-right-mid: 50%; /* 右侧中间位移 */ + /* Y轴偏移 */ + --tv-motion-slide-offset-top: -100%; /* 顶部初始位移 */ + --tv-motion-slide-offset-top-mid: -50%; /* 顶部中间位移 */ + --tv-motion-slide-offset-bottom: 100%; /* 底部初始位移 */ + --tv-motion-slide-offset-bottom-mid: 50%; /* 底部中间位移 */ + + /* ---------- 描边循环 (stroke.less) ---------- */ + --tv-motion-stroke-speed: 1.5s; /* 动画时长 */ + --tv-motion-stroke-dasharray-0: 1, 200; /* 初始 dasharray */ + --tv-motion-stroke-dasharray-50: 90, 150; /* 中间 dasharray */ + --tv-motion-stroke-dasharray-100: 90, 150; /* 结束 dasharray */ + --tv-motion-stroke-offset-0: 0; /* 初始 dashoffset */ + --tv-motion-stroke-offset-50: -40px; /* 中间 dashoffset */ + --tv-motion-stroke-offset-100: -120px; /* 结束 dashoffset */ + --tv-motion-stroke-offset-reverse-50: 40px; /* 反向中间 dashoffset */ + --tv-motion-stroke-offset-reverse-100: 120px; /* 反向结束 dashoffset */ + + /* ---------- Tab切换 (tab.less) ---------- */ + --tv-motion-tab-speed: 0.3s; /* 动画时长 */ + --tv-motion-tab-opacity-start: 0; /* 初始透明度 */ + --tv-motion-tab-opacity-end: 1; /* 结束透明度 */ + --tv-motion-tab-offset-x-start: 100%; /* X轴初始位移 */ + --tv-motion-tab-offset-x-end: 0; /* X轴结束位移 */ + --tv-motion-tab-offset-x-start-left: -100%; /* 左侧初始位移 */ + --tv-motion-tab-offset-y-start: 100%; /* Y轴初始位移 */ + --tv-motion-tab-offset-y-start-down: -100%; /* 下方初始位移 */ + --tv-motion-tab-offset-y-end: 0; /* Y轴结束位移 */ + + /* ---------- 弹出缩放 (zoom.less) ---------- */ + --tv-motion-scale-speed: 0.3s; /* 动画时长 */ + --tv-motion-scale-start: 0; /* 初始缩放 */ + --tv-motion-scale-mid: 0.5; /* 中间缩放 */ + --tv-motion-scale-end: 1; /* 结束缩放 */ + --tv-motion-scale-opacity-start: 0; /* 初始透明度 */ + --tv-motion-scale-opacity-mid: 0.5; /* 中间透明度 */ + --tv-motion-scale-opacity-end: 1; /* 结束透明度 */ } diff --git a/packages/theme/src/chart-core/index.less b/packages/theme/src/chart-core/index.less index 16d2aa5c2d..5b1f5e1290 100644 --- a/packages/theme/src/chart-core/index.less +++ b/packages/theme/src/chart-core/index.less @@ -50,13 +50,14 @@ background-color: var(--tv-ChartCore-data-empty-bg-color); .circular { + --tv-motion-rotate-speed: 2s; width: 42px; height: 42px; - animation: rotate-spin 2s linear infinite; + animation: rotate-spin var(--tv-motion-rotate-speed) linear infinite; } .path { - animation: stroke-dash-loop 1.5s ease-in-out infinite; + animation: stroke-dash-loop var(--tv-motion-stroke-speed) ease-in-out infinite; stroke-dasharray: 90, 150; stroke-dashoffset: 0; stroke-width: 2; diff --git a/packages/theme/src/dialog-box/index.less b/packages/theme/src/dialog-box/index.less index aa57196dd6..1ce1bff20d 100644 --- a/packages/theme/src/dialog-box/index.less +++ b/packages/theme/src/dialog-box/index.less @@ -210,11 +210,13 @@ } .v-modal-enter { - animation: fade-in 0.2s ease; + --tv-motion-fade-speed: 0.2s; + animation: fade-in var(--tv-motion-fade-speed) ease; } .v-modal-leave { - animation: fade-out 0.2s ease forwards; + --tv-motion-fade-speed: 0.2s; + animation: fade-out var(--tv-motion-fade-speed) ease forwards; } // @keyframes v-modal-in { @@ -272,14 +274,15 @@ // } .dialog-fade-enter-active { - animation: fade-in-up 0.3s; + animation: fade-in-up var(--tv-motion-fade-speed); } .dialog-fade-leave-active { .@{dialog-box-prefix-cls} { - animation: fade-out-up 3s; + --tv-motion-fade-speed: 3s; + animation: fade-out-up var(--tv-motion-fade-speed); } - animation: fade-out-up 0.3s; + animation: fade-out-up var(--tv-motion-fade-speed); } // @keyframes dialog-fade-in { @@ -307,7 +310,7 @@ // } .enlarge-enter-active { - animation: enlarge-in 350ms linear; + animation: enlarge-in var(--tv-motion-scale-speed) linear; } // @keyframes enlarge-in { @@ -330,4 +333,4 @@ top: 0 !important; left: 0 !important; } -} \ No newline at end of file +} diff --git a/packages/theme/src/drawer/index.less b/packages/theme/src/drawer/index.less index 2bfe2359e4..1a3c4b1f22 100644 --- a/packages/theme/src/drawer/index.less +++ b/packages/theme/src/drawer/index.less @@ -256,11 +256,11 @@ // } .drawer-slide-left-enter-active { - animation: slide-left-in 0.3s linear; + animation: slide-left-in var(--tv-motion-slide-speed) linear; } .drawer-slide-left-leave-active { - animation: slide-left-out 0.3s linear; + animation: slide-left-out var(--tv-motion-slide-speed) linear; } // @keyframes slideLeft { @@ -298,11 +298,11 @@ // } .drawer-slide-bottom-enter-active { - animation: slide-bottom-in 0.3s linear; + animation: slide-bottom-in var(--tv-motion-slide-speed) linear; } .drawer-slide-bottom-leave-active { - animation: slide-bottom-out 0.3s linear; + animation: slide-bottom-out var(--tv-motion-slide-speed) linear; } // @keyframes slideBottom { @@ -340,11 +340,11 @@ // } .drawer-slide-top-enter-active { - animation: slide-top-in 0.3s linear; + animation: slide-top-in var(--tv-motion-slide-speed) linear; } .drawer-slide-top-leave-active { - animation: slide-top-out 0.3s linear; + animation: slide-top-out var(--tv-motion-slide-speed) linear; } // @keyframes slideTop { @@ -382,11 +382,11 @@ // } .drawer-fade-enter-active { - animation: fade-in 0.3s linear; + animation: fade-in var(--tv-motion-fade-speed) linear; } .drawer-fade-leave-active { - animation: fade-out 0.3s linear; + animation: fade-out var(--tv-motion-fade-speed) linear; } // @keyframes drawer-fade-in { diff --git a/packages/theme/src/grid/body.less b/packages/theme/src/grid/body.less index 45aead1782..59c0818ef7 100644 --- a/packages/theme/src/grid/body.less +++ b/packages/theme/src/grid/body.less @@ -57,6 +57,7 @@ } .@{grid-prefix-cls}-copyed-borders { + --tv-motion-ants-shift: 13px; .@{grid-prefix-cls}-border-top, .@{grid-prefix-cls}-border-bottom { height: 3px; @@ -68,14 +69,21 @@ } & > span { - background: repeating-linear-gradient( - 135deg, - transparent, - transparent 3px, - var(--tv-Grid-border-color-active) 3px, - var(--tv-Grid-border-color-active) 9px - ); - animation: shine 1s infinite linear; + background: repeating-linear-gradient(135deg, transparent 0 3px, var(--tv-Grid-border-color-active) 3px 9px); + background-repeat: repeat; + } + + .@{grid-prefix-cls}-border-top { + animation: ants-x var(--tv-motion-ants-speed) linear infinite; + } + .@{grid-prefix-cls}-border-right { + animation: ants-y var(--tv-motion-ants-speed) linear infinite; + } + .@{grid-prefix-cls}-border-bottom { + animation: ants-x-rev var(--tv-motion-ants-speed) linear infinite; + } + .@{grid-prefix-cls}-border-left { + animation: ants-y-rev var(--tv-motion-ants-speed) linear infinite; } } } diff --git a/packages/theme/src/grid/icon.less b/packages/theme/src/grid/icon.less index e09d4d2c61..eff3c6c1b7 100644 --- a/packages/theme/src/grid/icon.less +++ b/packages/theme/src/grid/icon.less @@ -287,7 +287,7 @@ } &.roll { - animation: rotate-spin 1s infinite linear; + animation: rotate-spin var(--tv-motion-rotate-speed) infinite linear; } } diff --git a/packages/theme/src/grid/loading.less b/packages/theme/src/grid/loading.less index 4367bde5e6..dbb82fbef3 100644 --- a/packages/theme/src/grid/loading.less +++ b/packages/theme/src/grid/loading.less @@ -51,13 +51,14 @@ background: linear-gradient(to top, transparent, transparent); span { + --tv-motion-grid-loading-speed: 1.04s; display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: linear-gradient(#000, #000); position: absolute; - animation: grid-loading 1.04s ease infinite; + animation: grid-loading var(--tv-motion-grid-loading-speed) ease infinite; } // @keyframes load { diff --git a/packages/theme/src/image/index.less b/packages/theme/src/image/index.less index ce377eae55..6d0386e7de 100644 --- a/packages/theme/src/image/index.less +++ b/packages/theme/src/image/index.less @@ -81,11 +81,11 @@ } .viewer-fade-enter-active { - animation: fade-in-up 0.3s; + animation: fade-in-up var(--tv-motion-fade-speed); } .viewer-fade-leave-active { - animation: fade-out-up 0.3s; + animation: fade-out-up var(--tv-motion-fade-speed); } // @keyframes viewer-fade-in { diff --git "a/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256.md" "b/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256.md" new file mode 100644 index 0000000000..d9705db17f --- /dev/null +++ "b/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256.md" @@ -0,0 +1,224 @@ +# TinyVue 全局动效配置 + +## 1. 背景与目标 + +在应用开发中,统一的动效配置有助于提升整体用户体验和产品一致性。 + 本方案为 TinyVue 提供 **全局动效配置能力**,仅依赖 **LESS 与 CSS 变量**,实现以下目标: + +1. **统一管理**:所有动效集中管理,避免分散定义和重复维护。 +2. **全局可控**:通过 CSS 变量统一控制动效的持续时间、延迟、速度等参数。 +3. **组件集成**:组件可直接调用统一的动效类名或 `@keyframes`。 +4. **动态可调**:通过覆盖 CSS 变量即可在不同场景下切换动效风格。 + +------ + +## 2. 全局配置 + +### 2.1 全局变量定义 + +在 `/packages/theme/src/motion/index.less` 中统一定义: + +```less +:root { + /* 蚂蚁线相关配置 */ + --ants-shift: 8px; + --ants-speed: 0.8s; +} +``` + +开发者可在组件主题文件中覆盖这些变量: + +```css +.copyed-borders { + --ants-shift: 8px; + --ants-speed: 0.8s; +} +``` + +------ + +## 3. 动效分类与使用 + +动效统一存放在 `/packages/theme/src/motion/` 目录下,按类型拆分: + +``` +motion/ + ├─ fade.less // 淡入淡出 + ├─ slide.less // 滑动 + ├─ zoom.less // 缩放 + ├─ rotate.less // 旋转 + ├─ bounce.less // 弹跳 + ├─ scroll.less // 滚动 + ├─ stroke.less // 描边 + ├─ shine.less // 闪烁 + ├─ ants.less // 蚂蚁线 + ├─ arrow.less // 箭头 + ├─ tab.less // Tab 切换 + ├─ progress.less // 进度条 + └─ index.less // 全局变量定义 +``` + +------ + +## 3. 全局变量管理 + +### 3.1 示例:淡入淡出 (fade.less) + +```less +@keyframes fade-in { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes fade-out { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} +``` + +组件调用示例: + +```less +.@{fade-prefix-cls} { + &-enter-active { + animation: 0.3s fade-in both ease-out; + } + + &-leave-active { + animation: 0.3s fade-out both ease-in; + } +} +``` + +--- + +### 3.2 示例:滑动 (slide.less) + +```less +@keyframes slide-left-in { + 0% { + opacity: 0; + transform: translateX(-100%); + } + + 50% { + opacity: 0.6; + transform: translateX(-50%); + } + + 100% { + opacity: 1; + transform: translateX(0%); + } +} + +@keyframes slide-left-out { + 0% { + opacity: 1; + transform: translateX(0%); + } + + 50% { + opacity: 0.6; + transform: translateX(-50%); + } + + 100% { + opacity: 0; + transform: translateX(-100%); + } +} +``` + +组件调用示例: + +```less +.drawer-slide-left-enter-active { + animation: slide-left-in 0.3s linear; +} + +.drawer-slide-left-leave-active { + animation: slide-left-out 0.3s linear; +} +``` + +### 3.3 示例:蚂蚁线 (ants.less,可配置) + +```less +@keyframes ants-x { + 0% { + background-position: 0 0; + } + + 100% { + background-position: var(--ants-shift, 8px) 0; + } +} + +@keyframes ants-x-rev { + 0% { + background-position: 0 0; + } + + 100% { + background-position: calc(-1 * var(--ants-shift, 8px)) 0; + } +} +``` + +组件调用示例: + +```less +.@{grid-prefix-cls}-copyed-borders { + --ants-shift: 13px; + --ants-speed: 0.8s; + + .@{grid-prefix-cls}-border-top { + animation: ants-x var(--ants-speed) linear infinite; + } + .@{grid-prefix-cls}-border-bottom { + animation: ants-x-rev var(--ants-speed) linear infinite; + } +} +``` + +------ + +## 4. 组件集成方式 + +1. **全局引入** + 所有 `@keyframes` 集中在 `transition.less` 和 `motion/*` 中。 +2. **局部调用** + 组件通过 className 或 `-enter-active / -leave-active` 绑定。 +3. **可配置参数** + 开发者可通过覆盖 `:root` 变量修改动效时长、速度等。 + +示例动效: + +```less +.drawer-slide-left-enter-active { + animation: slide-left-in 0.3s linear; +} +``` + +------ + +## 5. 扩展与维护 + +1. **命名规范**: + - 使用 `{type}-{direction}-{state}` 格式,例如 `slide-left-in`。 + - 保证全局唯一性,避免冲突。 +2. **文档补充**: + - 每类动效提供示例代码与调用方式说明。 +3. **未来扩展**: + - 支持引入方便引入其他动效资源,增强 TinyVue 动效生态。 diff --git "a/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256\347\273\264\346\212\244.md" "b/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256\347\273\264\346\212\244.md" new file mode 100644 index 0000000000..e310656052 --- /dev/null +++ "b/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256\347\273\264\346\212\244.md" @@ -0,0 +1,135 @@ +# TinyVue 全局动效配置维护 + +## 1. 目的 + +本手册用于指导 TinyVue 开发者如何 **新增、修改和维护全局动效配置**。 + 目标是确保动效在 **全局统一管理、可配置、可扩展** 的前提下,保持 **一致性和易维护性**。 + +------ + +## 2. 目录与文件结构 + +动效统一存放在 `/packages/theme/src/motion/` 目录下,按类型拆分: + +``` +motion/ + ├─ fade.less // 淡入淡出 + ├─ slide.less // 滑动 + ├─ zoom.less // 缩放 + ├─ rotate.less // 旋转 + ├─ bounce.less // 弹跳 + ├─ scroll.less // 滚动 + ├─ stroke.less // 描边 + ├─ shine.less // 闪烁 + ├─ ants.less // 蚂蚁线 + ├─ arrow.less // 箭头 + ├─ tab.less // Tab 切换 + ├─ progress.less // 进度条 + └─ index.less // 全局变量定义 +``` + +------ + +## 3. 全局变量管理 + +全局变量统一在 `index.less` 中定义: + +```less +:root { + --ants-shift: 8px; + --ants-speed: 0.8s; +} +``` + +------ + +## 4. 动效命名规范 + +格式: + +``` +{type}-{direction}-{state} +``` + +示例: + +- `fade-in` / `fade-out` +- `slide-left-in` / `slide-left-out` +- `zoom-in-scale` / `zoom-out-scale` +- `ants-x` / `ants-x-rev` + +👉 规则: + +- **type**:动效类型(fade/slide/zoom/ants/...) +- **direction**:方向或轴向(left/right/up/down/x/y/scale) +- **state**:状态(in/out/rev/pulse 等) + +------ + +## 5. 新增动效流程 + +### Step 1. 创建 keyframes + +在对应 `motion/*.less` 文件中新增动效,示例: + +```less +@keyframes slide-up-in { + 0% { transform: translateY(100%); opacity: 0; } + 100% { transform: translateY(0); opacity: 1; } +} +``` + +### Step 2. (可选)使用变量替代固定值 + +```less +@keyframes ants-x { + 0% { background-position: 0 0; } + 100% { background-position: var(--ants-shift) 0; } +} +``` + +### Step 3. 在组件中绑定 + +```less +.modal-slide-up-enter-active { + animation: slide-up-in 0.3s linear; +} +``` + +### Step 4. 更新文档 + +- 在 **对应 `.less` 文件顶部注释** 动效用途 +- 在 PR 描述中说明:类别 / 动效名 / 用法示例 + +------ + +## 6. 动效扩展与维护 + +### 6.1 扩展原则 + +1. 动效必须写在对应分类文件中(如滑动类 → `slide.less`)。 +2. 保持命名唯一性,避免与现有动效冲突。 +3. 需要新变量时,先在 `index.less` 中声明,再调用。 + +### 6.2 维护规范 + +- **代码注释**:在 `@keyframes` 前标注用途和来源。 +- **文件内分组**:同类动效写在一起,便于查找。 + +------ + +## 7. 组件集成方式 + +1. **全局引入** + 所有动效在 `motion/*` 中维护,并在组件中通过 className 使用。 +2. **局部调用** + 组件通过 `-enter-active` / `-leave-active` 调用。 +3. **覆盖参数** + 用户可覆盖变量来自定义速度/时长。 + +------ + +## 8. 常见问题 + +- **不同组件能否自定义时长?** + 可以,在组件作用域覆盖变量。 \ No newline at end of file diff --git a/packages/theme/src/motion/ants.less b/packages/theme/src/motion/ants.less new file mode 100644 index 0000000000..4dd01c6882 --- /dev/null +++ b/packages/theme/src/motion/ants.less @@ -0,0 +1,39 @@ +/* 横向蚂蚁线动画(正向) */ +@keyframes ants-x { + 0% { + background-position: 0 0; + } + 100% { + background-position: var(--tv-motion-ants-shift, 8px) 0; + } +} + +/* 横向蚂蚁线动画(反向) */ +@keyframes ants-x-rev { + 0% { + background-position: 0 0; + } + 100% { + background-position: calc(-1 * var(--tv-motion-ants-shift, 8px)) 0; + } +} + +/* 纵向蚂蚁线动画(正向) */ +@keyframes ants-y { + 0% { + background-position: 0 0; + } + 100% { + background-position: 0 var(--tv-motion-ants-shift, 8px); + } +} + +/* 纵向蚂蚁线动画(反向) */ +@keyframes ants-y-rev { + 0% { + background-position: 0 0; + } + 100% { + background-position: 0 calc(-1 * var(--tv-motion-ants-shift, 8px)); + } +} diff --git a/packages/theme/src/motion/arrow.less b/packages/theme/src/motion/arrow.less index 14f13257b8..7276b11d3d 100644 --- a/packages/theme/src/motion/arrow.less +++ b/packages/theme/src/motion/arrow.less @@ -1,45 +1,50 @@ /* =========================== - 箭头移动动画 + 箭头移动动画 (arrow.less) 来源: fall-menu carousel-arrow + 可配置变量: + --tv-motion-arrow-offset 箭头最终位移(px) + --tv-motion-arrow-left-init 左侧初始位置(px) + --tv-motion-arrow-left-mid 左侧 pulse 中间位置(px) + --tv-motion-arrow-right-init 右侧初始位置(px) + --tv-motion-arrow-right-mid 右侧 pulse 中间位置(px) + --tv-motion-arrow-speed 箭头动画时长(s) =========================== */ + +/* ============ Pulse 效果 ============ */ @keyframes arrow-left-pulse { 0% { - left: -17px; + left: var(--tv-motion-arrow-left-init, -17px); } - 50% { - left: -13px; + left: var(--tv-motion-arrow-left-mid, -13px); } - 100% { - left: -17px; + left: var(--tv-motion-arrow-left-init, -17px); } } @keyframes arrow-right-pulse { 0% { - right: -17px; + right: var(--tv-motion-arrow-right-init, -17px); } - 50% { - right: -13px; + right: var(--tv-motion-arrow-right-mid, -13px); } - 100% { - right: -17px; + right: var(--tv-motion-arrow-right-init, -17px); } } +/* ============ Carousel 效果 ============ */ @keyframes arrow-right-carousel { 0% { opacity: 0; right: 0; } - 100% { opacity: 1; transform: translateY(-50%); - right: 16px; + right: var(--tv-motion-arrow-offset, 16px); } } @@ -48,27 +53,23 @@ opacity: 0; left: 0; } - 100% { opacity: 1; transform: translateY(-50%); - left: 16px; + left: var(--tv-motion-arrow-offset, 16px); } } -/* =相关补充= */ - -/* =补充结束= */ +/* ============ 普通 In/Out 效果 ============ */ @keyframes arrow-left-in { 0% { opacity: 0; left: 0; } - 100% { opacity: 1; transform: translateY(-50%); - left: 16px; + left: var(--tv-motion-arrow-offset, 16px); } } @@ -77,23 +78,19 @@ opacity: 0; right: 0; } - 100% { opacity: 1; transform: translateY(-50%); - right: 16px; + right: var(--tv-motion-arrow-offset, 16px); } } -/* =相关补充= */ - @keyframes arrow-left-out { 0% { opacity: 1; transform: translateY(-50%); - left: 16px; + left: var(--tv-motion-arrow-offset, 16px); } - 100% { opacity: 0; left: 0; @@ -104,13 +101,10 @@ 0% { opacity: 1; transform: translateY(-50%); - right: 16px; + right: var(--tv-motion-arrow-offset, 16px); } - 100% { opacity: 0; right: 0; } } - -/* =补充结束= */ \ No newline at end of file diff --git a/packages/theme/src/motion/bounce.less b/packages/theme/src/motion/bounce.less index 4b83c892b8..96b3ea82c8 100644 --- a/packages/theme/src/motion/bounce.less +++ b/packages/theme/src/motion/bounce.less @@ -1,35 +1,36 @@ /* =========================== - 缩放弹入动画(统一 bounce-in / scale-in) + 缩放弹入动画 (bounce.less) + 统一命名: bounce-in / bounce-out 来源: transition-icon + 可配置变量: + --tv-motion-bounce-scale-mid 弹入/弹出过程中的放大比例 + --tv-motion-bounce-scale-min 初始/结束时缩小比例 + --tv-motion-bounce-scale-max 完整展开比例 + --tv-motion-bounce-speed 动画时长 =========================== */ + +/* ============ 弹入 ============ */ @keyframes bounce-in { 0% { - transform: scale(0); + transform: scale(var(--tv-motion-bounce-scale-min, 0)); } - 50% { - transform: scale(1.2); + transform: scale(var(--tv-motion-bounce-scale-mid, 1.2)); } - 100% { - transform: scale(1); + transform: scale(var(--tv-motion-bounce-scale-max, 1)); } } -/* =相关补充= */ - +/* ============ 弹出 ============ */ @keyframes bounce-out { 0% { - transform: scale(1); + transform: scale(var(--tv-motion-bounce-scale-max, 1)); } - 50% { - transform: scale(1.2); + transform: scale(var(--tv-motion-bounce-scale-mid, 1.2)); } - 100% { - transform: scale(0); + transform: scale(var(--tv-motion-bounce-scale-min, 0)); } } - -/* =补充结束= */ diff --git a/packages/theme/src/motion/fade.less b/packages/theme/src/motion/fade.less index c933ba9c7b..7d7bf01996 100644 --- a/packages/theme/src/motion/fade.less +++ b/packages/theme/src/motion/fade.less @@ -1,12 +1,17 @@ /* =========================== - 淡入淡出动画 (透明度) - 来源: dialog-box, popup, drawer + 淡入淡出动画 (fade.less) + 来源: dialog-box, popup, drawer, image, timepicker + 可配置变量: + --tv-motion-fade-offset-x X轴位移(px) + --tv-motion-fade-offset-y Y轴位移(px) + --tv-motion-fade-speed 动画时长(s) =========================== */ + +/* ============ 纯淡入淡出 ============ */ @keyframes fade-in { 0% { opacity: 0; } - 100% { opacity: 1; } @@ -16,25 +21,18 @@ 0% { opacity: 1; } - 100% { opacity: 0; } } -/* =========================== - 淡入淡出动画 + 向上位移 - 来源: dialog-box, image -=========================== */ +/* ============ 各方向位移 + 淡入淡出 ============ */ @keyframes fade-in-up { 0% { - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); + transform: translate3d(0, calc(-1 * var(--tv-motion-fade-offset-y, 20px)), 0); opacity: 0; } - 100% { - -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); opacity: 1; } @@ -42,26 +40,20 @@ @keyframes fade-out-up { 0% { - -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); opacity: 1; } - 100% { - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); + transform: translate3d(0, calc(-1 * var(--tv-motion-fade-offset-y, 20px)), 0); opacity: 0; } } -/* =相关补充= */ - @keyframes fade-in-down { 0% { - transform: translate3d(0, 20px, 0); + transform: translate3d(0, var(--tv-motion-fade-offset-y, 20px), 0); opacity: 0; } - 100% { transform: translate3d(0, 0, 0); opacity: 1; @@ -73,19 +65,17 @@ transform: translate3d(0, 0, 0); opacity: 1; } - 100% { - transform: translate3d(0, 20px, 0); + transform: translate3d(0, var(--tv-motion-fade-offset-y, 20px), 0); opacity: 0; } } @keyframes fade-in-left { 0% { - transform: translate3d(-20px, 0, 0); + transform: translate3d(calc(-1 * var(--tv-motion-fade-offset-x, 20px)), 0, 0); opacity: 0; } - 100% { transform: translate3d(0, 0, 0); opacity: 1; @@ -97,19 +87,17 @@ transform: translate3d(0, 0, 0); opacity: 1; } - 100% { - transform: translate3d(-20px, 0, 0); + transform: translate3d(calc(-1 * var(--tv-motion-fade-offset-x, 20px)), 0, 0); opacity: 0; } } @keyframes fade-in-right { 0% { - transform: translate3d(20px, 0, 0); + transform: translate3d(var(--tv-motion-fade-offset-x, 20px), 0, 0); opacity: 0; } - 100% { transform: translate3d(0, 0, 0); opacity: 1; @@ -121,25 +109,18 @@ transform: translate3d(0, 0, 0); opacity: 1; } - 100% { - transform: translate3d(20px, 0, 0); + transform: translate3d(var(--tv-motion-fade-offset-x, 20px), 0, 0); opacity: 0; } } -/* =补充结束= */ - -/* =========================== - timepicker 面板进入动画 - 来源: transition-timepicker -=========================== */ +/* ============ Timepicker 动画 ============ */ @keyframes fade-in-timepicker { 0% { transform: translateY(-200px); z-index: -999; } - 100% { transform: translateY(0); z-index: 0; @@ -151,9 +132,8 @@ transform: translateY(200px); z-index: -999; } - 100% { transform: translateY(0); z-index: 0; } -} \ No newline at end of file +} diff --git a/packages/theme/src/motion/index.less b/packages/theme/src/motion/index.less index adf531ea94..16cec11b05 100644 --- a/packages/theme/src/motion/index.less +++ b/packages/theme/src/motion/index.less @@ -1,17 +1,24 @@ +/* ========================================== + 动画模块 Import 引入 +========================================== */ @import './rotate.less'; @import './fade.less'; @import './zoom.less'; @import './bounce.less'; - @import './slide.less'; @import './tab.less'; @import './arrow.less'; - @import './stroke.less'; @import './scroll.less'; @import './progress.less'; - -@import './skeleton.less'; +@import './loading.less'; @import './shine.less'; +@import './ants.less'; +/* ========================================== + 全局变量配置 (:root) +========================================== */ +:root, +:host { +} diff --git a/packages/theme/src/motion/loading.less b/packages/theme/src/motion/loading.less new file mode 100644 index 0000000000..72972a5aa6 --- /dev/null +++ b/packages/theme/src/motion/loading.less @@ -0,0 +1,26 @@ +/* =========================== + 加载动画 (loading.less) + 来源: skeleton-item, grid-loading + 可配置变量: + --tv-motion-skeleton-speed 骨架屏动画时长 + --tv-motion-skeleton-background-offset 背景流动偏移 + --tv-motion-grid-loading-speed 网格加载动画时长 + --tv-motion-grid-loading-opacity 网格加载最终透明度 +=========================== */ + +/* ============ 骨架屏动画 ============ */ +@keyframes skeleton-loading { + to { + background-position-x: var(--tv-motion-skeleton-background-offset, -20%); + } +} + +/* ============ 网格加载动画 ============ */ +@keyframes grid-loading { + 0% { + opacity: 1; + } + 100% { + opacity: var(--tv-motion-grid-loading-opacity, 0.1); + } +} diff --git a/packages/theme/src/motion/progress.less b/packages/theme/src/motion/progress.less index 7991c73dbb..95891133b0 100644 --- a/packages/theme/src/motion/progress.less +++ b/packages/theme/src/motion/progress.less @@ -1,22 +1,26 @@ /* =========================== - 进度条流动背景 + 进度条流动背景 (progress.less) 来源: progress + 可配置变量: + --tv-motion-progress-background-shift 背景流动位移(px) + --tv-motion-progress-speed 动画时长(s) =========================== */ + +/* ============ 动画 ============ */ @keyframes progress-background { 0% { background-position: 0 0; } - 100% { - background-position: 32px 0; + background-position: var(--tv-motion-progress-background-shift, 32px) 0; } } + @-webkit-keyframes progress-background { 0% { background-position: 0 0; } - 100% { - background-position: 32px 0; + background-position: var(--tv-motion-progress-background-shift, 32px) 0; } } diff --git a/packages/theme/src/motion/rotate.less b/packages/theme/src/motion/rotate.less index 312e473c94..0d659ab1f1 100644 --- a/packages/theme/src/motion/rotate.less +++ b/packages/theme/src/motion/rotate.less @@ -1,11 +1,16 @@ /* =========================== - 通用旋转 + 进度加载动画 + 通用旋转 + 进度加载动画 (rotate.less) 来源: chart-core, tree + 可配置变量: + --tv-motion-rotate-speed 旋转动画时长 + --tv-motion-rotate-degrees 旋转的角度 =========================== */ + +/* ============ 旋转动画 ============ */ @keyframes rotate-spin { - // chart-core:loading-rotate,tree:loading-rotate + // chart-core:loading-rotate, tree:loading-rotate 100% { - transform: rotate(360deg); + transform: rotate(var(--tv-motion-rotate-degrees, 360deg)); } } @@ -13,18 +18,13 @@ 0% { transform: rotateZ(0deg); } - 100% { - transform: rotateZ(360deg); + transform: rotateZ(var(--tv-motion-rotate-degrees, 360deg)); } } -/* ==========相关补充=========== */ - @keyframes rotate-reverse { 100% { - transform: rotate(-360deg); + transform: rotate(var(--tv-motion-rotate-degrees, -360deg)); } } - -/* =========================== */ \ No newline at end of file diff --git a/packages/theme/src/motion/scroll.less b/packages/theme/src/motion/scroll.less index 05d61bd9c5..2baa52aad1 100644 --- a/packages/theme/src/motion/scroll.less +++ b/packages/theme/src/motion/scroll.less @@ -1,103 +1,96 @@ /* =========================== - 滚动文字动画 + 滚动文字动画 (scroll-text.less) 来源: scroll-text + 可配置变量: + --tv-motion-scroll-speed 动画时长 + --tv-motion-scroll-offset-x X轴初始位移 + --tv-motion-scroll-offset-x-end X轴结束位移 + --tv-motion-scroll-offset-y Y轴初始位移 + --tv-motion-scroll-offset-y-end Y轴结束位移 =========================== */ + +/* ============ 滚动动画 ============ */ @keyframes scroll-left { 0% { - transform: translateX(300px); + transform: translateX(var(--tv-motion-scroll-offset-x, 300px)); } - 100% { - transform: translateX(-100%); + transform: translateX(var(--tv-motion-scroll-offset-x-end, -100%)); } } @keyframes scroll-right { 0% { - transform: translateX(-100%); + transform: translateX(var(--tv-motion-scroll-offset-x-end, -100%)); } - 100% { - transform: translateX(300px); + transform: translateX(var(--tv-motion-scroll-offset-x, 300px)); } } @keyframes scroll-up { 0% { - transform: translateY(100%); + transform: translateY(var(--tv-motion-scroll-offset-y, 100%)); } - 100% { - transform: translateY(-100%); + transform: translateY(var(--tv-motion-scroll-offset-y-end, -100%)); } } @keyframes scroll-down { 0% { - transform: translateY(-100%); + transform: translateY(var(--tv-motion-scroll-offset-y-end, -100%)); } - 100% { - transform: translateY(100%); + transform: translateY(var(--tv-motion-scroll-offset-y, 100%)); } } +/* ============ 滚动适应动画 ============ */ @keyframes scroll-left-adapt { 0% { transform: translateX(100%); } - 50% { transform: translateX(0); } - 100% { - transform: translateX(-100%); + transform: translateX(var(--tv-motion-scroll-offset-x-end, -100%)); } } @keyframes scroll-right-adapt { 0% { - transform: translateX(-100%); + transform: translateX(var(--tv-motion-scroll-offset-x-end, -100%)); } - 50% { transform: translateX(0); } - 100% { transform: translateX(100%); } } -/* =相关补充= */ - @keyframes scroll-up-adapt { 0% { - transform: translateY(100%); + transform: translateY(var(--tv-motion-scroll-offset-y, 100%)); } - 50% { transform: translateY(0); } - 100% { - transform: translateY(-100%); + transform: translateY(var(--tv-motion-scroll-offset-y-end, -100%)); } } @keyframes scroll-down-adapt { 0% { - transform: translateY(-100%); + transform: translateY(var(--tv-motion-scroll-offset-y-end, -100%)); } - 50% { transform: translateY(0); } - 100% { - transform: translateY(100%); + transform: translateY(var(--tv-motion-scroll-offset-y, 100%)); } } - -/* =补充结束= */ \ No newline at end of file diff --git a/packages/theme/src/motion/shine.less b/packages/theme/src/motion/shine.less index 2df4609737..958301dd48 100644 --- a/packages/theme/src/motion/shine.less +++ b/packages/theme/src/motion/shine.less @@ -1,10 +1,18 @@ -//grid-body +/* =========================== + 光泽闪烁动画 (shine.less) + 来源: grid-body + 可配置变量: + --tv-motion-shine-speed 动画时长 + --tv-motion-shine-offset-x X轴背景位移 + --tv-motion-shine-offset-y Y轴背景位移 +=========================== */ + +/* ============ 光泽闪烁效果 ============ */ @keyframes shine { 0% { - background-position: -1px -1px; + background-position: var(--tv-motion-shine-offset-x, -1px) var(--tv-motion-shine-offset-y, -1px); } - 100% { - background-position: -12px -12px; + background-position: var(--tv-motion-shine-offset-x, -12px) var(--tv-motion-shine-offset-y, -12px); } -} \ No newline at end of file +} diff --git a/packages/theme/src/motion/skeleton.less b/packages/theme/src/motion/skeleton.less deleted file mode 100644 index b00c2c0ed1..0000000000 --- a/packages/theme/src/motion/skeleton.less +++ /dev/null @@ -1,19 +0,0 @@ -/* =========================== - 骨架屏、加载等 - 来源: skeleton-item, grid-loading -=========================== */ -@keyframes skeleton-loading { - to { - background-position-x: -20%; - } -} - -@keyframes grid-loading { - 0% { - opacity: 10; - } - - 100% { - opacity: 0.1; - } -} diff --git a/packages/theme/src/motion/slide.less b/packages/theme/src/motion/slide.less index 14363f94a0..a132d3c3cb 100644 --- a/packages/theme/src/motion/slide.less +++ b/packages/theme/src/motion/slide.less @@ -1,18 +1,23 @@ /* =========================== - 抽屉/对话框 滑动方向动画 + 抽屉/对话框滑动方向动画 (slide.less) 来源: dialog-box, drawer + 可配置变量: + --tv-motion-slide-speed 动画时长 + --tv-motion-slide-opacity-mid 中间透明度 + --tv-motion-slide-offset-x X轴位移 (%) + --tv-motion-slide-offset-y Y轴位移 (%) =========================== */ + +/* ============ 左滑 ============ */ @keyframes slide-left-in { 0% { opacity: 0; - transform: translateX(-100%); + transform: translateX(var(--tv-motion-slide-offset-left)); } - 50% { - opacity: 0.6; - transform: translateX(-50%); + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateX(var(--tv-motion-slide-offset-left-mid)); } - 100% { opacity: 1; transform: translateX(0%); @@ -24,29 +29,26 @@ opacity: 1; transform: translateX(0%); } - 50% { - opacity: 0.6; - transform: translateX(-50%); + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateX(var(--tv-motion-slide-offset-left-mid)); } - 100% { opacity: 0; - transform: translateX(-100%); + transform: translateX(var(--tv-motion-slide-offset-left)); } } +/* ============ 右滑 ============ */ @keyframes slide-right-in { 0% { opacity: 0; - transform: translateX(100%); + transform: translateX(var(--tv-motion-slide-offset-right)); } - 50% { - opacity: 0.6; - transform: translateX(50%); + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateX(var(--tv-motion-slide-offset-right-mid)); } - 100% { opacity: 1; transform: translateX(0%); @@ -58,29 +60,26 @@ opacity: 1; transform: translateX(0%); } - 50% { - opacity: 0.6; - transform: translateX(50%); + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateX(var(--tv-motion-slide-offset-right-mid)); } - 100% { opacity: 0; - transform: translateX(100%); + transform: translateX(var(--tv-motion-slide-offset-right)); } } +/* ============ 上滑 ============ */ @keyframes slide-top-in { 0% { opacity: 0; - transform: translateY(-100%); + transform: translateY(var(--tv-motion-slide-offset-top)); } - 50% { - opacity: 0.6; - transform: translateY(-50%); + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateY(var(--tv-motion-slide-offset-top-mid)); } - 100% { opacity: 1; transform: translateY(0%); @@ -89,32 +88,29 @@ @keyframes slide-top-out { 0% { - opacity: 0; + opacity: 1; transform: translateY(0%); } - 50% { - opacity: 0.6; - transform: translateY(-50%); + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateY(var(--tv-motion-slide-offset-top-mid)); } - 100% { - opacity: 1; - transform: translateY(-100%); + opacity: 0; + transform: translateY(var(--tv-motion-slide-offset-top)); } } +/* ============ 下滑 ============ */ @keyframes slide-bottom-in { 0% { opacity: 0; - transform: translateY(100%); + transform: translateY(var(--tv-motion-slide-offset-bottom)); } - 50% { - opacity: 0.6; - transform: translateY(50%); + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateY(var(--tv-motion-slide-offset-bottom-mid)); } - 100% { opacity: 1; transform: translateY(0%); @@ -123,17 +119,15 @@ @keyframes slide-bottom-out { 0% { - opacity: 0; + opacity: 1; transform: translateY(0%); } - 50% { - opacity: 0.6; - transform: translateY(50%); + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateY(var(--tv-motion-slide-offset-bottom-mid)); } - 100% { - opacity: 1; - transform: translateY(100%); + opacity: 0; + transform: translateY(var(--tv-motion-slide-offset-bottom)); } -} \ No newline at end of file +} diff --git a/packages/theme/src/motion/stroke.less b/packages/theme/src/motion/stroke.less index 20e383f7ac..1e98bb6e8f 100644 --- a/packages/theme/src/motion/stroke.less +++ b/packages/theme/src/motion/stroke.less @@ -1,38 +1,46 @@ +/* =========================== + 描边循环动画 (stroke.less) + 来源: chart-core, tree + 可配置变量: + --tv-motion-stroke-speed 动画时长 + --tv-motion-stroke-dasharray-0 初始 dasharray + --tv-motion-stroke-dasharray-50 中间 dasharray + --tv-motion-stroke-dasharray-100 结束 dasharray + --tv-motion-stroke-offset-0 初始 dashoffset + --tv-motion-stroke-offset-50 中间 dashoffset + --tv-motion-stroke-offset-100 结束 dashoffset + --tv-motion-stroke-offset-reverse-50 中间反向 dashoffset + --tv-motion-stroke-offset-reverse-100 结束反向 dashoffset +=========================== */ + +/* ============ 正向循环 ============ */ @keyframes stroke-dash-loop { - // chart-core:loading-dash,tree:loading-dash 0% { - stroke-dasharray: 1, 200; - stroke-dashoffset: 0; + stroke-dasharray: var(--tv-motion-stroke-dasharray-0, 1, 200); + stroke-dashoffset: var(--tv-motion-stroke-offset-0, 0); } - 50% { - stroke-dasharray: 90, 150; - stroke-dashoffset: -40px; + stroke-dasharray: var(--tv-motion-stroke-dasharray-50, 90, 150); + stroke-dashoffset: var(--tv-motion-stroke-offset-50, -40px); } - 100% { - stroke-dasharray: 90, 150; - stroke-dashoffset: -120px; + stroke-dasharray: var(--tv-motion-stroke-dasharray-100, 90, 150); + stroke-dashoffset: var(--tv-motion-stroke-offset-100, -120px); } } -/* =相关补充= */ - +/* ============ 反向循环 ============ */ @keyframes stroke-dash-reverse { 0% { - stroke-dasharray: 1, 200; - stroke-dashoffset: 0; + stroke-dasharray: var(--tv-motion-stroke-dasharray-0, 1, 200); + stroke-dashoffset: var(--tv-motion-stroke-offset-0, 0); } - 50% { - stroke-dasharray: 90, 150; - stroke-dashoffset: 40px; + stroke-dasharray: var(--tv-motion-stroke-dasharray-50, 90, 150); + stroke-dashoffset: var(--tv-motion-stroke-offset-reverse-50, 40px); } - 100% { - stroke-dasharray: 90, 150; - stroke-dashoffset: 120px; + stroke-dasharray: var(--tv-motion-stroke-dasharray-100, 90, 150); + stroke-dashoffset: var(--tv-motion-stroke-offset-reverse-100, 120px); } } - -/* =补充结束= */ \ No newline at end of file diff --git a/packages/theme/src/motion/tab.less b/packages/theme/src/motion/tab.less index 8cdc3502dd..6a4329b52c 100644 --- a/packages/theme/src/motion/tab.less +++ b/packages/theme/src/motion/tab.less @@ -1,111 +1,114 @@ /* =========================== - Tab切换动画 (保留 enter/leave) + Tab切换动画 (tab.less) 来源: tabs + 可配置变量: + --tv-motion-tab-speed 动画时长 + --tv-motion-tab-opacity-start 初始透明度 + --tv-motion-tab-opacity-end 结束透明度 + --tv-motion-tab-offset-x-start X轴初始位移 + --tv-motion-tab-offset-x-end X轴结束位移 + --tv-motion-tab-offset-x-start-left 左向 X轴初始位移 + --tv-motion-tab-offset-y-start Y轴初始位移 + --tv-motion-tab-offset-y-start-down 下向 Y轴初始位移 + --tv-motion-tab-offset-y-end Y轴结束位移 =========================== */ + +/* ============ 水平向右 ============ */ @keyframes tab-slide-right-in { 0% { - opacity: 0; + opacity: var(--tv-motion-tab-opacity-start, 0); transform-origin: 0 0; - transform: translateX(100%); + transform: translateX(var(--tv-motion-tab-offset-x-start, 100%)); } - 100% { - opacity: 1; - transform: translateX(0); + opacity: var(--tv-motion-tab-opacity-end, 1); + transform: translateX(var(--tv-motion-tab-offset-x-end, 0)); } } @keyframes tab-slide-right-out { 0% { transform-origin: 0 0; - transform: translateX(0); - opacity: 1; + transform: translateX(var(--tv-motion-tab-offset-x-end, 0)); + opacity: var(--tv-motion-tab-opacity-end, 1); } - 100% { - transform: translateX(100%); - opacity: 0; + transform: translateX(var(--tv-motion-tab-offset-x-start, 100%)); + opacity: var(--tv-motion-tab-opacity-start, 0); } } +/* ============ 水平向左 ============ */ @keyframes tab-slide-left-in { 0% { - opacity: 0; + opacity: var(--tv-motion-tab-opacity-start, 0); transform-origin: 0 0; - transform: translateX(-100%); + transform: translateX(var(--tv-motion-tab-offset-x-start-left, -100%)); } - 100% { - opacity: 1; - transform: translateX(0); + opacity: var(--tv-motion-tab-opacity-end, 1); + transform: translateX(var(--tv-motion-tab-offset-x-end, 0)); } } @keyframes tab-slide-left-out { 0% { transform-origin: 0 0; - transform: translateX(0); - opacity: 1; + transform: translateX(var(--tv-motion-tab-offset-x-end, 0)); + opacity: var(--tv-motion-tab-opacity-end, 1); } - 100% { - transform: translateX(-100%); - opacity: 0; + transform: translateX(var(--tv-motion-tab-offset-x-start-left, -100%)); + opacity: var(--tv-motion-tab-opacity-start, 0); } } -/* =相关补充= */ - +/* ============ 垂直向上 ============ */ @keyframes tab-slide-up-in { 0% { - opacity: 0; + opacity: var(--tv-motion-tab-opacity-start, 0); transform-origin: 0 0; - transform: translateY(100%); + transform: translateY(var(--tv-motion-tab-offset-y-start, 100%)); } - 100% { - opacity: 1; - transform: translateY(0); + opacity: var(--tv-motion-tab-opacity-end, 1); + transform: translateY(var(--tv-motion-tab-offset-y-end, 0)); } } @keyframes tab-slide-up-out { 0% { transform-origin: 0 0; - transform: translateY(0); - opacity: 1; + transform: translateY(var(--tv-motion-tab-offset-y-end, 0)); + opacity: var(--tv-motion-tab-opacity-end, 1); } - 100% { - transform: translateY(100%); - opacity: 0; + transform: translateY(var(--tv-motion-tab-offset-y-start, 100%)); + opacity: var(--tv-motion-tab-opacity-start, 0); } } +/* ============ 垂直向下 ============ */ @keyframes tab-slide-down-in { 0% { - opacity: 0; + opacity: var(--tv-motion-tab-opacity-start, 0); transform-origin: 0 0; - transform: translateY(-100%); + transform: translateY(var(--tv-motion-tab-offset-y-start-down, -100%)); } - 100% { - opacity: 1; - transform: translateY(0); + opacity: var(--tv-motion-tab-opacity-end, 1); + transform: translateY(var(--tv-motion-tab-offset-y-end, 0)); } } @keyframes tab-slide-down-out { 0% { transform-origin: 0 0; - transform: translateY(0); - opacity: 1; + transform: translateY(var(--tv-motion-tab-offset-y-end, 0)); + opacity: var(--tv-motion-tab-opacity-end, 1); } - 100% { - transform: translateY(-100%); - opacity: 0; + transform: translateY(var(--tv-motion-tab-offset-y-start-down, -100%)); + opacity: var(--tv-motion-tab-opacity-start, 0); } } - -/* =补充结束= */ \ No newline at end of file diff --git a/packages/theme/src/motion/zoom.less b/packages/theme/src/motion/zoom.less index 339c3e9d25..9e0808d7b0 100644 --- a/packages/theme/src/motion/zoom.less +++ b/packages/theme/src/motion/zoom.less @@ -1,69 +1,68 @@ /* =========================== - 弹出缩放动画 + 弹出缩放动画 (zoom.less) 来源: dialog-box + 可配置变量: + --tv-motion-scale-speed 动画时长 + --tv-motion-scale-start 初始缩放 + --tv-motion-scale-mid 中间缩放 + --tv-motion-scale-end 结束缩放 + --tv-motion-scale-opacity-start 初始透明度 + --tv-motion-scale-opacity-mid 中间透明度 + --tv-motion-scale-opacity-end 结束透明度 =========================== */ + +/* ============ 弹出缩放 ============ */ @keyframes enlarge-in { 0% { - transform: scale(0); + transform: scale(var(--tv-motion-scale-start, 0)); } - 50% { - transform: scale(0.5); + transform: scale(var(--tv-motion-scale-mid, 0.5)); } - 100% { - transform: scale(1); + transform: scale(var(--tv-motion-scale-end, 1)); } } -/* =相关补充= */ - @keyframes enlarge-in-fade { 0% { - transform: scale(0); - opacity: 0; + transform: scale(var(--tv-motion-scale-start, 0)); + opacity: var(--tv-motion-scale-opacity-start, 0); } - 50% { - transform: scale(0.5); - opacity: 0.5; + transform: scale(var(--tv-motion-scale-mid, 0.5)); + opacity: var(--tv-motion-scale-opacity-mid, 0.5); } - 100% { - transform: scale(1); - opacity: 1; + transform: scale(var(--tv-motion-scale-end, 1)); + opacity: var(--tv-motion-scale-opacity-end, 1); } } +/* ============ 收缩缩放 ============ */ @keyframes shrink-out { 0% { - transform: scale(1); + transform: scale(var(--tv-motion-scale-end, 1)); } - 50% { - transform: scale(0.5); + transform: scale(var(--tv-motion-scale-mid, 0.5)); } - 100% { - transform: scale(0); + transform: scale(var(--tv-motion-scale-start, 0)); } } @keyframes shrink-out-fade { 0% { - transform: scale(1); - opacity: 1; + transform: scale(var(--tv-motion-scale-end, 1)); + opacity: var(--tv-motion-scale-opacity-end, 1); } - 50% { - transform: scale(0.5); - opacity: 0.5; + transform: scale(var(--tv-motion-scale-mid, 0.5)); + opacity: var(--tv-motion-scale-opacity-mid, 0.5); } - 100% { - transform: scale(0); - opacity: 0; + transform: scale(var(--tv-motion-scale-start, 0)); + opacity: var(--tv-motion-scale-opacity-start, 0); } } - -/* =补充结束= */ \ No newline at end of file diff --git a/packages/theme/src/popup/index.less b/packages/theme/src/popup/index.less index 96df9ba9a2..906b5a9f23 100644 --- a/packages/theme/src/popup/index.less +++ b/packages/theme/src/popup/index.less @@ -19,11 +19,11 @@ .@{fade-prefix-cls} { &-enter-active { - animation: 0.3s fade-in both ease-out; + animation: var(--tv-motion-fade-speed) fade-in both ease-out; } &-leave-active { - animation: 0.3s fade-out both ease-in; + animation: var(--tv-motion-fade-speed) fade-out both ease-in; } } diff --git a/packages/theme/src/skeleton-item/index.less b/packages/theme/src/skeleton-item/index.less index 72ee9df72e..1301b21ab7 100644 --- a/packages/theme/src/skeleton-item/index.less +++ b/packages/theme/src/skeleton-item/index.less @@ -1,5 +1,6 @@ @import '../custom.less'; @import './vars.less'; +@import '../motion/index.less'; @skeleton-item-prefix-cls: ~'@{css-prefix}skeleton-item'; @@ -11,7 +12,7 @@ background: var(--tv-SkeletonItem-linear-gradient); background-size: 200% 100%; background-position-x: 180%; - animation: 1.5s skeleton-loading ease-in-out infinite; + animation: var(--tv-motion-skeleton-speed) skeleton-loading ease-in-out infinite; } } @@ -73,9 +74,3 @@ } } } - -@keyframes skeleton-loading { - to { - background-position-x: -20%; - } -} diff --git a/packages/theme/src/tabs/index.less b/packages/theme/src/tabs/index.less index 58d5053840..dad14fbce6 100644 --- a/packages/theme/src/tabs/index.less +++ b/packages/theme/src/tabs/index.less @@ -35,7 +35,6 @@ overflow: hidden; } - /** 头部场景 */ &__header { position: relative; @@ -45,7 +44,6 @@ align-items: center; .@{tabs-prefix-cls} { - // 活跃块 &__active-bar { position: absolute; @@ -238,7 +236,6 @@ } .@{tabs-prefix-cls}__icon-close { - &, &:hover { background-color: transparent; @@ -251,7 +248,6 @@ } &.is-closable { - // 修复自定义标签配置:with-close="true"样式错乱问题 > div { display: inline-block; @@ -274,7 +270,8 @@ border-radius: 4px; text-align: center; transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); - margin: var(--tv-Tabs-icon-close-margin-vertical) var(--tv-Tabs-icon-close-margin-right) var(--tv-Tabs-icon-close-margin-vertical) var(--tv-Tabs-icon-close-margin-left); + margin: var(--tv-Tabs-icon-close-margin-vertical) var(--tv-Tabs-icon-close-margin-right) + var(--tv-Tabs-icon-close-margin-vertical) var(--tv-Tabs-icon-close-margin-left); display: inline-flex; justify-content: center; align-items: center; @@ -418,7 +415,8 @@ font-size: var(--tv-Tabs-prev-next-btn-icon-size); } - .@{tabs-prefix-cls}__nav.is-show-active-bar .@{tabs-prefix-cls}__item:not(.@{tabs-prefix-cls}__item-separator-space) { + .@{tabs-prefix-cls}__nav.is-show-active-bar + .@{tabs-prefix-cls}__item:not(.@{tabs-prefix-cls}__item-separator-space) { margin-right: var(--tv-Tabs-small-item-margin-right); } @@ -435,7 +433,6 @@ // 一层tab页签: card类型 &&--card { - &.@{tabs-prefix-cls}--left .@{tabs-prefix-cls}__nav, &.@{tabs-prefix-cls}--right .@{tabs-prefix-cls}__nav { width: 120px; @@ -991,7 +988,6 @@ &&--left, &&--right { .@{tabs-prefix-cls} { - &__header, &__nav-wrap { height: 100%; @@ -1105,7 +1101,6 @@ } .@{tab-pane-prefix-cls} { - .@{tabs-prefix-cls}__header, .@{tabs-prefix-cls}__nav-wrap { float: inherit; @@ -1236,7 +1231,6 @@ &.is-left, &.is-right { - .@{tabs-prefix-cls}__nav-prev, .@{tabs-prefix-cls}__nav-next { display: none; @@ -1325,29 +1319,25 @@ } .slideInRight-enter { - -webkit-animation: slideInRight-enter 0.3s; - animation: tab-slide-right-in 0.3s; + animation: tab-slide-right-in var(--tv-motion-tab-speed); } .slideInRight-leave { position: absolute; left: 0; right: 0; - -webkit-animation: slideInRight-leave 0.3s; - animation: tab-slide-right-out 0.3s; + animation: tab-slide-right-out var(--tv-motion-tab-speed); } .slideInLeft-enter { - -webkit-animation: slideInLeft-enter 0.3s; - animation: tab-slide-left-in 0.3s; + animation: tab-slide-left-in var(--tv-motion-tab-speed); } .slideInLeft-leave { position: absolute; left: 0; right: 0; - -webkit-animation: slideInLeft-leave 0.3s; - animation: tab-slide-left-out 0.3s; + animation: tab-slide-left-out var(--tv-motion-tab-speed); } } // @-webkit-keyframes slideInRight-enter { @@ -1493,4 +1483,4 @@ // opacity: 0; // } // } -// } \ No newline at end of file +// } diff --git a/packages/theme/src/transition/carousel-arrow.less b/packages/theme/src/transition/carousel-arrow.less index c2547fc74b..ecadd19bca 100644 --- a/packages/theme/src/transition/carousel-arrow.less +++ b/packages/theme/src/transition/carousel-arrow.less @@ -36,11 +36,11 @@ } .@{css-prefix}transition-carousel-arrow-right-enter-active { - animation: arrow-right-carousel 0.3s; + animation: arrow-right-carousel var(--tv-motion-arrow-speed); } .@{css-prefix}transition-carousel-arrow-right-leave-active { - animation: arrow-right-carousel 0.3s reverse; + animation: arrow-right-carousel var(--tv-motion-arrow-speed) reverse; } // @keyframes animation-right { diff --git a/packages/theme/src/transition/icon.less b/packages/theme/src/transition/icon.less index c1cdcf5348..335af554aa 100644 --- a/packages/theme/src/transition/icon.less +++ b/packages/theme/src/transition/icon.less @@ -15,19 +15,19 @@ // input右边icon显示隐藏动画 .@{css-prefix}transition-icon-out-in-enter-active { - animation: bounce-in 0.3s; + animation: bounce-in var(--tv-motion-bounce-speed); } .@{css-prefix}transition-icon-out-in-leave-active { - animation: bounce-in 0.3s reverse; + animation: bounce-in var(--tv-motion-bounce-speed) reverse; } .@{css-prefix}transition-icon-scale-in-enter-active { - animation: bounce-in 0.3s; + animation: bounce-in var(--tv-motion-bounce-speed); } .@{css-prefix}transition-icon-scale-in-leave-active { - animation: bounce-in 0.3s reverse; + animation: bounce-in var(--tv-motion-bounce-speed) reverse; } // @keyframes bounce-in { diff --git a/packages/theme/src/transition/timepicker.less b/packages/theme/src/transition/timepicker.less index 1d2548e607..cd78855e96 100644 --- a/packages/theme/src/transition/timepicker.less +++ b/packages/theme/src/transition/timepicker.less @@ -14,11 +14,11 @@ @import '../motion/index.less'; .@{css-prefix}transition-timepicker { - animation: fade-in-timepicker 0.3s; + animation: fade-in-timepicker var(--tv-motion-fade-speed); } .@{css-prefix}transition-timepicker-up { - animation: fade-up-timepicker 0.3s; + animation: fade-up-timepicker var(--tv-motion-fade-speed); } // @keyframes fadein { From 7dd09a29cdc92eefa49baec7e8cb6dc324fd3642 Mon Sep 17 00:00:00 2001 From: Lyra <1170158548@qq.com> Date: Tue, 2 Sep 2025 16:11:45 +0800 Subject: [PATCH 4/7] feat(theme): [motion] update the documentation and fix some bug --- packages/theme/src/dialog-box/index.less | 6 +- packages/theme/src/drawer/index.less | 4 +- ...50\346\225\210\351\205\215\347\275\256.md" | 67 ++++++++++--------- ...15\347\275\256\347\273\264\346\212\244.md" | 38 +++++++---- packages/theme/src/motion/index.less | 8 --- 5 files changed, 65 insertions(+), 58 deletions(-) diff --git a/packages/theme/src/dialog-box/index.less b/packages/theme/src/dialog-box/index.less index 1ce1bff20d..b11fe69fb0 100644 --- a/packages/theme/src/dialog-box/index.less +++ b/packages/theme/src/dialog-box/index.less @@ -232,11 +232,13 @@ // } .dialog-slideRight-enter-active { - animation: slide-right-in 0.5s ease-in forwards; + --tv-motion-slide-speed: 0.5s; + animation: slide-right-in var(--tv-motion-slide-speed) ease-in forwards; } .dialog-slideRight-leave-active { - animation: slide-right-out 0.5s ease-in forwards; + --tv-motion-slide-speed: 0.5s; + animation: slide-right-out var(--tv-motion-slide-speed) ease-in forwards; } // @keyframes slideRight { diff --git a/packages/theme/src/drawer/index.less b/packages/theme/src/drawer/index.less index 1a3c4b1f22..e36a327a59 100644 --- a/packages/theme/src/drawer/index.less +++ b/packages/theme/src/drawer/index.less @@ -214,11 +214,11 @@ } .drawer-slide-right-enter-active { - animation: slide-right-in 0.3s linear; + animation: slide-right-in var(--tv-motion-slide-speed) linear; } .drawer-slide-right-leave-active { - animation: slide-right-out 0.3s linear; + animation: slide-right-out var(--tv-motion-slide-speed) linear; } // @keyframes slideRight { diff --git "a/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256.md" "b/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256.md" index d9705db17f..9211710491 100644 --- "a/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256.md" +++ "b/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256.md" @@ -21,8 +21,9 @@ ```less :root { /* 蚂蚁线相关配置 */ - --ants-shift: 8px; - --ants-speed: 0.8s; + --tv-motion-ants-shift: 8px; + --tv-motion-ants-speed: 0.8s; + ... } ``` @@ -30,8 +31,8 @@ ```css .copyed-borders { - --ants-shift: 8px; - --ants-speed: 0.8s; + --tv-motion-ants-shift: 12px; + --tv-motion-ants-speed: 1.2s; } ``` @@ -91,11 +92,11 @@ motion/ ```less .@{fade-prefix-cls} { &-enter-active { - animation: 0.3s fade-in both ease-out; + animation: var(--tv-motion-fade-speed) fade-in both ease-out; } &-leave-active { - animation: 0.3s fade-out both ease-in; + animation: var(--tv-motion-fade-speed) fade-out both ease-in; } } ``` @@ -105,17 +106,16 @@ motion/ ### 3.2 示例:滑动 (slide.less) ```less +/* ============ 左滑 ============ */ @keyframes slide-left-in { 0% { opacity: 0; - transform: translateX(-100%); + transform: translateX(var(--tv-motion-slide-offset-left)); } - 50% { - opacity: 0.6; - transform: translateX(-50%); + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateX(var(--tv-motion-slide-offset-left-mid)); } - 100% { opacity: 1; transform: translateX(0%); @@ -127,15 +127,13 @@ motion/ opacity: 1; transform: translateX(0%); } - 50% { - opacity: 0.6; - transform: translateX(-50%); + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateX(var(--tv-motion-slide-offset-left-mid)); } - 100% { opacity: 0; - transform: translateX(-100%); + transform: translateX(var(--tv-motion-slide-offset-left)); } } ``` @@ -144,11 +142,11 @@ motion/ ```less .drawer-slide-left-enter-active { - animation: slide-left-in 0.3s linear; + animation: slide-left-in var(--tv-motion-slide-speed) linear; } .drawer-slide-left-leave-active { - animation: slide-left-out 0.3s linear; + animation: slide-left-out var(--tv-motion-slide-speed) linear; } ``` @@ -159,9 +157,8 @@ motion/ 0% { background-position: 0 0; } - 100% { - background-position: var(--ants-shift, 8px) 0; + background-position: var(--tv-motion-ants-shift, 8px) 0; } } @@ -169,9 +166,8 @@ motion/ 0% { background-position: 0 0; } - 100% { - background-position: calc(-1 * var(--ants-shift, 8px)) 0; + background-position: calc(-1 * var(--tv-motion-ants-shift, 8px)) 0; } } ``` @@ -179,17 +175,22 @@ motion/ 组件调用示例: ```less -.@{grid-prefix-cls}-copyed-borders { - --ants-shift: 13px; - --ants-speed: 0.8s; - - .@{grid-prefix-cls}-border-top { - animation: ants-x var(--ants-speed) linear infinite; + .@{grid-prefix-cls}-copyed-borders { + --tv-motion-ants-shift: 13px; + + .@{grid-prefix-cls}-border-top { + animation: ants-x var(--tv-motion-ants-speed) linear infinite; + } + .@{grid-prefix-cls}-border-right { + animation: ants-y var(--tv-motion-ants-speed) linear infinite; + } + .@{grid-prefix-cls}-border-bottom { + animation: ants-x-rev var(--tv-motion-ants-speed) linear infinite; + } + .@{grid-prefix-cls}-border-left { + animation: ants-y-rev var(--tv-motion-ants-speed) linear infinite; + } } - .@{grid-prefix-cls}-border-bottom { - animation: ants-x-rev var(--ants-speed) linear infinite; - } -} ``` ------ @@ -207,7 +208,7 @@ motion/ ```less .drawer-slide-left-enter-active { - animation: slide-left-in 0.3s linear; + animation: slide-left-in var(--tv-motion-slide-speed) linear; } ``` diff --git "a/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256\347\273\264\346\212\244.md" "b/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256\347\273\264\346\212\244.md" index e310656052..50cf9fea8f 100644 --- "a/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256\347\273\264\346\212\244.md" +++ "b/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256\347\273\264\346\212\244.md" @@ -36,8 +36,10 @@ motion/ ```less :root { - --ants-shift: 8px; - --ants-speed: 0.8s; + /* 蚂蚁线相关配置 */ + --tv-motion-ants-shift: 8px; + --tv-motion-ants-speed: 0.8s; + ... } ``` @@ -73,26 +75,38 @@ motion/ 在对应 `motion/*.less` 文件中新增动效,示例: ```less -@keyframes slide-up-in { - 0% { transform: translateY(100%); opacity: 0; } - 100% { transform: translateY(0); opacity: 1; } +@keyframes fade-in-up { + 0% { + transform: translate3d(0, -20p, 0); + opacity: 0; + } + 100% { + transform: translate3d(0, 0, 0); + opacity: 1; + } } ``` ### Step 2. (可选)使用变量替代固定值 ```less -@keyframes ants-x { - 0% { background-position: 0 0; } - 100% { background-position: var(--ants-shift) 0; } +@keyframes fade-in-up { + 0% { + transform: translate3d(0, calc(-1 * var(--tv-motion-fade-offset-y, 20px)), 0); + opacity: 0; + } + 100% { + transform: translate3d(0, 0, 0); + opacity: 1; + } } ``` ### Step 3. 在组件中绑定 ```less -.modal-slide-up-enter-active { - animation: slide-up-in 0.3s linear; +.dialog-fade-enter-active { + animation: fade-in-up var(--tv-motion-fade-speed); } ``` @@ -121,9 +135,7 @@ motion/ ## 7. 组件集成方式 1. **全局引入** - 所有动效在 `motion/*` 中维护,并在组件中通过 className 使用。 -2. **局部调用** - 组件通过 `-enter-active` / `-leave-active` 调用。 + 所有动效在 `motion/*` 中维护,并在组件中通过className或者animation使用。 3. **覆盖参数** 用户可覆盖变量来自定义速度/时长。 diff --git a/packages/theme/src/motion/index.less b/packages/theme/src/motion/index.less index 16cec11b05..465ff53ae4 100644 --- a/packages/theme/src/motion/index.less +++ b/packages/theme/src/motion/index.less @@ -14,11 +14,3 @@ @import './loading.less'; @import './shine.less'; @import './ants.less'; - -/* ========================================== - 全局变量配置 (:root) -========================================== */ -:root, -:host { - -} From fa751187abb2ae0f0c82218e6a69f0858dc4bc97 Mon Sep 17 00:00:00 2001 From: Lyra <1170158548@qq.com> Date: Tue, 2 Sep 2025 19:49:03 +0800 Subject: [PATCH 5/7] feat(theme): [motion] rename the documentation and remove unnecessary comments --- packages/theme/src/base/reset.less | 10 -- packages/theme/src/base/transition.less | 26 --- packages/theme/src/base/vars.less | 2 +- packages/theme/src/chart-core/index.less | 23 --- packages/theme/src/dialog-box/index.less | 86 ---------- packages/theme/src/drawer/index.less | 158 +----------------- packages/theme/src/fall-menu/index.less | 31 +--- packages/theme/src/grid/body.less | 10 -- packages/theme/src/grid/excel.less | 10 -- packages/theme/src/grid/icon.less | 12 +- packages/theme/src/grid/loading.less | 10 -- packages/theme/src/image/index.less | 30 +--- ...bal Animation Configuration Maintenance.md | 0 .../TinyVue Global Animation Configuration.md | 0 packages/theme/src/popup/index.less | 20 --- packages/theme/src/progress/index.less | 23 +-- packages/theme/src/scroll-text/index.less | 70 +------- packages/theme/src/tabs/index.less | 144 ---------------- .../theme/src/transition/carousel-arrow.less | 28 +--- packages/theme/src/transition/icon.less | 30 +--- packages/theme/src/transition/timepicker.less | 26 +-- packages/theme/src/tree/index.less | 26 +-- 22 files changed, 11 insertions(+), 764 deletions(-) rename "packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256\347\273\264\346\212\244.md" => packages/theme/src/motion/TinyVue Global Animation Configuration Maintenance.md (100%) rename "packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256.md" => packages/theme/src/motion/TinyVue Global Animation Configuration.md (100%) diff --git a/packages/theme/src/base/reset.less b/packages/theme/src/base/reset.less index 4905b39ced..0f8fe377eb 100644 --- a/packages/theme/src/base/reset.less +++ b/packages/theme/src/base/reset.less @@ -21,16 +21,6 @@ animation: rotate-z var(--tv-motion-rotate-speed) linear infinite; } -// @keyframes rotating { -// 0% { -// transform: rotateZ(0deg); -// } - -// 100% { -// transform: rotateZ(360deg); -// } -// } - // 高亮节点 .tiny-hl-query-node { color: var(--tv-color-text-active) !important; diff --git a/packages/theme/src/base/transition.less b/packages/theme/src/base/transition.less index 8fae75e43f..28df7ee3a7 100644 --- a/packages/theme/src/base/transition.less +++ b/packages/theme/src/base/transition.less @@ -244,29 +244,3 @@ vue3的动画状态类: v-enter-from v-enter-to v-leave-from v-leave-to 以 .tiny-transition-alert-fade-leave-active { transition: opacity 0.3s ease-in; } - -// modal 的动画 -// @keyframes modal-fade-in { -// 0% { -// transform: translate3d(0, -20px, 0); -// opacity: 0; -// } - -// 100% { -// transform: translate3d(0, 0, 0); -// opacity: 1; -// } -// } - - -// @keyframes modal-fade-out { -// 0% { -// transform: translate3d(0, 0, 0); -// opacity: 1; -// } - -// 100% { -// transform: translate3d(0, -20px, 0); -// opacity: 0; -// } -// } diff --git a/packages/theme/src/base/vars.less b/packages/theme/src/base/vars.less index 1e1ec03888..541913a714 100644 --- a/packages/theme/src/base/vars.less +++ b/packages/theme/src/base/vars.less @@ -576,7 +576,7 @@ --tv-motion-shine-offset-y: -12px; /* Y轴背景位移 */ /* ---------- 滑动方向 (slide.less) ---------- */ - --tv-motion-slide-speed: 0.3s; /* 动画时长 */ + --tv-motion-slide-speed: 1s; /* 动画时长 */ --tv-motion-slide-opacity-mid: 0.6; /* 中间透明度 */ /* X轴偏移 */ --tv-motion-slide-offset-left: -100%; /* 左侧初始位移 */ diff --git a/packages/theme/src/chart-core/index.less b/packages/theme/src/chart-core/index.less index 5b1f5e1290..20edc3a08a 100644 --- a/packages/theme/src/chart-core/index.less +++ b/packages/theme/src/chart-core/index.less @@ -70,26 +70,3 @@ filter: blur(1px); } } - -// @keyframes loading-rotate { -// 100% { -// transform: rotate(360deg); -// } -// } - -// @keyframes loading-dash { -// 0% { -// stroke-dasharray: 1, 200; -// stroke-dashoffset: 0; -// } - -// 50% { -// stroke-dasharray: 90, 150; -// stroke-dashoffset: -40px; -// } - -// 100% { -// stroke-dasharray: 90, 150; -// stroke-dashoffset: -120px; -// } -// } diff --git a/packages/theme/src/dialog-box/index.less b/packages/theme/src/dialog-box/index.less index b11fe69fb0..b665887c80 100644 --- a/packages/theme/src/dialog-box/index.less +++ b/packages/theme/src/dialog-box/index.less @@ -219,62 +219,14 @@ animation: fade-out var(--tv-motion-fade-speed) ease forwards; } -// @keyframes v-modal-in { -// 0% { -// opacity: 0; -// } -// } - -// @keyframes v-modal-out { -// 100% { -// opacity: 0; -// } -// } - .dialog-slideRight-enter-active { - --tv-motion-slide-speed: 0.5s; animation: slide-right-in var(--tv-motion-slide-speed) ease-in forwards; } .dialog-slideRight-leave-active { - --tv-motion-slide-speed: 0.5s; animation: slide-right-out var(--tv-motion-slide-speed) ease-in forwards; } -// @keyframes slideRight { -// 0% { -// opacity: 0; -// transform: translateX(100%); -// } - -// 50% { -// opacity: 0.6; -// transform: translateX(50%); -// } - -// 100% { -// opacity: 1; -// transform: translateX(0%); -// } -// } - -// @keyframes slideRightout { -// 0% { -// opacity: 1; -// transform: translateX(0%); -// } - -// 50% { -// opacity: 0.6; -// transform: translateX(50%); -// } - -// 100% { -// opacity: 0; -// transform: translateX(100%); -// } -// } - .dialog-fade-enter-active { animation: fade-in-up var(--tv-motion-fade-speed); } @@ -287,48 +239,10 @@ animation: fade-out-up var(--tv-motion-fade-speed); } -// @keyframes dialog-fade-in { -// 0% { -// transform: translate3d(0, -20px, 0); -// opacity: 0; -// } - -// 100% { -// transform: translate3d(0, 0, 0); -// opacity: 1; -// } -// } - -// @keyframes dialog-fade-out { -// 0% { -// transform: translate3d(0, 0, 0); -// opacity: 1; -// } - -// 100% { -// transform: translate3d(0, -20px, 0); -// opacity: 0; -// } -// } - .enlarge-enter-active { animation: enlarge-in var(--tv-motion-scale-speed) linear; } -// @keyframes enlarge-in { -// 0% { -// transform: scale(0); -// } - -// 50% { -// transform: scale(0.5); -// } - -// 100% { -// transform: scale(1); -// } -// } - @media (max-width: 480px) { .@{dialog-box-prefix-cls} { width: 100% !important; diff --git a/packages/theme/src/drawer/index.less b/packages/theme/src/drawer/index.less index e36a327a59..6dc05a18e3 100644 --- a/packages/theme/src/drawer/index.less +++ b/packages/theme/src/drawer/index.less @@ -221,40 +221,6 @@ animation: slide-right-out var(--tv-motion-slide-speed) linear; } -// @keyframes slideRight { -// 0% { -// opacity: 0; -// transform: translateX(100%); -// } - -// 50% { -// opacity: 0.6; -// transform: translateX(50%); -// } - -// 100% { -// opacity: 1; -// transform: translateX(0%); -// } -// } - -// @keyframes slideRightout { -// 0% { -// opacity: 1; -// transform: translateX(0%); -// } - -// 50% { -// opacity: 0.6; -// transform: translateX(50%); -// } - -// 100% { -// opacity: 0; -// transform: translateX(100%); -// } -// } - .drawer-slide-left-enter-active { animation: slide-left-in var(--tv-motion-slide-speed) linear; } @@ -263,40 +229,6 @@ animation: slide-left-out var(--tv-motion-slide-speed) linear; } -// @keyframes slideLeft { -// 0% { -// opacity: 0; -// transform: translateX(-100%); -// } - -// 50% { -// opacity: 0.6; -// transform: translateX(-50%); -// } - -// 100% { -// opacity: 1; -// transform: translateX(0%); -// } -// } - -// @keyframes slideLeftout { -// 0% { -// opacity: 1; -// transform: translateX(0%); -// } - -// 50% { -// opacity: 0.6; -// transform: translateX(-50%); -// } - -// 100% { -// opacity: 0; -// transform: translateX(-100%); -// } -// } - .drawer-slide-bottom-enter-active { animation: slide-bottom-in var(--tv-motion-slide-speed) linear; } @@ -305,40 +237,6 @@ animation: slide-bottom-out var(--tv-motion-slide-speed) linear; } -// @keyframes slideBottom { -// 0% { -// opacity: 0; -// transform: translateY(100%); -// } - -// 50% { -// opacity: 0.6; -// transform: translateY(50%); -// } - -// 100% { -// opacity: 1; -// transform: translateY(0%); -// } -// } - -// @keyframes slideBottomout { -// 0% { -// opacity: 0; -// transform: translateY(0%); -// } - -// 50% { -// opacity: 0.6; -// transform: translateY(50%); -// } - -// 100% { -// opacity: 1; -// transform: translateY(100%); -// } -// } - .drawer-slide-top-enter-active { animation: slide-top-in var(--tv-motion-slide-speed) linear; } @@ -347,64 +245,10 @@ animation: slide-top-out var(--tv-motion-slide-speed) linear; } -// @keyframes slideTop { -// 0% { -// opacity: 0; -// transform: translateY(-100%); -// } - -// 50% { -// opacity: 0.6; -// transform: translateY(-50%); -// } - -// 100% { -// opacity: 1; -// transform: translateY(0%); -// } -// } - -// @keyframes slideTopout { -// 0% { -// opacity: 0; -// transform: translateY(0%); -// } - -// 50% { -// opacity: 0.6; -// transform: translateY(-50%); -// } - -// 100% { -// opacity: 1; -// transform: translateY(-100%); -// } -// } - .drawer-fade-enter-active { animation: fade-in var(--tv-motion-fade-speed) linear; } .drawer-fade-leave-active { animation: fade-out var(--tv-motion-fade-speed) linear; -} - -// @keyframes drawer-fade-in { -// 0% { -// opacity: 0; -// } - -// 100% { -// opacity: 1; -// } -// } - -// @keyframes drawer-fade-out { -// 0% { -// opacity: 1; -// } - -// 100% { -// opacity: 0; -// } -// } +} \ No newline at end of file diff --git a/packages/theme/src/fall-menu/index.less b/packages/theme/src/fall-menu/index.less index ab5fb4814b..1431f54cc7 100644 --- a/packages/theme/src/fall-menu/index.less +++ b/packages/theme/src/fall-menu/index.less @@ -185,33 +185,4 @@ .opacity(1); } } -} - -// notice: The following keyframes are commented out as they are not used in the current implementation. -// @keyframes leftArrow { -// 0% { -// left: -17px; -// } - -// 50% { -// left: -13px; -// } - -// 100% { -// left: -17px; -// } -// } - -// @keyframes rightArrow { -// 0% { -// right: -17px; -// } - -// 50% { -// right: -13px; -// } - -// 100% { -// right: -17px; -// } -// } +} \ No newline at end of file diff --git a/packages/theme/src/grid/body.less b/packages/theme/src/grid/body.less index 59c0818ef7..ed5821491f 100644 --- a/packages/theme/src/grid/body.less +++ b/packages/theme/src/grid/body.less @@ -101,13 +101,3 @@ } } } - -// @keyframes shine { -// 0% { -// background-position: -1px -1px; -// } - -// 100% { -// background-position: -12px -12px; -// } -// } diff --git a/packages/theme/src/grid/excel.less b/packages/theme/src/grid/excel.less index d4093f3498..a9e65ae91c 100644 --- a/packages/theme/src/grid/excel.less +++ b/packages/theme/src/grid/excel.less @@ -80,13 +80,3 @@ } } } - -// @keyframes shine { -// 0% { -// background-position: -1px -1px; -// } - -// 100% { -// background-position: -12px -12px; -// } -// } diff --git a/packages/theme/src/grid/icon.less b/packages/theme/src/grid/icon.less index eff3c6c1b7..9f337a466f 100644 --- a/packages/theme/src/grid/icon.less +++ b/packages/theme/src/grid/icon.less @@ -384,14 +384,4 @@ content: '\2716'; } } -} - -// @keyframes rollCircle { -// 0% { -// transform: rotate(0deg); -// } - -// 100% { -// transform: rotate(360deg); -// } -// } +} \ No newline at end of file diff --git a/packages/theme/src/grid/loading.less b/packages/theme/src/grid/loading.less index dbb82fbef3..ee822deb52 100644 --- a/packages/theme/src/grid/loading.less +++ b/packages/theme/src/grid/loading.less @@ -61,16 +61,6 @@ animation: grid-loading var(--tv-motion-grid-loading-speed) ease infinite; } - // @keyframes load { - // 0% { - // opacity: 10; - // } - - // 100% { - // opacity: 0.1; - // } - // } - span:nth-child(1) { top: 68%; left: 68%; diff --git a/packages/theme/src/image/index.less b/packages/theme/src/image/index.less index 6d0386e7de..d8315b0157 100644 --- a/packages/theme/src/image/index.less +++ b/packages/theme/src/image/index.less @@ -86,32 +86,4 @@ .viewer-fade-leave-active { animation: fade-out-up var(--tv-motion-fade-speed); -} - -// @keyframes viewer-fade-in { -// 0% { -// -webkit-transform: translate3d(0, -20px, 0); -// transform: translate3d(0, -20px, 0); -// opacity: 0; -// } - -// 100% { -// -webkit-transform: translate3d(0, 0, 0); -// transform: translate3d(0, 0, 0); -// opacity: 1; -// } -// } - -// @keyframes viewer-fade-out { -// 0% { -// -webkit-transform: translate3d(0, 0, 0); -// transform: translate3d(0, 0, 0); -// opacity: 1; -// } - -// 100% { -// -webkit-transform: translate3d(0, -20px, 0); -// transform: translate3d(0, -20px, 0); -// opacity: 0; -// } -// } +} \ No newline at end of file diff --git "a/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256\347\273\264\346\212\244.md" b/packages/theme/src/motion/TinyVue Global Animation Configuration Maintenance.md similarity index 100% rename from "packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256\347\273\264\346\212\244.md" rename to packages/theme/src/motion/TinyVue Global Animation Configuration Maintenance.md diff --git "a/packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256.md" b/packages/theme/src/motion/TinyVue Global Animation Configuration.md similarity index 100% rename from "packages/theme/src/motion/TinyVue \345\205\250\345\261\200\345\212\250\346\225\210\351\205\215\347\275\256.md" rename to packages/theme/src/motion/TinyVue Global Animation Configuration.md diff --git a/packages/theme/src/popup/index.less b/packages/theme/src/popup/index.less index 906b5a9f23..9b8893b3a5 100644 --- a/packages/theme/src/popup/index.less +++ b/packages/theme/src/popup/index.less @@ -158,23 +158,3 @@ } } } - -// @keyframes mobile-fade-in { -// from { -// opacity: 0; -// } - -// to { -// opacity: 1; -// } -// } - -// @keyframes mobile-fade-out { -// from { -// opacity: 1; -// } - -// to { -// opacity: 0; -// } -// } diff --git a/packages/theme/src/progress/index.less b/packages/theme/src/progress/index.less index fe415eb822..2300a1e92e 100644 --- a/packages/theme/src/progress/index.less +++ b/packages/theme/src/progress/index.less @@ -145,25 +145,4 @@ } } } -} - -// notice: not used -// @-webkit-keyframes progress { -// 0% { -// background-position: 0 0; -// } - -// 100% { -// background-position: 32px 0; -// } -// } - -// @keyframes progress { -// 0% { -// background-position: 0 0; -// } - -// 100% { -// background-position: 32px 0; -// } -// } +} \ No newline at end of file diff --git a/packages/theme/src/scroll-text/index.less b/packages/theme/src/scroll-text/index.less index 68263bf1b9..d1fb118c7e 100644 --- a/packages/theme/src/scroll-text/index.less +++ b/packages/theme/src/scroll-text/index.less @@ -108,72 +108,4 @@ } } } -} - -// @keyframes moveLeft { -// 0% { -// transform: translateX(300px); -// } - -// 100% { -// transform: translateX(-100%); -// } -// } - -// @keyframes moveRight { -// 0% { -// transform: translateX(-100%); -// } - -// 100% { -// transform: translateX(300px); -// } -// } - -// @keyframes moveUp { -// 0% { -// transform: translateY(100%); -// } - -// 100% { -// transform: translateY(-100%); -// } -// } - -// @keyframes moveDown { -// 0% { -// transform: translateY(-100%); -// } - -// 100% { -// transform: translateY(100%); -// } -// } - -// @keyframes moveLeftWidthAdapt { -// 0% { -// transform: translateX(100%); -// } - -// 50% { -// transform: translateX(0); -// } - -// 100% { -// transform: translateX(-100%); -// } -// } - -// @keyframes moveRightWidthAdapt { -// 0% { -// transform: translateX(-100%); -// } - -// 50% { -// transform: translateX(0); -// } - -// 100% { -// transform: translateX(100%); -// } -// } +} \ No newline at end of file diff --git a/packages/theme/src/tabs/index.less b/packages/theme/src/tabs/index.less index dad14fbce6..925ba2b77d 100644 --- a/packages/theme/src/tabs/index.less +++ b/packages/theme/src/tabs/index.less @@ -1340,147 +1340,3 @@ animation: tab-slide-left-out var(--tv-motion-tab-speed); } } -// @-webkit-keyframes slideInRight-enter { -// 0% { -// opacity: 0; -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(100%); -// transform: translateX(100%); -// } - -// to { -// opacity: 1; -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(0); -// transform: translateX(0); -// } -// } - -// @keyframes slideInRight-enter { -// 0% { -// opacity: 0; -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(100%); -// transform: translateX(100%); -// } - -// to { -// opacity: 1; -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(0); -// transform: translateX(0); -// } -// } - -// @-webkit-keyframes slideInRight-leave { -// 0% { -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(0); -// transform: translateX(0); -// opacity: 1; -// } - -// 100% { -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(100%); -// transform: translateX(100%); -// opacity: 0; -// } -// } - -// @keyframes slideInRight-leave { -// 0% { -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(0); -// transform: translateX(0); -// opacity: 1; -// } - -// 100% { -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(100%); -// transform: translateX(100%); -// opacity: 0; -// } -// } - -// @-webkit-keyframes slideInLeft-enter { -// 0% { -// opacity: 0; -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(-100%); -// transform: translateX(-100%); -// } - -// to { -// opacity: 1; -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(0); -// transform: translateX(0); -// } -// } - -// @keyframes slideInLeft-enter { -// 0% { -// opacity: 0; -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(-100%); -// transform: translateX(-100%); -// } - -// to { -// opacity: 1; -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(0); -// transform: translateX(0); -// } -// } - -// @-webkit-keyframes slideInLeft-leave { -// 0% { -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(0); -// transform: translateX(0); -// opacity: 1; -// } - -// 100% { -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(-100%); -// transform: translateX(-100%); -// opacity: 0; -// } -// } - -// @keyframes slideInLeft-leave { -// 0% { -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(0); -// transform: translateX(0); -// opacity: 1; -// } - -// 100% { -// -webkit-transform-origin: 0 0; -// transform-origin: 0 0; -// -webkit-transform: translateX(-100%); -// transform: translateX(-100%); -// opacity: 0; -// } -// } -// } diff --git a/packages/theme/src/transition/carousel-arrow.less b/packages/theme/src/transition/carousel-arrow.less index ecadd19bca..78f9d108bc 100644 --- a/packages/theme/src/transition/carousel-arrow.less +++ b/packages/theme/src/transition/carousel-arrow.less @@ -41,30 +41,4 @@ .@{css-prefix}transition-carousel-arrow-right-leave-active { animation: arrow-right-carousel var(--tv-motion-arrow-speed) reverse; -} - -// @keyframes animation-right { -// 0% { -// opacity: 0; -// right: 0; -// } - -// 100% { -// opacity: 1; -// transform: translateY(-50%); -// right: 16px; -// } -// } - -// @keyframes animation-left { -// 0% { -// opacity: 0; -// left: 0; -// } - -// 100% { -// opacity: 1; -// transform: translateY(-50%); -// left: 16px; -// } -// } +} \ No newline at end of file diff --git a/packages/theme/src/transition/icon.less b/packages/theme/src/transition/icon.less index 335af554aa..87518c25a7 100644 --- a/packages/theme/src/transition/icon.less +++ b/packages/theme/src/transition/icon.less @@ -28,32 +28,4 @@ .@{css-prefix}transition-icon-scale-in-leave-active { animation: bounce-in var(--tv-motion-bounce-speed) reverse; -} - -// @keyframes bounce-in { -// 0% { -// transform: scale(0); -// } - -// 50% { -// transform: scale(1.2); -// } - -// 100% { -// transform: scale(1); -// } -// } - -// @keyframes scale-in { -// 0% { -// transform: scale(0); -// } - -// 50% { -// transform: scale(1.2); -// } - -// 100% { -// transform: scale(1); -// } -// } +} \ No newline at end of file diff --git a/packages/theme/src/transition/timepicker.less b/packages/theme/src/transition/timepicker.less index cd78855e96..1792c74dae 100644 --- a/packages/theme/src/transition/timepicker.less +++ b/packages/theme/src/transition/timepicker.less @@ -19,28 +19,4 @@ .@{css-prefix}transition-timepicker-up { animation: fade-up-timepicker var(--tv-motion-fade-speed); -} - -// @keyframes fadein { -// 0% { -// transform: translateY(-200px); -// z-index: -999; -// } - -// 100% { -// transform: translateY(0); -// z-index: 0; -// } -// } - -// @keyframes fadeup { -// 0% { -// transform: translateY(200px); -// z-index: -999; -// } - -// 100% { -// transform: translateY(0); -// z-index: 0; -// } -// } +} \ No newline at end of file diff --git a/packages/theme/src/tree/index.less b/packages/theme/src/tree/index.less index fa2ce9769b..460538bd4c 100644 --- a/packages/theme/src/tree/index.less +++ b/packages/theme/src/tree/index.less @@ -476,28 +476,4 @@ 0.3s padding-top ease-in-out, 0.3s padding-bottom ease-in-out; } -} - -// notice: not used -// @keyframes { -// 100% { -// transform: rotate(360deg); -// } -// } - -// @keyframes loading-dash { -// 0% { -// stroke-dasharray: 1, 200; -// stroke-dashoffset: 0; -// } - -// 50% { -// stroke-dasharray: 90, 150; -// stroke-dashoffset: -40px; -// } - -// 100% { -// stroke-dasharray: 90, 150; -// stroke-dashoffset: -120px; -// } -// } +} \ No newline at end of file From 5dca8896025c6ba8b334f34b3c5864af685517ba Mon Sep 17 00:00:00 2001 From: Lyra <1170158548@qq.com> Date: Tue, 2 Sep 2025 19:52:23 +0800 Subject: [PATCH 6/7] feat(theme): [motion] reset the css variables --- packages/theme/src/base/vars.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/theme/src/base/vars.less b/packages/theme/src/base/vars.less index 541913a714..1e1ec03888 100644 --- a/packages/theme/src/base/vars.less +++ b/packages/theme/src/base/vars.less @@ -576,7 +576,7 @@ --tv-motion-shine-offset-y: -12px; /* Y轴背景位移 */ /* ---------- 滑动方向 (slide.less) ---------- */ - --tv-motion-slide-speed: 1s; /* 动画时长 */ + --tv-motion-slide-speed: 0.3s; /* 动画时长 */ --tv-motion-slide-opacity-mid: 0.6; /* 中间透明度 */ /* X轴偏移 */ --tv-motion-slide-offset-left: -100%; /* 左侧初始位移 */ From 156cb19ff33b4c3f336d6dd926298913bda42131 Mon Sep 17 00:00:00 2001 From: Lyra <1170158548@qq.com> Date: Fri, 12 Sep 2025 20:20:23 +0800 Subject: [PATCH 7/7] feat(theme): [motion] optimized animation effect configuration --- packages/theme/src/base/reset.less | 1 - packages/theme/src/base/vars.less | 6 +++--- packages/theme/src/chart-core/index.less | 1 - packages/theme/src/dialog-box/index.less | 3 --- packages/theme/src/grid/icon.less | 3 ++- packages/theme/src/grid/loading.less | 1 - packages/theme/src/motion/scroll.less | 8 ++++---- 7 files changed, 9 insertions(+), 14 deletions(-) diff --git a/packages/theme/src/base/reset.less b/packages/theme/src/base/reset.less index 0f8fe377eb..e8432706e7 100644 --- a/packages/theme/src/base/reset.less +++ b/packages/theme/src/base/reset.less @@ -16,7 +16,6 @@ // .tiny-icon-loading 类名的动画效果。 它出现在多个组件中,故抽取到一起。 .@{css-prefix-iconfont}-loading { - --tv-motion-rotate-speed: 2s; line-height: 1; animation: rotate-z var(--tv-motion-rotate-speed) linear infinite; } diff --git a/packages/theme/src/base/vars.less b/packages/theme/src/base/vars.less index 1e1ec03888..7d96190f31 100644 --- a/packages/theme/src/base/vars.less +++ b/packages/theme/src/base/vars.less @@ -552,7 +552,7 @@ --tv-motion-skeleton-speed: 1.5s; /* 骨架屏动画时长 */ --tv-motion-skeleton-background-offset: -20%; /* 背景流动偏移 */ /* 网格加载 */ - --tv-motion-grid-loading-speed: 1.5s; /* 网格加载动画时长 */ + --tv-motion-grid-loading-speed: 1.04s; /* 网格加载动画时长 */ --tv-motion-grid-loading-opacity: 0.1; /* 网格加载最终透明度 */ /* ---------- 进度条背景 (progress.less) ---------- */ @@ -560,12 +560,12 @@ --tv-motion-progress-speed: 1s; /* 动画时长 */ /* ---------- 通用旋转 (rotate.less) ---------- */ - --tv-motion-rotate-speed: 1s; /* 旋转动画时长 */ + --tv-motion-rotate-speed: 2s; /* 旋转动画时长 */ --tv-motion-rotate-degrees: 360deg; /* 旋转角度 */ /* ---------- 滚动文字 (scroll.less) ---------- */ --tv-motion-scroll-speed: 3s; /* 动画时长 */ - --tv-motion-scroll-offset-x: 300px; /* X轴初始位移 */ + --tv-motion-scroll-offset-x: 100%; /* X轴初始位移 */ --tv-motion-scroll-offset-x-end: -100%; /* X轴结束位移 */ --tv-motion-scroll-offset-y: 100%; /* Y轴初始位移 */ --tv-motion-scroll-offset-y-end: -100%; /* Y轴结束位移 */ diff --git a/packages/theme/src/chart-core/index.less b/packages/theme/src/chart-core/index.less index 20edc3a08a..915a8786df 100644 --- a/packages/theme/src/chart-core/index.less +++ b/packages/theme/src/chart-core/index.less @@ -50,7 +50,6 @@ background-color: var(--tv-ChartCore-data-empty-bg-color); .circular { - --tv-motion-rotate-speed: 2s; width: 42px; height: 42px; animation: rotate-spin var(--tv-motion-rotate-speed) linear infinite; diff --git a/packages/theme/src/dialog-box/index.less b/packages/theme/src/dialog-box/index.less index b665887c80..3ea53b5a2f 100644 --- a/packages/theme/src/dialog-box/index.less +++ b/packages/theme/src/dialog-box/index.less @@ -210,12 +210,10 @@ } .v-modal-enter { - --tv-motion-fade-speed: 0.2s; animation: fade-in var(--tv-motion-fade-speed) ease; } .v-modal-leave { - --tv-motion-fade-speed: 0.2s; animation: fade-out var(--tv-motion-fade-speed) ease forwards; } @@ -233,7 +231,6 @@ .dialog-fade-leave-active { .@{dialog-box-prefix-cls} { - --tv-motion-fade-speed: 3s; animation: fade-out-up var(--tv-motion-fade-speed); } animation: fade-out-up var(--tv-motion-fade-speed); diff --git a/packages/theme/src/grid/icon.less b/packages/theme/src/grid/icon.less index 9f337a466f..c9c1e0bd50 100644 --- a/packages/theme/src/grid/icon.less +++ b/packages/theme/src/grid/icon.less @@ -287,6 +287,7 @@ } &.roll { + --tv-motion-rotate-speed: 1s; animation: rotate-spin var(--tv-motion-rotate-speed) infinite linear; } } @@ -384,4 +385,4 @@ content: '\2716'; } } -} \ No newline at end of file +} diff --git a/packages/theme/src/grid/loading.less b/packages/theme/src/grid/loading.less index ee822deb52..066501bb38 100644 --- a/packages/theme/src/grid/loading.less +++ b/packages/theme/src/grid/loading.less @@ -51,7 +51,6 @@ background: linear-gradient(to top, transparent, transparent); span { - --tv-motion-grid-loading-speed: 1.04s; display: inline-block; width: 10px; height: 10px; diff --git a/packages/theme/src/motion/scroll.less b/packages/theme/src/motion/scroll.less index 2baa52aad1..f181f57fe6 100644 --- a/packages/theme/src/motion/scroll.less +++ b/packages/theme/src/motion/scroll.less @@ -12,7 +12,7 @@ /* ============ 滚动动画 ============ */ @keyframes scroll-left { 0% { - transform: translateX(var(--tv-motion-scroll-offset-x, 300px)); + transform: translateX(var(--tv-motion-scroll-offset-x, 100%)); } 100% { transform: translateX(var(--tv-motion-scroll-offset-x-end, -100%)); @@ -24,7 +24,7 @@ transform: translateX(var(--tv-motion-scroll-offset-x-end, -100%)); } 100% { - transform: translateX(var(--tv-motion-scroll-offset-x, 300px)); + transform: translateX(var(--tv-motion-scroll-offset-x, 100%)); } } @@ -49,7 +49,7 @@ /* ============ 滚动适应动画 ============ */ @keyframes scroll-left-adapt { 0% { - transform: translateX(100%); + transform: translateX(var(--tv-motion-scroll-offset-x, 100%)); } 50% { transform: translateX(0); @@ -67,7 +67,7 @@ transform: translateX(0); } 100% { - transform: translateX(100%); + transform: translateX(var(--tv-motion-scroll-offset-x, 100%)); } }