diff --git a/examples/sites/demos/pc/app/scroll-text/scroll-direction.spec.ts b/examples/sites/demos/pc/app/scroll-text/scroll-direction.spec.ts index 271ebc0d6b..8e8032ecc3 100644 --- a/examples/sites/demos/pc/app/scroll-text/scroll-direction.spec.ts +++ b/examples/sites/demos/pc/app/scroll-text/scroll-direction.spec.ts @@ -3,8 +3,8 @@ import { test, expect } from '@playwright/test' test('文字滚动方向', async ({ page }) => { page.on('pageerror', (exception) => expect(exception).toBeNull()) await page.goto('scroll-text#scroll-direction') - await expect(page.locator('.tiny-scroll-text__content > div').nth(0)).toHaveCSS('animation-name', 'moveLeft') - await expect(page.locator('.tiny-scroll-text__content > div').nth(1)).toHaveCSS('animation-name', 'moveRight') - await expect(page.locator('.tiny-scroll-text__content > div').nth(2)).toHaveCSS('animation-name', 'moveUp') - await expect(page.locator('.tiny-scroll-text__content > div').nth(3)).toHaveCSS('animation-name', 'moveDown') + await expect(page.locator('.tiny-scroll-text__content > div').nth(0)).toHaveCSS('animation-name', 'scroll-left') + await expect(page.locator('.tiny-scroll-text__content > div').nth(1)).toHaveCSS('animation-name', 'scroll-right') + await expect(page.locator('.tiny-scroll-text__content > div').nth(2)).toHaveCSS('animation-name', 'scroll-up') + await expect(page.locator('.tiny-scroll-text__content > div').nth(3)).toHaveCSS('animation-name', 'scroll-down') }) diff --git a/packages/theme/src/base/index.less b/packages/theme/src/base/index.less index 1a57177515..d89c3c2d05 100644 --- a/packages/theme/src/base/index.less +++ b/packages/theme/src/base/index.less @@ -14,4 +14,5 @@ @import './vars.less'; // @import './old-theme.less'; // @import './aurora-theme.less'; +// @import './motion-theme.less'; @import './transition.less'; diff --git a/packages/theme/src/base/motion-theme.less b/packages/theme/src/base/motion-theme.less new file mode 100644 index 0000000000..de485e9d33 --- /dev/null +++ b/packages/theme/src/base/motion-theme.less @@ -0,0 +1,622 @@ +/* prettier-ignore */ +:root, +:host { + /* 1.1品牌色 */ + + /* 品牌主色 */ + --tv-base-color-brand: #191919; // 主色黑/链接颜色 + + --tv-base-color-brand-1: #f0f7ff; + --tv-base-color-brand-2: #deecff; // 日期选择悬浮背景色 /提示-背景色 + --tv-base-color-brand-3: #b3d6ff; // 浅背景-悬浮色,开关组件“开”禁用背景色 + --tv-base-color-brand-4: #7eb7fc; + --tv-base-color-brand-5: #4191fa; + --tv-base-color-brand-6: #1476ff; // 辅助色, 文字按钮色、文字按钮悬浮色 /单选框选中悬浮/聚焦/激活小圆点填充色和边框色 + --tv-base-color-brand-7: #0f5ed4; + --tv-base-color-brand-8: #0845a6; + --tv-base-color-brand-9: #022e7a; + --tv-base-color-brand-10: #001a4a; + --tv-base-color-brand-11: #3d6899; + --tv-base-color-brand-12: #7fa6d4; + --tv-base-color-brand-13: #b6d4f2; + + /* 1.2 中立色 */ + + /* 公用灰色系,用于文本、图标、线条、背景色 */ + --tv-base-color-common-1: #ffffff; // 顶部导航背景色、 顶部导航下拉背景色/次要按钮-背景色、次要按钮-hover/Focus/active背景色、输入框背景色 + --tv-base-color-common-2: #fafafa; // 新区域组件-悬浮背景色 + --tv-base-color-common-3: #f5f5f5; // 通用背景-页面背景色/ 选块默认色/滑块背景色/分页悬浮色、下拉、列表、悬浮背景、表头背景、下拉菜单、选块选中色 + --tv-base-color-common-4: #f0f0f0; // 白色背景分割线 /禁用背景/小表格中禁用背景/支付列表中禁用背景、顶部导航下拉悬浮背景色 + --tv-base-color-common-5: #e6e6e6; // 灰色标签背景色/轮播箭头悬浮色 + --tv-base-color-common-6: #dbdbdb; // 开关组件“关”禁用背景色/ 禁用描边/ 灰色背景分割线 + --tv-base-color-common-7: #c2c2c2; // 选块悬浮色/页签禁用文字色/边框色(如下拉、输入框)/文字禁用/禁用图标 + --tv-base-color-common-8: #808080; // 弱化信息、说明文字 + --tv-base-color-common-9: #595959; // 次要信息/图标默认/主色悬浮色、链接悬浮色/主要按钮-hover/Focus背景色 + --tv-base-color-common-10: #333333; + --tv-base-color-common-11: #191919; // 正文主色,重要信息、标题颜色、输入类文本颜色、导航栏文字图标/主要按钮-背景色 + --tv-base-color-common-12: #000000; + + /* 1.4 功能色 */ + --tv-base-color-success-1: #edf7df; + --tv-base-color-success-2: #daf2bb; + --tv-base-color-success-3: #b9e683; // 成功-按钮active、hover 颜色 + --tv-base-color-success-4: #9edb58; + --tv-base-color-success-5: #7dcc29; + --tv-base-color-success-6: #5cb300; // 成功-背景色/ 图标色/文本色 /进度条当前进度背景色 + --tv-base-color-success-7: #4b9902; + --tv-base-color-success-8: #3c8001; + --tv-base-color-success-9: #2e6600; + --tv-base-color-success-10: #1f4700; + --tv-base-color-success-11: #628c38; + --tv-base-color-success-12: #a2c777; + --tv-base-color-success-13: #d2e6b8; + --tv-base-color-success-14: #e6f2d5; // 成功-背景色/边框色 (这个不在规范色阶中) + + --tv-base-color-error-1: #fff1f0; // + --tv-base-color-error-2: #fce2e0; // 错误-边框色 /背景色 /错误校验背景色,设计稿用了这个#FCE3E1,但不在色阶中 + --tv-base-color-error-3: #faa7a3; // 错误-图标色、校验边框色/、悬浮菜单背景色 + --tv-base-color-error-4: #fa8682; // + --tv-base-color-error-5: #f76360; + --tv-base-color-error-6: #f23030; // 错误-文本色/交易金额色 / 紧急告警色 + --tv-base-color-error-7: #bf0a1c; + --tv-base-color-error-8: #a3171c; + --tv-base-color-error-9: #78080e; + --tv-base-color-error-10: #4d0005; + --tv-base-color-error-11: #a64242; + --tv-base-color-error-12: #f2c5c2; + --tv-base-color-error-13: #fce3e1; // 错误-背景色/错误校验背景色 (这个不在规范色阶中) + + --tv-base-color-warn-1: #fff4e8; + --tv-base-color-warn-2: #ffebd1; // 告警-背景色/边框色(浅) + --tv-base-color-warn-3: #fcd5a4; + --tv-base-color-warn-4: #fcbc72; + --tv-base-color-warn-5: #ff9a2e; + --tv-base-color-warn-6: #ff8800; // 告警-图标色/深色背景 /重要告警色 + --tv-base-color-warn-7: #d96900; // 优惠折扣功能色 ti-color-discount + --tv-base-color-warn-8: #a64d00; + --tv-base-color-warn-9: #733400; + --tv-base-color-warn-10: #4d2201; + --tv-base-color-warn-11: #9e6d3f; + --tv-base-color-warn-12: #d6a981; + --tv-base-color-warn-13: #f2d8c2; + --tv-base-color-warn-secondary-1: #ffb700; // 次要告警色 黄色系 + + --tv-base-color-info-1: #f0f7ff; + --tv-base-color-info-2: #deecff; // 提示-背景色 / 边框色 + --tv-base-color-info-3: #b3d6ff; // 开关组件“开”禁用背景色 + --tv-base-color-info-4: #7eb7fc; + --tv-base-color-info-5: #4191fa; + --tv-base-color-info-6: #1476ff; // 提示-图标色 / 文本色 + --tv-base-color-info-7: #0f5ed4; + --tv-base-color-info-8: #0845a6; + --tv-base-color-info-9: #022e7a; + --tv-base-color-info-10: #001a4a; + --tv-base-color-info-11: #3d6899; + --tv-base-color-info-12: #7fa6d4; + --tv-base-color-info-13: #b6d4f2; + + /** 2. 公共色 **/ + + /** 2.2 提示类型组件 ----Alert组件、Modal(message)组件、Tag 标签组件、Notify 通知、Tooltip、Badge、-错误校验等场景 **/ + --tv-color-success-text: var(--tv-base-color-success-6); // #5cb300 成功-文本色 tag的light、plain类型 + --tv-color-success-text-primary: var(--tv-base-color-common-11); // #191919 常规一级文本色(非主题色) + --tv-color-success-bg: var(--tv-base-color-success-6); //#5cb300 成功-背景色(深) tag的dark类型/tooltip/badge + --tv-color-success-bg-light: var(--tv-base-color-success-14); // #e6f2d5 成功-背景色(浅) alert/tag的light类型 + --tv-color-success-bg-1: var(--tv-base-color-success-14); // #e6f2d5 tag的light类型 + --tv-color-success-border: var(--tv-base-color-success-6); // #5cb300 成功-边框色(深) tooltip/badge/tag的dark、plain类型 + --tv-color-success-border-light: var(--tv-base-color-success-14); // #e6f2d5 成功-边框色(浅) alert/tag的light类型 + --tv-color-success-border-1: var(--tv-base-color-success-14); // #e6f2d5 tag的light类型 + --tv-color-success-icon: var(--tv-base-color-success-6); // #5cb300 成功-图标色 + + --tv-color-error-text: var(--tv-base-color-error-6); // #f23030 #f23030 错误-文本色/交易金额色/错误校验/tag的light、plain类型 + --tv-color-error-text-primary: var(--tv-base-color-common-11); // #191919 常规一级文本色(非主题色) + --tv-color-error-bg: var(--tv-base-color-error-6); // #f23030 #f23030 错误-背景色(深) tag的dark类型/tooltip/badge + --tv-color-error-bg-1: var(--tv-base-color-error-13); // #fce3e1 tag的light类型 + --tv-color-error-bg-light: var(--tv-base-color-error-13); // #fce3e1 错误-背景色(浅):错误校验背景色/alert/tag的light类型 + --tv-color-error-border: var(--tv-base-color-error-6); // #f23030 #f23030 错误-边框色(深) tooltip/badge/tag的dark、plain类型/错误校验边框色 + --tv-color-error-border-light: var(--tv-base-color-error-13); // #fce3e1 错误-边框色(浅) alert/tag的light类型 + --tv-color-error-border-1: var(--tv-base-color-error-13); // #fce3e1 tag的light类型 + --tv-color-error-icon: var(--tv-base-color-error-6); // #f23030 #f23030 错误-图标色 + + --tv-color-warn-text: var(--tv-base-color-warn-6); // #ff8800 告警-文本色 tag的light、plain类型 + --tv-color-warn-text-primary: var(--tv-base-color-common-11); // #191919 常规一级文本色(非主题色) + --tv-color-warn-bg: var(--tv-base-color-warn-6); // #ff8800 告警-背景色(深) tag的dark类型/tooltip/badge + --tv-color-warn-bg-light: var(--tv-base-color-warn-2); // #ffebd1 告警-背景色(浅) alert/tag的light类型 + --tv-color-warn-bg-1: var(--tv-base-color-warn-2); // #ffebd1 tag的light类型 + --tv-color-warn-border: var(--tv-base-color-warn-6); // #ff8800 告警-边框色(深) tooltip/badge/tag的dark、plain类型 + --tv-color-warn-border-light: var(--tv-base-color-warn-2); // #ffebd1 告警-边框色(浅) alert/tag的light类型 + --tv-color-warn-border-1: var(--tv-base-color-warn-2); // #ffebd1 tag的light类型 + --tv-color-warn-icon: var(--tv-base-color-warn-6); // #ff8800 告警-图标色 + + --tv-color-info-text: var(--tv-base-color-info-6); // #1476ff 信息-文本色 tag的light、plain类型 + --tv-color-info-text-primary: var(--tv-base-color-common-11); // #191919 常规一级文本色(非主题色) tag的dark类型/tooltip/badge + --tv-color-info-text-1: var(--tv-base-color-info-6); // #1476ff + --tv-color-info-bg: var(--tv-base-color-info-6); // #1476ff 信息-背景色(深) alert/tag的light类型 + --tv-color-info-bg-1: var(--tv-base-color-info-2); // #deecff + --tv-color-info-bg-light: var(--tv-base-color-info-2); // #deecff 信息-背景色(浅) alert/tag的light类型 + --tv-color-info-border: var(--tv-base-color-info-6); // #1476ff 信息-边框色(深) tooltip/badge/tag的dark、plain类型 + --tv-color-info-border-light: var(--tv-base-color-info-2); // #deecff 信息-边框色(浅) alert/tag的light类型 + --tv-color-info-border-1: var(--tv-base-color-info-2); // #deecff tag的light类型 + --tv-color-info-icon: var(--tv-base-color-info-6); // #1476ff 信息-图标色 + + /** 2.3 交互类型颜色---- Button组件、Link 文字链接 **/ + + /* 主要-primary */ + --tv-color-act-primary-text: var(--tv-base-color-brand); // #191919 主要文本色-1(品牌色): 朴素/幽灵/纯文本/链接 + --tv-color-act-primary-text-hover: var(--tv-base-color-brand); // #191919 主要hover文本色-1 朴素/幽灵/纯文本/链接 + --tv-color-act-primary-text-active: var(--tv-base-color-brand); // #191919 主要active文本色-1 朴素/幽灵/纯文本/链接 + + --tv-color-act-primary-text-inverse-tint: var(--tv-base-color-common-1); // #fff 主要文本色-2(白色) 基本按钮 + --tv-color-act-primary-text-inverse-tint-hover: var(--tv-base-color-common-1); // #fff 主要hover文本色-2(白色) 基本按钮 + --tv-color-act-primary-text-inverse-tint-active: var(--tv-base-color-common-1); // #fff 主要active文本色-2(白色) 基本按钮 + + --tv-color-act-primary-plain-text-hover: var(--tv-base-color-brand); // #191919 朴素悬浮文本色 + + --tv-color-act-primary-bg: var(--tv-base-color-brand); // #191919 主要背景色-1(品牌色): 基本按钮 + --tv-color-act-primary-bg-hover: var(--tv-base-color-common-9); // #595959 主要hover背景色-1 基本按钮 + --tv-color-act-primary-bg-active: var(--tv-base-color-common-9); // #595959 主要active背景色-1 基本按钮 + + --tv-color-act-primary-bg-white: var(--tv-base-color-common-1); // #fff 主要背景色-2(白):朴素 + --tv-color-act-primary-bg-white-hover: var(--tv-base-color-common-1); // #fff 主要hover背景色-2(白色): 朴素 + --tv-color-act-primary-bg-white-active: var(--tv-base-color-common-1); // 主要active背景色-2(白色): 朴素 + + --tv-color-act-primary-border: var(--tv-base-color-brand); // #191919 主要边框色-1 基本按钮 + --tv-color-act-primary-border-hover: var(--tv-base-color-common-9); // #595959 主要hover边框色-1 基本按钮 + --tv-color-act-primary-border-active: var(--tv-base-color-common-9); // #595959 主要active边框色-1 基本按钮 + + --tv-color-act-primary-border-light: var(--tv-base-color-common-9); // #595959 边框色-2 幽灵/朴素 + --tv-color-act-primary-border-light-hover: var(--tv-base-color-common-1); // #fff 边框色-2.1 朴素hover + --tv-color-act-primary-border-light-active: var(--tv-base-color-common-1); // #fff 边框色-2.1 朴素active + --tv-color-act-primary-border-light-hover-1: var(--tv-base-color-common-7); // #c2c2c2 边框色-2.2 幽灵hover + --tv-color-act-primary-border-light-active-1: var(--tv-base-color-common-7); // #c2c2c2 边框色-2.2 幽灵active + + + + /* 成功-success */ + --tv-color-act-success-text: var(--tv-base-color-success-6); // #5cb300 成功文本色-1(成功主色): 朴素/幽灵/纯文本/链接 + --tv-color-act-success-text-hover: var(--tv-base-color-success-6); // #5cb300 成功hover文本色-1 朴素/幽灵/纯文本/链接 + --tv-color-act-success-text-active: var(--tv-base-color-success-6); // #5cb300 成功active文本色-1 朴素/幽灵/纯文本/链接 + + --tv-color-act-success-text-white: var(--tv-base-color-common-1); // #fff 成功文本色-2(白色):基本按钮 + --tv-color-act-success-text-white-hover: var(--tv-base-color-common-1); // #fff 成功hover文本色-2(白色) 基本按钮 + --tv-color-act-success-text-white-active: var(--tv-base-color-common-1); // #fff 成功active文本色-2(白色) 基本按钮 + + --tv-color-act-success-plain-text-hover: var(--tv-base-color-success-6); // #5cb300 朴素悬浮文本色 + + --tv-color-act-success-bg: var(--tv-base-color-success-6); // #5cb300 成功背景色-1(品牌色):基本按钮 + --tv-color-act-success-bg-hover: var(--tv-base-color-success-5); // #7dcc29 成功hover背景色-1 基本按钮 + --tv-color-act-success-bg-active: var(--tv-base-color-success-5); // #7dcc29 成功active背景色-1 基本按钮 + + --tv-color-act-success-bg-light: var(--tv-base-color-success-1); // #edf7df 成功背景色-1(品牌色):朴素 + --tv-color-act-success-bg-light-hover: var(--tv-base-color-success-1); // #edf7df 成功hover背景色-1 朴素 + --tv-color-act-success-bg-light-active: var(--tv-base-color-success-1); // #edf7df 成功active背景色-1 朴素 + + --tv-color-act-success-border: var(--tv-base-color-success-6); // #5cb300 成功边框色-1:基本按钮/幽灵按钮 + --tv-color-act-success-border-hover: var(--tv-base-color-success-5); // #7dcc29 成功hover边框色-1.1 基本按钮 + --tv-color-act-success-border-active: var(--tv-base-color-success-5); // #7dcc29 成功active边框色-1.1 基本按钮 + --tv-color-act-success-border-hover-1: var(--tv-base-color-success-2); // #daf2bb 成功hover边框色-1.2 幽灵按钮 + --tv-color-act-success-border-active-1: var(--tv-base-color-success-2); // #daf2bb 成功active边框色-1.2 幽灵按钮 + + --tv-color-act-success-border-light: var(--tv-base-color-success-2); // #daf2bb 成功边框色-2:朴素按钮 + --tv-color-act-success-border-light-hover: var(--tv-base-color-success-1); // #edf7df 成功hover边框色 朴素按钮 + --tv-color-act-success-border-light-active: var(--tv-base-color-success-1); // #edf7df 成功active边框色 朴素按钮 + + + + /* 告警-warning */ + --tv-color-act-warning-text: var(--tv-base-color-warn-6); // #ff8800 告警文本色-1(告警主色):朴素/幽灵/纯文本/链接 + --tv-color-act-warning-text-hover: var(--tv-base-color-warn-6); // #ff8800 告警hover文本色-1 朴素/幽灵/纯文本/链接 + --tv-color-act-warning-text-active: var(--tv-base-color-warn-6); // #ff8800 告警active文本色-1 朴素/幽灵/纯文本/链接 + + --tv-color-act-warning-text-white: var(--tv-base-color-common-1); // #fff 告警文本色-2(白色):基本按钮 + --tv-color-act-warning-text-white-hover: var(--tv-base-color-common-1); // #fff 告警hover文本色-2(白色) 基本按钮 + --tv-color-act-warning-text-white-active: var(--tv-base-color-common-1); // #fff 告警active文本色-2(白色) 基本按钮 + + --tv-color-act-warning-plain-text-hover: var(--tv-base-color-warn-6); // #ff8800 朴素悬浮文本色 + + --tv-color-act-warning-bg: var(--tv-base-color-warn-6); // #ff8800 告警背景色-1(告警主色):基本按钮 + --tv-color-act-warning-bg-hover: var(--tv-base-color-warn-5); //#ff9a2e 告警hover背景色-1 基本按钮 + --tv-color-act-warning-bg-active: var(--tv-base-color-warn-5); //#ff9a2e 告警active背景色-1 基本按钮 + + --tv-color-act-warning-bg-light: var(--tv-base-color-warn-1); // #fff4e8 告警背景色-1(告警主色衍生色):朴素按钮 + --tv-color-act-warning-bg-light-hover: var(--tv-base-color-warn-1); // #fff4e8 告警hover背景色-1 朴素按钮 + --tv-color-act-warning-bg-light-active: var(--tv-base-color-warn-1); // #fff4e8 告警active背景色-1 朴素按钮 + + --tv-color-act-warning-border: var(--tv-base-color-warn-6); // #ff8800 告警边框色-1:基本按钮/幽灵按钮 + --tv-color-act-warning-border-hover: var(--tv-base-color-warn-5); //#ff9a2e 告警hover边框色-1.1 基本按钮 + --tv-color-act-warning-border-active: var(--tv-base-color-warn-5); //#ff9a2e 告警active边框色-1.1 基本按钮 + --tv-color-act-warning-border-hover-1: var(--tv-base-color-warn-2); //#ffebd1 告警幽灵hover边框色-1.2 幽灵按钮 + --tv-color-act-warning-border-active-1: var(--tv-base-color-warn-2); //#ffebd1 告警幽灵active边框色-1.2 幽灵按钮 + + --tv-color-act-warning-border-light: var(--tv-base-color-warn-2); //#ffebd1 告警边框色-2:朴素按钮 + --tv-color-act-warning-border-light-hover: var(--tv-base-color-warn-1); // #fff4e8 告警hover边框色 朴素按钮 + --tv-color-act-warning-border-light-active: var(--tv-base-color-warn-1); // #fff4e8 告警active边框色 朴素按钮 + + + + /* 危险-danger */ + --tv-color-act-danger-text: var(--tv-base-color-error-6); // #f23030 危险文本色-1(成功主色):朴素/幽灵/纯文本/链接 + --tv-color-act-danger-text-hover: var(--tv-base-color-error-6); // #f23030 #f23030 危险hover文本色-1 朴素/幽灵/纯文本/链接 + --tv-color-act-danger-text-active: var(--tv-base-color-error-6); // #f23030 #f23030 危险active文本色-1 朴素/幽灵/纯文本/链接 + + --tv-color-act-danger-text-white: var(--tv-base-color-common-1); // #fff 危险文本色-2(白色):基本按钮 + --tv-color-act-danger-text-white-hover: var(--tv-base-color-common-1); // #fff 危险hover文本色-2(白色) 基本按钮 + --tv-color-act-danger-text-white-active: var(--tv-base-color-common-1); // #fff 危险active文本色-2(白色) 基本按钮 + + --tv-color-act-danger-plain-text-hover: var(--tv-base-color-error-6); // #f23030 朴素按钮 + + --tv-color-act-danger-bg: var(--tv-base-color-error-6); // #f23030 #f23030 危险背景色-1(成功主色):基本按钮 + --tv-color-act-danger-bg-hover: var(--tv-base-color-error-5); // #f76360 危险hover背景色-1 基本按钮 + --tv-color-act-danger-bg-active: var(--tv-base-color-error-5); // #f76360 危险active背景色-1 基本按钮 + + --tv-color-act-danger-bg-light: var(--tv-base-color-error-1); // #fff1f0 危险背景色-2(成功主色衍生色):朴素按钮 + --tv-color-act-danger-bg-light-hover: var(--tv-base-color-error-1); // #fff1f0 危险hover背景色-1 朴素按钮 + --tv-color-act-danger-bg-light-active: var(--tv-base-color-error-1); // #fff1f0 危险active背景色-1 朴素按钮 + + --tv-color-act-danger-border: var(--tv-base-color-error-6); // #f23030 #f23030 危险边框色-1:基本按钮/幽灵按钮 + --tv-color-act-danger-border-hover: var(--tv-base-color-error-5); // #f76360 危险hover边框色-1.1 基本按钮 + --tv-color-act-danger-border-active: var(--tv-base-color-error-5); // #f76360 危险active边框色-1.1 基本按钮 + --tv-color-act-danger-border-hover-1: var(--tv-base-color-error-2); // #fce2e0 危险hover边框色-1.2 幽灵按钮 + --tv-color-act-danger-border-active-1: var(--tv-base-color-error-2); // #fce2e0 危险active边框色-1.2 幽灵按钮 + + --tv-color-act-danger-border-light: var(--tv-base-color-error-2); // #fce2e0 危险边框色-2: 朴素按钮 + --tv-color-act-danger-border-light-hover: var(--tv-base-color-error-1); // #fff1f0 危险hover边框色 朴素按钮 + --tv-color-act-danger-border-light-active: var(--tv-base-color-error-1); // #fff1f0 危险active边框色 朴素按钮 + + + + /* 信息-info */ + --tv-color-act-info-text: var(--tv-base-color-info-6); // #1476ff 信息文本色-1(信息主色):朴素/幽灵/纯文本/链接 + --tv-color-act-info-text-hover: var(--tv-base-color-info-6); // #1476ff 信息hover文本色-1 朴素/幽灵/纯文本/链接 + --tv-color-act-info-text-active: var(--tv-base-color-info-6); // #1476ff 信息active文本色-1 朴素/幽灵/纯文本/链接 + + --tv-color-act-info-text-white: var(--tv-base-color-common-1); // #fff 信息文本色-2(白色):基本按钮 + --tv-color-act-info-text-white-hover: var(--tv-base-color-common-1); // #fff 信息hover文本色-2(白色) 基本按钮 + --tv-color-act-info-text-white-active: var(--tv-base-color-common-1); // #fff 信息active文本色-2(白色) 基本按钮 + + --tv-color-act-info-plain-text-hover: var(--tv-base-color-info-6); // #1476ff 朴素按钮 + + --tv-color-act-info-bg: var(--tv-base-color-info-6); // #1476ff 信息背景色-1(信息主色):基本按钮 + --tv-color-act-info-bg-hover: var(--tv-base-color-info-5); // #4191fa 信息hover背景色-1 基本按钮 + --tv-color-act-info-bg-active: var(--tv-base-color-info-5); // #4191fa 信息active背景色-1 基本按钮 + + --tv-color-act-info-bg-light: var(--tv-base-color-info-1); // #f0f7ff 信息背景色-1(信息主色衍生色):朴素按钮 + --tv-color-act-info-bg-light-hover: var(--tv-base-color-info-1); // #f0f7ff 信息hover背景色-1 朴素按钮 + --tv-color-act-info-bg-light-active: var(--tv-base-color-info-1); // #f0f7ff 信息active背景色-1 朴素按钮 + + --tv-color-act-info-border: var(--tv-base-color-info-6); // #1476ff 信息边框色-1:基本按钮/幽灵按钮 + --tv-color-act-info-border-hover: var(--tv-base-color-info-5); // #4191fa 信息hover边框色-1.1 基本按钮 + --tv-color-act-info-border-active: var(--tv-base-color-info-5); // #4191fa 信息active边框色-1.1 基本按钮 + --tv-color-act-info-border-hover-1: var(--tv-base-color-info-2); // #deecff 信息hover边框色-1.2:幽灵按钮 + --tv-color-act-info-border-active-1: var(--tv-base-color-info-2); // #deecff 信息active边框色-1.2 幽灵按钮 + + --tv-color-act-info-border-light: var(--tv-base-color-info-2); // #deecff 信息边框色-2:朴素按钮 + --tv-color-act-info-border-light-hover: var(--tv-base-color-info-1); // #f0f7ff 信息hover边框色 朴素按钮 + --tv-color-act-info-border-light-active: var(--tv-base-color-info-1); // #f0f7ff 信息active边框色 朴素按钮 + + + + /** 2.4 文本色 **/ + --tv-color-text: var(--tv-base-color-common-11); // #191919 一级文本色-正文主色:重要信息/标题颜色/输入类文本颜色/导航栏文字图标/顶部导航/一级tab/tip场景文本色 + --tv-color-text-secondary: var(--tv-base-color-common-9); // #595959 二级文本色-次要信息:卡片式tab页签文本色(深色tab) + --tv-color-text-weaken: var(--tv-base-color-common-8); // #808080 三级文本色-弱化信息、说明文字 + --tv-color-text-placeholder: var(--tv-base-color-common-8); // #808080 占位文本色 + --tv-color-text-disabled: var(--tv-base-color-common-7); // #c2c2c2 禁用文本色 + --tv-color-text-active: var(--tv-base-color-brand-6); // #1476ff 选中文本色 / 文本高亮色(搜索关键字高亮) + --tv-color-text-important: var(--tv-base-color-common-11); // #191919 重要文本色-文本_金额 + --tv-color-text-link: var(--tv-base-color-brand-6); // #1476ff 链接色(链接按钮) + --tv-color-text-link-hover: var(--tv-base-color-brand-6); // #1476ff 链接悬浮色 + --tv-color-plain-text-hover: var(--tv-base-color-common-11); // #191919 朴素次要按钮文本悬浮色 + // -- 暗色新增 -- + --tv-color-text-control: var(--tv-base-color-common-11); // #191919 左侧导航默认文本色/主要图标按钮/主要图标+按钮 + --tv-color-text-inverse: var(--tv-base-color-common-1); // #fff 亮色暗色都是白色场景 + --tv-color-text-inverse-tint: var(--tv-base-color-common-1); // #fff 暗色反色成黑色:主要按钮文本色 + --tv-color-text-inverse-black: var(--tv-base-color-common-11); // #191919 tooltip的light文字 + --tv-color-text-active-1: var(--tv-base-color-common-11); // #191919 卡片式tab页签激活文本色 + --tv-color-text-active-2: var(--tv-base-color-info-6); // #1476ff tree选中文本色 + --tv-color-text-active-3: var(--tv-base-color-common-11); // #191919 tab页签激活色 + --tv-color-text-inverse-active: var(--tv-base-color-common-1); // #fff buttonGrounp激活色 + --tv-color-text-hover: var(--tv-base-color-common-11); // #191919 片式tab页签悬浮文本色/深色背景卡片式链接悬浮色 + --tv-color-text-link-1: var(--tv-base-color-common-11); // #191919 面包屑/主要链接 + --tv-color-text-link-1-hover: var(--tv-base-color-common-11); // #191919 面包屑/主要链接悬浮色 + + /** 2.5 图标色 **/ + --tv-color-icon: var(--tv-base-color-common-8); // #808080 默认图标色 + --tv-color-icon-hover: var(--tv-base-color-common-11); // #191919 图标悬浮色 + --tv-color-icon-active: var(--tv-base-color-common-11); // #191919 图标激活色 级联/下拉多级选中图标色 + --tv-color-icon-disabled: var(--tv-base-color-common-7); // #c2c2c2 图标禁用色 + --tv-color-icon-checked-disabled: var(--tv-base-color-common-6); // #dbdbdb 图标禁用色-1 checkbox选中且禁用 + --tv-color-icon-control: var(--tv-base-color-brand); // #191919 图标按钮 / 图标+文本按钮图标色,主要在按钮场景(稳定态图标色, hover时不用变化) + --tv-color-icon-control-active: var(--tv-base-color-brand-6); // #1476ff 控件图标激活色,主要在checkbox、radio图标激活场景 + --tv-color-icon-control-disabled: var(--tv-base-color-common-6); // #dbdbdb 控件图标禁用色,主要在checkbox、radio图标激活场景 + --tv-color-icon-link: var(--tv-base-color-brand-6); // #1476ff 链接图标色 + --tv-color-icon-warn-secondary: var(--tv-base-color-warn-secondary-1); // #ffb700 次要警告图标色 / 评分组件rate-图标色/状态图标-异常 + // -- 暗色新增 -- + --tv-color-icon-inverse: var(--tv-base-color-common-1); // #fff 亮色暗色都是白色场景 + --tv-color-icon-inverse-tint: var(--tv-base-color-common-1); // #fff 暗色反色成黑色:按钮下拉线头 + // -- 空状态图标 -- + --tv-color-no-data-gary-1: var(--tv-base-color-common-4); // #f0f0f0 + --tv-color-no-data-gary-2: var(--tv-base-color-common-1); // #ffffff + --tv-color-no-data-border: var(--tv-base-color-common-8); // #808080 + --tv-color-no-data-brand: var(--tv-base-color-brand-6); // #317af7 + + /** 2.6 背景色 **/ + + /* 2.6.1 常态 */ + --tv-color-bg: var(--tv-base-color-common-3); // #f5f5f5 通用背景色 /选块的默认背景颜色/下拉搜索的背景、折叠面板背景色/滑块背景色 + --tv-color-bg-primary: var(--tv-base-color-brand); // #191919 主要背景色(品牌色):slider/step/流程图 + --tv-color-bg-secondary: var(--tv-base-color-common-1); // #fff 次要背景色(白色):// 输入框背景/默认按钮背景/折叠面板头部背景色/下拉面板背景色/穿梭框头部背景 + --tv-color-bg-control: var(--tv-base-color-common-7); // #c2c2c2 单选/复选/开关/滑块默认背景色 + --tv-color-bg-control-unactive: var(--tv-base-color-common-7); // #c2c2c2 开关组件-关闭状态-背景色 + --tv-color-bg-gray-1: var(--tv-base-color-common-2); // #fafafa 灰色背景-1:灰色卡片背景色 + --tv-color-bg-gray-2: var(--tv-base-color-common-5); // #e6e6e6 灰色背景-2:灰色标签背景色/进度条灰色背景 + --tv-color-bg-header: var(--tv-base-color-common-3); // #f5f5f5 表头背景色 + --tv-color-bg-mask: rgba(0, 0, 0, 20%); // 全局加载蒙层/抽屉弹窗蒙层 + --tv-color-bg-mask-block:rgba(255, 255, 255, 70%); // 模块内容加载蒙层 + --tv-color-bg-dark: var(--tv-base-color-brand); // #191919; 深色背景色 顶部导航/ 深色tab + + + /* 2.6.2 禁用 */ + --tv-color-bg-disabled: var(--tv-base-color-common-4); // #f0f0f0 禁用背景色 + --tv-color-bg-disabled-control-checked: var(--tv-base-color-common-6); // #dbdbdb 控件选中状态下的禁用背景色:选块已选禁用 + --tv-color-bg-disabled-control-unactive: var(--tv-base-color-common-6); // #dbdbdb 深色背景禁用色:开关组件“关”禁用背景色 + --tv-color-bg-disabled-control-active: var(--tv-base-color-brand-3); // #b3d6ff 深色背景禁用色,单、复选框禁用背景色/开关组件“开”禁用背景色 + + /* 2.6.3 悬浮 */ + --tv-color-bg-hover: var(--tv-base-color-common-3); // #f5f5f5 浅背景-悬浮色 一级tab页签背景-悬浮色 /分页hover背景颜色/表格悬浮/下拉悬浮/左侧导航悬浮 + --tv-color-bg-hover-primary: var(--tv-base-color-common-9); // #595959 主色背景悬浮:step悬浮 + --tv-color-bg-hover-secondary: var(--tv-base-color-common-1); // #fff 次要背景色悬浮色:次要按钮 + --tv-color-bg-hover-1: var(--tv-base-color-brand-2); // #deecff 选块悬浮态背景色 + --tv-color-bg-hover-2: var(--tv-base-color-common-5); // #e6e6e6 轮播箭头背景悬浮色 + --tv-color-bg-hover-dark: var(--tv-base-color-common-11); // #191919 深色背景悬浮色 + + /* 2.6.4 active/选中 */ + --tv-color-bg-active: var(--tv-base-color-common-3); // #f5f5f5 分页选中背景色/左侧导航选中背景色 + --tv-color-bg-active-control: var(--tv-base-color-brand-6); // #1476ff 主色蓝,单选/复选选中背景色、开关“开”的背景色、选块点击背景色、滑块选中背景色、价格曲线、区域选择选中的背景色 + --tv-color-bg-active-primary: var(--tv-base-color-brand); // #191919 品牌色,锚点-当前位置的圆点背景色/leftmenuthin左侧导航收起图标选中的背景色、NPS评分选中背景色 + --tv-color-bg-active-secondary: var(--tv-base-color-common-1); // #fff 次要背景色active色/下拉选中的背景色/一级tab页签背景-选中色/树控件选中背景颜色 + --tv-color-bg-active-emphasize: var(--tv-base-color-brand-2); // #deecff 时间选择选中背景色 + --tv-color-bg-active-emphasize-light: var(--tv-base-color-brand-1); // #f0f7ff 表格选中背景色 + --tv-color-bg-active-dark: var(--tv-base-color-common-3); // #f5f5f5 深色背景悬浮色 + + // -- 暗色新增 -- + --tv-color-bg-2: var(--tv-base-color-common-1); // #fff下拉面板/tip的normal背景色 + --tv-color-bg-3: var(--tv-base-color-common-1); // #fff 顶部导航背景色/顶部导航下拉背景色/折叠面板背景色/modal,dialogbox背景色/容器二级背景色:左侧导航/折叠面板/表格下展背景 + --tv-color-bg-4: var(--tv-base-color-common-7); // #c2c2c2 时间线实心圆点 + --tv-color-bg-progressbar: var(--tv-base-color-success-6); // #5cb300 step当前进度背景色 (考虑去掉,成功主色替代) + --tv-color-bg-active-emphasize-1: var(--tv-base-color-common-1); // #fff 下拉选中背景色、tab二级选中背景色 + --tv-color-bg-container-hover: var(--tv-base-color-common-1); // #fff 卡片选中悬浮背景色(区块背景) + --tv-color-bg-hover-3: var(--tv-base-color-brand-2); // #deecff 日期悬浮 + --tv-color-bg-hover-4: var(--tv-base-color-common-1); // #ffffff 表格悬浮/下拉悬浮/左侧导航悬浮 + --tv-color-bg-active-primary-1: var(--tv-base-color-common-9); // #595959 主要按钮悬浮 + --tv-color-bg-inverse: var(--tv-base-color-common-1); // #fff 不发生反色的背景色:switch/slider按钮控件背景色 + --tv-color-bg-active-control-1: var(--tv-base-color-common-6); // #dbdbdb radio 选中禁用色 + --tv-color-bg-5: var(--tv-base-color-common-5); // #e6e6e6 轮播指示器背景色 + --tv-color-bg-5-active: var(--tv-base-color-common-9); // #595959 轮播指示器激活背景色 + --tv-color-bg-inverse-tint-1: var(--tv-base-color-common-1); // #fff 图片工具栏背景色 + --tv-color-bg-disabled-control: var(--tv-base-color-common-7); // #c2c2c2 滑块高亮部分禁用色 + --tv-color-bg-inverse-disabled: var(--tv-base-color-common-1); // #fff 复选框禁用/开个按钮禁用/滑块按钮禁用(此3类场景图标白色部分反色成#999) + --tv-color-bg-dark-1: var(--tv-base-color-common-11); // #191919 tip的dark背景色 + + /** 2.7 边框色/分割线颜色 **/ + + /* 2.7.1 边框 */ + --tv-color-border: var(--tv-base-color-common-7); // #c2c2c2 线条-正常色 + --tv-color-border-hover: var(--tv-base-color-brand); // #191919 线条悬浮色 + --tv-color-border-active: var(--tv-base-color-brand); // #191919 线条active色 + --tv-color-border-active-control: var(--tv-base-color-brand-6); // #1476ff 主色蓝,单选/复选选中的边框色 + --tv-color-border-disabled: var(--tv-base-color-common-6); // #dbdbdb 线条禁用色 + --tv-color-border-secondary: var(--tv-base-color-common-9); // #595959 线条-次要色:次要按钮边框默认色 + --tv-color-border-ghost: var(--tv-base-color-common-8); // #808080 + --tv-color-border-ghost-active: var(--tv-base-color-common-6); // #dbdbdb + + /* 2.7.2 分割线 */ + --tv-color-border-divider: var(--tv-base-color-common-4); // #f0f0f0 分割线1(较长分割线场景) + --tv-color-border-divider-short: var(--tv-base-color-common-6); // #dbdbdb 分割线2(较短分割线场景) + // -- 暗色新增 -- + --tv-color-border-secondary-hover: var(--tv-base-color-common-7); // #c2c2c2 次要按钮边框悬浮色 + --tv-color-border-container: var(--tv-base-color-common-4); // #f0f0f0 卡片选择默认边框 + --tv-color-border-container-hover: var(--tv-base-color-common-1); // #fff 卡片选择悬浮边框 + --tv-color-border-container-active: var(--tv-base-color-brand-6); // #1476ff 卡片选择选中边框 + --tv-color-border-inverse-tint: var(--tv-base-color-common-1); // #fff tag边框 + --tv-color-border-1: var(--tv-base-color-common-6); // #dbdbdb 滑块圆圈描边 + + /** 3. 字体变量 **/ + + /* 3.1 字体家族 -- 【组件内不要指定】 */ + --tv-font-family: 'Helvetica', 'Arial', 'PingFangSC-Regular', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', 'Microsoft JhengHei'; // 默认中文 + --tv-font-family-1: 'Arial', 'San Francisco', 'Helvetica'; // 数字 / 英文 + + /* 3.2 字号 */ + --tv-font-size-sm: 12px; // 辅助文本 + --tv-font-size-md: 14px; // 正文,默认字体尺寸 + --tv-font-size-lg: 16px; + --tv-font-size-xl: 18px; + --tv-font-size-xxl: 20px; + --tv-font-size-default: var(--tv-font-size-md); + + --tv-font-size-heading-xs: 16px; // 卡片标题 + --tv-font-size-heading-sm: 18px; // 页面标题 + --tv-font-size-heading-md: 20px; // 弹窗标题、数字 + --tv-font-size-heading-lg: 24px; // 数字、面额 + --tv-font-size-heading-xl: 32px; // 数字、面额 + + /** 3.3 行高 */ + + --tv-line-height-number: 1.5; + + /* 3.4 字重 */ + --tv-font-weight-thin: 200; + --tv-font-weight-regular: 400; // 默认值:nomal + --tv-font-weight-bold: 600; + + /** 4. 圆角变量 **/ + --tv-border-radius-xs: 2px; + --tv-border-radius-sm: 4px; + --tv-border-radius-md: 6px; // 默认 + --tv-border-radius-lg: 8px; + --tv-border-radius-round: 999px; // 50% 会造成椭圆,避免使用。 + --tv-border-radius-brand: var(--tv-border-radius-round); // 品牌相关。用于圆角,按钮、分页等场景 + + /** 5. 边框 **/ + --tv-border-width: 1px; + + /** 6. 间距变量 space ----margin、padding、top、 left 、 right、bottom **/ + --tv-space-base: 4px; + --tv-space-xs: 2px; + --tv-space-sm: var(--tv-space-base); + --tv-space-md: calc(var(--tv-space-base) * 2); + --tv-space-lg: calc(var(--tv-space-base) * 3); + --tv-space-xl: calc(var(--tv-space-base) * 4); + --tv-space-xxl: calc(var(--tv-space-base) * 6); // 内容块之间的间距 + --tv-space-xxxl: calc(var(--tv-space-base) * 8); // 容器与容器内容的间距 + --tv-space-table-x: 4px; // 表格单元格水平间距基准 + --tv-space-table-y: 4px; // 表格单元格垂直间距基准 + + /** 7. 尺寸变量 size **/ + + /** 尺寸系数 calc */ + --tv-size-base: 4px; + + /** 7.1 表单类组件的 height */ + --tv-size-height-xs: 24px; // mini 尺寸 + --tv-size-height-sm: 28px; // small 尺寸 + --tv-size-height-md: 32px; // medium 尺寸 - 默认 + --tv-size-height-lg: 40px; // large 尺寸 + --tv-size-height-xl: 48px; // xLarge 尺寸 + + /** 7.2 图标大小 width, height **/ + --tv-icon-size: 16px; + + /** 8. 阴影变量 box-shadow **/ + --tv-shadow-0: 0 4px 16px 0 rgba(0, 0, 0, 0.08); // 页面布局容器组件(layout-section)阴影 + --tv-shadow-1: 0 0 0 0 rgba(0, 0, 0, 0); // 页面布局容器组件(layout-section)阴影 + --tv-shadow-cell-left: -5px 0 5px 0 rgba(0, 0, 0, 0.10); // 表格固定列阴影 + --tv-shadow-cell-right: 5px 0 5px 0 rgba(0, 0, 0, 0.10); // 表格固定列阴影 + + --tv-shadow-1-up: 0 -1px 4px 0 rgba(0, 0, 0, 0.08); // 购买浮层 + --tv-shadow-1-down: 0 1px 4px 0 rgba(0, 0, 0, 0.08); // 页面卡片、滑块、顶部导航 + --tv-shadow-1-left: -1px 0 4px 0 rgba(0, 0, 0, 0.08); + --tv-shadow-1-right: 1px 0 4px 0 rgba(0, 0, 0, 0.08); // 手风琴(leftmenu) + + --tv-shadow-2-up: 0 -2px 12px 0 rgba(0, 0, 0, 0.16); + --tv-shadow-2-down: 0 2px 12px 0 rgba(0, 0, 0, 0.16); // tips提示、扩展视图 + --tv-shadow-2-left: -2px 0 12px 0 rgba(0, 0, 0, 0.16); + --tv-shadow-2-right: 2px 0 12px 0 rgba(0, 0, 0, 0.16); + + --tv-shadow-3-up: 0 -4px 16px 0 rgba(0, 0, 0, 0.08); + --tv-shadow-3-down: 0 4px 16px 0 rgba(0, 0, 0, 0.08); // 卡片hover/选中、下拉面板 + --tv-shadow-3-left: -4px 0 16px 0 rgba(0, 0, 0, 0.08); + --tv-shadow-3-right: 4px 0 16px 0 rgba(0, 0, 0, 0.08); + + --tv-shadow-4-up: 0 -8px 24px 0 rgba(0, 0, 0, 0.16); + --tv-shadow-4-down: 0 8px 24px 0 rgba(0, 0, 0, 0.16); // 弹窗、气泡确认框 + --tv-shadow-4-left: -8px 0 24px 0 rgba(0, 0, 0, 0.16); // 右侧抽屉 + --tv-shadow-4-right: 8px 0 24px 0 rgba(0, 0, 0, 0.16); + + /** 9. 滚动条变量 **/ + --tv-size-scrollbar-width: 8px; // 滚动条宽度 + --tv-size-scrollbar-height: 8px; // 滚动条高度 + --tv-border-radius-scrollbar-thumb: 4px; // 滑块圆角 + --tv-color-bg-scrollbar-thumb: var(--tv-base-color-common-6); // #dbdbdb 滑块背景色 + --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.6s; /* 动画时长 */ + + /* ---------- 箭头移动 (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.5; /* 弹入/弹出中间比例 */ + --tv-motion-bounce-scale-max: 1; /* 最终展开比例 */ + --tv-motion-bounce-speed: 0.3s; /* 动画时长 */ + + /* ---------- 淡入淡出 (fade.less) ---------- */ + --tv-motion-fade-offset-x: 30vw; /* X轴位移 */ + --tv-motion-fade-offset-y: 30vh; /* 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.04s; /* 网格加载动画时长 */ + --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: 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轴结束位移 */ + + /* ---------- 光泽闪烁 (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: -60%; /* 左侧中间位移 */ + --tv-motion-slide-offset-right: 100%; /* 右侧初始位移 */ + --tv-motion-slide-offset-right-mid: 60%; /* 右侧中间位移 */ + /* Y轴偏移 */ + --tv-motion-slide-offset-top: -100%; /* 顶部初始位移 */ + --tv-motion-slide-offset-top-mid: -60%; /* 顶部中间位移 */ + --tv-motion-slide-offset-bottom: 100%; /* 底部初始位移 */ + --tv-motion-slide-offset-bottom-mid: 60%; /* 底部中间位移 */ + + /* ---------- 描边循环 (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: 1.2; /* 中间缩放 */ + --tv-motion-scale-end: 1; /* 结束缩放 */ + --tv-motion-scale-opacity-start: 0; /* 初始透明度 */ + --tv-motion-scale-opacity-mid: 0.6; /* 中间透明度 */ + --tv-motion-scale-opacity-end: 1; /* 结束透明度 */ +} diff --git a/packages/theme/src/base/reset.less b/packages/theme/src/base/reset.less index 5cd64b4f02..e8432706e7 100644 --- a/packages/theme/src/base/reset.less +++ b/packages/theme/src/base/reset.less @@ -12,21 +12,12 @@ @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; -} - -@keyframes rotating { - 0% { - transform: rotateZ(0deg); - } - - 100% { - transform: rotateZ(360deg); - } + animation: rotate-z var(--tv-motion-rotate-speed) linear infinite; } // 高亮节点 diff --git a/packages/theme/src/base/transition.less b/packages/theme/src/base/transition.less index 2520f0e1ca..28df7ee3a7 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 { @@ -243,28 +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 4339ba352e..7d96190f31 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.04s; /* 网格加载动画时长 */ + --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: 2s; /* 旋转动画时长 */ + --tv-motion-rotate-degrees: 360deg; /* 旋转角度 */ + + /* ---------- 滚动文字 (scroll.less) ---------- */ + --tv-motion-scroll-speed: 3s; /* 动画时长 */ + --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轴结束位移 */ + + /* ---------- 光泽闪烁 (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 75b18d1df9..915a8786df 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 var(--tv-motion-rotate-speed) linear infinite; } .path { - animation: loading-dash 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; @@ -68,26 +69,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 3832dbddbb..3ea53b5a2f 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,118 +210,34 @@ } .v-modal-enter { - animation: v-modal-in 0.2s ease; + animation: fade-in var(--tv-motion-fade-speed) ease; } .v-modal-leave { - animation: v-modal-out 0.2s ease forwards; -} - -@keyframes v-modal-in { - 0% { - opacity: 0; - } -} - -@keyframes v-modal-out { - 100% { - opacity: 0; - } + animation: fade-out var(--tv-motion-fade-speed) ease forwards; } .dialog-slideRight-enter-active { - animation: slideRight 0.5s ease-in forwards; + animation: slide-right-in var(--tv-motion-slide-speed) 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%); - } -} - -@keyframes slideRightout { - 0% { - opacity: 1; - transform: translateX(0%); - } - - 50% { - opacity: 0.6; - transform: translateX(50%); - } - - 100% { - opacity: 0; - transform: translateX(100%); - } + animation: slide-right-out var(--tv-motion-slide-speed) ease-in forwards; } .dialog-fade-enter-active { - animation: dialog-fade-in 0.3s; + animation: fade-in-up var(--tv-motion-fade-speed); } .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; - } -} - -@keyframes dialog-fade-out { - 0% { - transform: translate3d(0, 0, 0); - opacity: 1; - } - - 100% { - transform: translate3d(0, -20px, 0); - opacity: 0; + animation: fade-out-up var(--tv-motion-fade-speed); } + animation: fade-out-up var(--tv-motion-fade-speed); } .enlarge-enter-active { - animation: enlarge-in 350ms linear; -} - -@keyframes enlarge-in { - 0% { - transform: scale(0); - } - - 50% { - transform: scale(0.5); - } - - 100% { - transform: scale(1); - } + animation: enlarge-in var(--tv-motion-scale-speed) linear; } @media (max-width: 480px) { diff --git a/packages/theme/src/drawer/index.less b/packages/theme/src/drawer/index.less index ec8828fc2d..6dc05a18e3 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,41 @@ } .drawer-slide-right-enter-active { - animation: slideRight 0.3s linear; + animation: slide-right-in var(--tv-motion-slide-speed) linear; } .drawer-slide-right-leave-active { - animation: slideRightout 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%); - } + animation: slide-right-out var(--tv-motion-slide-speed) linear; } .drawer-slide-left-enter-active { - animation: slideLeft 0.3s linear; + animation: slide-left-in var(--tv-motion-slide-speed) linear; } .drawer-slide-left-leave-active { - animation: slideLeftout 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%); - } + animation: slide-left-out var(--tv-motion-slide-speed) linear; } .drawer-slide-bottom-enter-active { - animation: slideBottom 0.3s linear; + animation: slide-bottom-in var(--tv-motion-slide-speed) linear; } .drawer-slide-bottom-leave-active { - animation: slideBottomout 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%); - } + animation: slide-bottom-out var(--tv-motion-slide-speed) linear; } .drawer-slide-top-enter-active { - animation: slideTop 0.3s linear; + animation: slide-top-in var(--tv-motion-slide-speed) 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%); - } -} - -@keyframes slideTopout { - 0% { - opacity: 0; - transform: translateY(0%); - } - - 50% { - opacity: 0.6; - transform: translateY(-50%); - } - - 100% { - opacity: 1; - transform: translateY(-100%); - } + animation: slide-top-out var(--tv-motion-slide-speed) linear; } .drawer-fade-enter-active { - animation: drawer-fade-in 0.3s linear; + animation: fade-in var(--tv-motion-fade-speed) linear; } .drawer-fade-leave-active { - animation: drawer-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; - } -} + animation: fade-out var(--tv-motion-fade-speed) linear; +} \ 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 e5cf7e3057..1431f54cc7 100644 --- a/packages/theme/src/fall-menu/index.less +++ b/packages/theme/src/fall-menu/index.less @@ -185,32 +185,4 @@ .opacity(1); } } -} - -@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 ecf2cc17d1..ed5821491f 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'; @@ -56,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; @@ -67,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; } } } @@ -92,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 c7671b6ad4..a9e65ae91c 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'; @@ -79,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 3ffa3fda86..c9c1e0bd50 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,8 @@ } &.roll { - animation: rollCircle 1s infinite linear; + --tv-motion-rotate-speed: 1s; + animation: rotate-spin var(--tv-motion-rotate-speed) infinite linear; } } @@ -384,13 +386,3 @@ } } } - -@keyframes rollCircle { - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(360deg); - } -} diff --git a/packages/theme/src/grid/loading.less b/packages/theme/src/grid/loading.less index 4a5dd55e31..066501bb38 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,17 +57,7 @@ border-radius: 50%; background: linear-gradient(#000, #000); position: absolute; - animation: load 1.04s ease infinite; - } - - @keyframes load { - 0% { - opacity: 10; - } - - 100% { - opacity: 0.1; - } + animation: grid-loading var(--tv-motion-grid-loading-speed) ease infinite; } span:nth-child(1) { diff --git a/packages/theme/src/image/index.less b/packages/theme/src/image/index.less index 3d8b558b14..d8315b0157 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,9 @@ } .viewer-fade-enter-active { - animation: viewer-fade-in 0.3s; + animation: fade-in-up var(--tv-motion-fade-speed); } .viewer-fade-leave-active { - animation: viewer-fade-out 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; - } -} + animation: fade-out-up var(--tv-motion-fade-speed); +} \ 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 new file mode 100644 index 0000000000..7276b11d3d --- /dev/null +++ b/packages/theme/src/motion/arrow.less @@ -0,0 +1,110 @@ +/* =========================== + 箭头移动动画 (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: var(--tv-motion-arrow-left-init, -17px); + } + 50% { + left: var(--tv-motion-arrow-left-mid, -13px); + } + 100% { + left: var(--tv-motion-arrow-left-init, -17px); + } +} + +@keyframes arrow-right-pulse { + 0% { + right: var(--tv-motion-arrow-right-init, -17px); + } + 50% { + right: var(--tv-motion-arrow-right-mid, -13px); + } + 100% { + 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: var(--tv-motion-arrow-offset, 16px); + } +} + +@keyframes arrow-left-carousel { + 0% { + opacity: 0; + left: 0; + } + 100% { + opacity: 1; + transform: translateY(-50%); + 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: var(--tv-motion-arrow-offset, 16px); + } +} + +@keyframes arrow-right-in { + 0% { + opacity: 0; + right: 0; + } + 100% { + opacity: 1; + transform: translateY(-50%); + right: var(--tv-motion-arrow-offset, 16px); + } +} + +@keyframes arrow-left-out { + 0% { + opacity: 1; + transform: translateY(-50%); + left: var(--tv-motion-arrow-offset, 16px); + } + 100% { + opacity: 0; + left: 0; + } +} + +@keyframes arrow-right-out { + 0% { + opacity: 1; + transform: translateY(-50%); + right: var(--tv-motion-arrow-offset, 16px); + } + 100% { + opacity: 0; + right: 0; + } +} diff --git a/packages/theme/src/motion/bounce.less b/packages/theme/src/motion/bounce.less new file mode 100644 index 0000000000..96b3ea82c8 --- /dev/null +++ b/packages/theme/src/motion/bounce.less @@ -0,0 +1,36 @@ +/* =========================== + 缩放弹入动画 (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(var(--tv-motion-bounce-scale-min, 0)); + } + 50% { + transform: scale(var(--tv-motion-bounce-scale-mid, 1.2)); + } + 100% { + transform: scale(var(--tv-motion-bounce-scale-max, 1)); + } +} + +/* ============ 弹出 ============ */ +@keyframes bounce-out { + 0% { + transform: scale(var(--tv-motion-bounce-scale-max, 1)); + } + 50% { + transform: scale(var(--tv-motion-bounce-scale-mid, 1.2)); + } + 100% { + transform: scale(var(--tv-motion-bounce-scale-min, 0)); + } +} diff --git a/packages/theme/src/motion/configuration-maintenance.md b/packages/theme/src/motion/configuration-maintenance.md new file mode 100644 index 0000000000..50cf9fea8f --- /dev/null +++ b/packages/theme/src/motion/configuration-maintenance.md @@ -0,0 +1,147 @@ +# 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 { + /* 蚂蚁线相关配置 */ + --tv-motion-ants-shift: 8px; + --tv-motion-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 fade-in-up { + 0% { + transform: translate3d(0, -20p, 0); + opacity: 0; + } + 100% { + transform: translate3d(0, 0, 0); + opacity: 1; + } +} +``` + +### Step 2. (可选)使用变量替代固定值 + +```less +@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 +.dialog-fade-enter-active { + animation: fade-in-up var(--tv-motion-fade-speed); +} +``` + +### Step 4. 更新文档 + +- 在 **对应 `.less` 文件顶部注释** 动效用途 +- 在 PR 描述中说明:类别 / 动效名 / 用法示例 + +------ + +## 6. 动效扩展与维护 + +### 6.1 扩展原则 + +1. 动效必须写在对应分类文件中(如滑动类 → `slide.less`)。 +2. 保持命名唯一性,避免与现有动效冲突。 +3. 需要新变量时,先在 `index.less` 中声明,再调用。 + +### 6.2 维护规范 + +- **代码注释**:在 `@keyframes` 前标注用途和来源。 +- **文件内分组**:同类动效写在一起,便于查找。 + +------ + +## 7. 组件集成方式 + +1. **全局引入** + 所有动效在 `motion/*` 中维护,并在组件中通过className或者animation使用。 +3. **覆盖参数** + 用户可覆盖变量来自定义速度/时长。 + +------ + +## 8. 常见问题 + +- **不同组件能否自定义时长?** + 可以,在组件作用域覆盖变量。 \ No newline at end of file diff --git a/packages/theme/src/motion/fade.less b/packages/theme/src/motion/fade.less new file mode 100644 index 0000000000..7d7bf01996 --- /dev/null +++ b/packages/theme/src/motion/fade.less @@ -0,0 +1,139 @@ +/* =========================== + 淡入淡出动画 (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; + } +} + +@keyframes fade-out { + 0% { + opacity: 1; + } + 100% { + opacity: 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; + } +} + +@keyframes fade-out-up { + 0% { + transform: translate3d(0, 0, 0); + opacity: 1; + } + 100% { + transform: translate3d(0, calc(-1 * var(--tv-motion-fade-offset-y, 20px)), 0); + opacity: 0; + } +} + +@keyframes fade-in-down { + 0% { + transform: translate3d(0, var(--tv-motion-fade-offset-y, 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, var(--tv-motion-fade-offset-y, 20px), 0); + opacity: 0; + } +} + +@keyframes fade-in-left { + 0% { + transform: translate3d(calc(-1 * var(--tv-motion-fade-offset-x, 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(calc(-1 * var(--tv-motion-fade-offset-x, 20px)), 0, 0); + opacity: 0; + } +} + +@keyframes fade-in-right { + 0% { + transform: translate3d(var(--tv-motion-fade-offset-x, 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(var(--tv-motion-fade-offset-x, 20px), 0, 0); + opacity: 0; + } +} + +/* ============ 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; + } +} diff --git a/packages/theme/src/motion/global-configuration.md b/packages/theme/src/motion/global-configuration.md new file mode 100644 index 0000000000..9211710491 --- /dev/null +++ b/packages/theme/src/motion/global-configuration.md @@ -0,0 +1,225 @@ +# TinyVue 全局动效配置 + +## 1. 背景与目标 + +在应用开发中,统一的动效配置有助于提升整体用户体验和产品一致性。 + 本方案为 TinyVue 提供 **全局动效配置能力**,仅依赖 **LESS 与 CSS 变量**,实现以下目标: + +1. **统一管理**:所有动效集中管理,避免分散定义和重复维护。 +2. **全局可控**:通过 CSS 变量统一控制动效的持续时间、延迟、速度等参数。 +3. **组件集成**:组件可直接调用统一的动效类名或 `@keyframes`。 +4. **动态可调**:通过覆盖 CSS 变量即可在不同场景下切换动效风格。 + +------ + +## 2. 全局配置 + +### 2.1 全局变量定义 + +在 `/packages/theme/src/motion/index.less` 中统一定义: + +```less +:root { + /* 蚂蚁线相关配置 */ + --tv-motion-ants-shift: 8px; + --tv-motion-ants-speed: 0.8s; + ... +} +``` + +开发者可在组件主题文件中覆盖这些变量: + +```css +.copyed-borders { + --tv-motion-ants-shift: 12px; + --tv-motion-ants-speed: 1.2s; +} +``` + +------ + +## 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: var(--tv-motion-fade-speed) fade-in both ease-out; + } + + &-leave-active { + animation: var(--tv-motion-fade-speed) fade-out both ease-in; + } +} +``` + +--- + +### 3.2 示例:滑动 (slide.less) + +```less +/* ============ 左滑 ============ */ +@keyframes slide-left-in { + 0% { + opacity: 0; + transform: translateX(var(--tv-motion-slide-offset-left)); + } + 50% { + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateX(var(--tv-motion-slide-offset-left-mid)); + } + 100% { + opacity: 1; + transform: translateX(0%); + } +} + +@keyframes slide-left-out { + 0% { + opacity: 1; + transform: translateX(0%); + } + 50% { + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateX(var(--tv-motion-slide-offset-left-mid)); + } + 100% { + opacity: 0; + transform: translateX(var(--tv-motion-slide-offset-left)); + } +} +``` + +组件调用示例: + +```less +.drawer-slide-left-enter-active { + animation: slide-left-in var(--tv-motion-slide-speed) linear; +} + +.drawer-slide-left-leave-active { + animation: slide-left-out var(--tv-motion-slide-speed) linear; +} +``` + +### 3.3 示例:蚂蚁线 (ants.less,可配置) + +```less +@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; + } +} +``` + +组件调用示例: + +```less + .@{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; + } + } +``` + +------ + +## 4. 组件集成方式 + +1. **全局引入** + 所有 `@keyframes` 集中在 `transition.less` 和 `motion/*` 中。 +2. **局部调用** + 组件通过 className 或 `-enter-active / -leave-active` 绑定。 +3. **可配置参数** + 开发者可通过覆盖 `:root` 变量修改动效时长、速度等。 + +示例动效: + +```less +.drawer-slide-left-enter-active { + animation: slide-left-in var(--tv-motion-slide-speed) linear; +} +``` + +------ + +## 5. 扩展与维护 + +1. **命名规范**: + - 使用 `{type}-{direction}-{state}` 格式,例如 `slide-left-in`。 + - 保证全局唯一性,避免冲突。 +2. **文档补充**: + - 每类动效提供示例代码与调用方式说明。 +3. **未来扩展**: + - 支持引入方便引入其他动效资源,增强 TinyVue 动效生态。 diff --git a/packages/theme/src/motion/index.less b/packages/theme/src/motion/index.less new file mode 100644 index 0000000000..465ff53ae4 --- /dev/null +++ b/packages/theme/src/motion/index.less @@ -0,0 +1,16 @@ +/* ========================================== + 动画模块 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 './loading.less'; +@import './shine.less'; +@import './ants.less'; 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 new file mode 100644 index 0000000000..95891133b0 --- /dev/null +++ b/packages/theme/src/motion/progress.less @@ -0,0 +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: var(--tv-motion-progress-background-shift, 32px) 0; + } +} + +@-webkit-keyframes progress-background { + 0% { + background-position: 0 0; + } + 100% { + 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 new file mode 100644 index 0000000000..0d659ab1f1 --- /dev/null +++ b/packages/theme/src/motion/rotate.less @@ -0,0 +1,30 @@ +/* =========================== + 通用旋转 + 进度加载动画 (rotate.less) + 来源: chart-core, tree + 可配置变量: + --tv-motion-rotate-speed 旋转动画时长 + --tv-motion-rotate-degrees 旋转的角度 +=========================== */ + +/* ============ 旋转动画 ============ */ +@keyframes rotate-spin { + // chart-core:loading-rotate, tree:loading-rotate + 100% { + transform: rotate(var(--tv-motion-rotate-degrees, 360deg)); + } +} + +@keyframes rotate-z { + 0% { + transform: rotateZ(0deg); + } + 100% { + transform: rotateZ(var(--tv-motion-rotate-degrees, 360deg)); + } +} + +@keyframes rotate-reverse { + 100% { + transform: rotate(var(--tv-motion-rotate-degrees, -360deg)); + } +} diff --git a/packages/theme/src/motion/scroll.less b/packages/theme/src/motion/scroll.less new file mode 100644 index 0000000000..f181f57fe6 --- /dev/null +++ b/packages/theme/src/motion/scroll.less @@ -0,0 +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(var(--tv-motion-scroll-offset-x, 100%)); + } + 100% { + transform: translateX(var(--tv-motion-scroll-offset-x-end, -100%)); + } +} + +@keyframes scroll-right { + 0% { + transform: translateX(var(--tv-motion-scroll-offset-x-end, -100%)); + } + 100% { + transform: translateX(var(--tv-motion-scroll-offset-x, 100%)); + } +} + +@keyframes scroll-up { + 0% { + transform: translateY(var(--tv-motion-scroll-offset-y, 100%)); + } + 100% { + transform: translateY(var(--tv-motion-scroll-offset-y-end, -100%)); + } +} + +@keyframes scroll-down { + 0% { + transform: translateY(var(--tv-motion-scroll-offset-y-end, -100%)); + } + 100% { + transform: translateY(var(--tv-motion-scroll-offset-y, 100%)); + } +} + +/* ============ 滚动适应动画 ============ */ +@keyframes scroll-left-adapt { + 0% { + transform: translateX(var(--tv-motion-scroll-offset-x, 100%)); + } + 50% { + transform: translateX(0); + } + 100% { + transform: translateX(var(--tv-motion-scroll-offset-x-end, -100%)); + } +} + +@keyframes scroll-right-adapt { + 0% { + transform: translateX(var(--tv-motion-scroll-offset-x-end, -100%)); + } + 50% { + transform: translateX(0); + } + 100% { + transform: translateX(var(--tv-motion-scroll-offset-x, 100%)); + } +} + +@keyframes scroll-up-adapt { + 0% { + transform: translateY(var(--tv-motion-scroll-offset-y, 100%)); + } + 50% { + transform: translateY(0); + } + 100% { + transform: translateY(var(--tv-motion-scroll-offset-y-end, -100%)); + } +} + +@keyframes scroll-down-adapt { + 0% { + transform: translateY(var(--tv-motion-scroll-offset-y-end, -100%)); + } + 50% { + transform: translateY(0); + } + 100% { + transform: translateY(var(--tv-motion-scroll-offset-y, 100%)); + } +} diff --git a/packages/theme/src/motion/shine.less b/packages/theme/src/motion/shine.less new file mode 100644 index 0000000000..958301dd48 --- /dev/null +++ b/packages/theme/src/motion/shine.less @@ -0,0 +1,18 @@ +/* =========================== + 光泽闪烁动画 (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: var(--tv-motion-shine-offset-x, -1px) var(--tv-motion-shine-offset-y, -1px); + } + 100% { + background-position: var(--tv-motion-shine-offset-x, -12px) var(--tv-motion-shine-offset-y, -12px); + } +} diff --git a/packages/theme/src/motion/slide.less b/packages/theme/src/motion/slide.less new file mode 100644 index 0000000000..a132d3c3cb --- /dev/null +++ b/packages/theme/src/motion/slide.less @@ -0,0 +1,133 @@ +/* =========================== + 抽屉/对话框滑动方向动画 (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(var(--tv-motion-slide-offset-left)); + } + 50% { + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateX(var(--tv-motion-slide-offset-left-mid)); + } + 100% { + opacity: 1; + transform: translateX(0%); + } +} + +@keyframes slide-left-out { + 0% { + opacity: 1; + transform: translateX(0%); + } + 50% { + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateX(var(--tv-motion-slide-offset-left-mid)); + } + 100% { + opacity: 0; + transform: translateX(var(--tv-motion-slide-offset-left)); + } +} + +/* ============ 右滑 ============ */ +@keyframes slide-right-in { + 0% { + opacity: 0; + transform: translateX(var(--tv-motion-slide-offset-right)); + } + 50% { + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateX(var(--tv-motion-slide-offset-right-mid)); + } + 100% { + opacity: 1; + transform: translateX(0%); + } +} + +@keyframes slide-right-out { + 0% { + opacity: 1; + transform: translateX(0%); + } + 50% { + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateX(var(--tv-motion-slide-offset-right-mid)); + } + 100% { + opacity: 0; + transform: translateX(var(--tv-motion-slide-offset-right)); + } +} + +/* ============ 上滑 ============ */ +@keyframes slide-top-in { + 0% { + opacity: 0; + transform: translateY(var(--tv-motion-slide-offset-top)); + } + 50% { + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateY(var(--tv-motion-slide-offset-top-mid)); + } + 100% { + opacity: 1; + transform: translateY(0%); + } +} + +@keyframes slide-top-out { + 0% { + opacity: 1; + transform: translateY(0%); + } + 50% { + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateY(var(--tv-motion-slide-offset-top-mid)); + } + 100% { + opacity: 0; + transform: translateY(var(--tv-motion-slide-offset-top)); + } +} + +/* ============ 下滑 ============ */ +@keyframes slide-bottom-in { + 0% { + opacity: 0; + transform: translateY(var(--tv-motion-slide-offset-bottom)); + } + 50% { + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateY(var(--tv-motion-slide-offset-bottom-mid)); + } + 100% { + opacity: 1; + transform: translateY(0%); + } +} + +@keyframes slide-bottom-out { + 0% { + opacity: 1; + transform: translateY(0%); + } + 50% { + opacity: var(--tv-motion-slide-opacity-mid); + transform: translateY(var(--tv-motion-slide-offset-bottom-mid)); + } + 100% { + opacity: 0; + transform: translateY(var(--tv-motion-slide-offset-bottom)); + } +} diff --git a/packages/theme/src/motion/stroke.less b/packages/theme/src/motion/stroke.less new file mode 100644 index 0000000000..1e98bb6e8f --- /dev/null +++ b/packages/theme/src/motion/stroke.less @@ -0,0 +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 { + 0% { + stroke-dasharray: var(--tv-motion-stroke-dasharray-0, 1, 200); + stroke-dashoffset: var(--tv-motion-stroke-offset-0, 0); + } + 50% { + stroke-dasharray: var(--tv-motion-stroke-dasharray-50, 90, 150); + stroke-dashoffset: var(--tv-motion-stroke-offset-50, -40px); + } + 100% { + 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: var(--tv-motion-stroke-dasharray-0, 1, 200); + stroke-dashoffset: var(--tv-motion-stroke-offset-0, 0); + } + 50% { + stroke-dasharray: var(--tv-motion-stroke-dasharray-50, 90, 150); + stroke-dashoffset: var(--tv-motion-stroke-offset-reverse-50, 40px); + } + 100% { + stroke-dasharray: var(--tv-motion-stroke-dasharray-100, 90, 150); + stroke-dashoffset: var(--tv-motion-stroke-offset-reverse-100, 120px); + } +} diff --git a/packages/theme/src/motion/tab.less b/packages/theme/src/motion/tab.less new file mode 100644 index 0000000000..6a4329b52c --- /dev/null +++ b/packages/theme/src/motion/tab.less @@ -0,0 +1,114 @@ +/* =========================== + 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: var(--tv-motion-tab-opacity-start, 0); + transform-origin: 0 0; + transform: translateX(var(--tv-motion-tab-offset-x-start, 100%)); + } + 100% { + 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(var(--tv-motion-tab-offset-x-end, 0)); + opacity: var(--tv-motion-tab-opacity-end, 1); + } + 100% { + 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: var(--tv-motion-tab-opacity-start, 0); + transform-origin: 0 0; + transform: translateX(var(--tv-motion-tab-offset-x-start-left, -100%)); + } + 100% { + 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(var(--tv-motion-tab-offset-x-end, 0)); + opacity: var(--tv-motion-tab-opacity-end, 1); + } + 100% { + 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: var(--tv-motion-tab-opacity-start, 0); + transform-origin: 0 0; + transform: translateY(var(--tv-motion-tab-offset-y-start, 100%)); + } + 100% { + 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(var(--tv-motion-tab-offset-y-end, 0)); + opacity: var(--tv-motion-tab-opacity-end, 1); + } + 100% { + 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: var(--tv-motion-tab-opacity-start, 0); + transform-origin: 0 0; + transform: translateY(var(--tv-motion-tab-offset-y-start-down, -100%)); + } + 100% { + 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(var(--tv-motion-tab-offset-y-end, 0)); + opacity: var(--tv-motion-tab-opacity-end, 1); + } + 100% { + transform: translateY(var(--tv-motion-tab-offset-y-start-down, -100%)); + opacity: var(--tv-motion-tab-opacity-start, 0); + } +} diff --git a/packages/theme/src/motion/zoom.less b/packages/theme/src/motion/zoom.less new file mode 100644 index 0000000000..9e0808d7b0 --- /dev/null +++ b/packages/theme/src/motion/zoom.less @@ -0,0 +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(var(--tv-motion-scale-start, 0)); + } + 50% { + transform: scale(var(--tv-motion-scale-mid, 0.5)); + } + 100% { + transform: scale(var(--tv-motion-scale-end, 1)); + } +} + +@keyframes enlarge-in-fade { + 0% { + transform: scale(var(--tv-motion-scale-start, 0)); + opacity: var(--tv-motion-scale-opacity-start, 0); + } + 50% { + transform: scale(var(--tv-motion-scale-mid, 0.5)); + opacity: var(--tv-motion-scale-opacity-mid, 0.5); + } + 100% { + transform: scale(var(--tv-motion-scale-end, 1)); + opacity: var(--tv-motion-scale-opacity-end, 1); + } +} + +/* ============ 收缩缩放 ============ */ +@keyframes shrink-out { + 0% { + transform: scale(var(--tv-motion-scale-end, 1)); + } + 50% { + transform: scale(var(--tv-motion-scale-mid, 0.5)); + } + 100% { + transform: scale(var(--tv-motion-scale-start, 0)); + } +} + +@keyframes shrink-out-fade { + 0% { + transform: scale(var(--tv-motion-scale-end, 1)); + opacity: var(--tv-motion-scale-opacity-end, 1); + } + 50% { + transform: scale(var(--tv-motion-scale-mid, 0.5)); + opacity: var(--tv-motion-scale-opacity-mid, 0.5); + } + 100% { + transform: scale(var(--tv-motion-scale-start, 0)); + opacity: var(--tv-motion-scale-opacity-start, 0); + } +} diff --git a/packages/theme/src/popup/index.less b/packages/theme/src/popup/index.less index 795112ee48..9b8893b3a5 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: var(--tv-motion-fade-speed) fade-in both ease-out; } &-leave-active { - animation: 0.3s mobile-fade-out both ease-in; + animation: var(--tv-motion-fade-speed) fade-out both ease-in; } } @@ -157,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 ae3d9d8ec8..2300a1e92e 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'; @@ -144,24 +145,4 @@ } } } -} - -@-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 1e3d52123a..d1fb118c7e 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,13 @@ > 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%); - } -} +} \ No newline at end of file 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 28e432186a..925ba2b77d 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'; @@ -34,7 +35,6 @@ overflow: hidden; } - /** 头部场景 */ &__header { position: relative; @@ -44,7 +44,6 @@ align-items: center; .@{tabs-prefix-cls} { - // 活跃块 &__active-bar { position: absolute; @@ -237,7 +236,6 @@ } .@{tabs-prefix-cls}__icon-close { - &, &:hover { background-color: transparent; @@ -250,7 +248,6 @@ } &.is-closable { - // 修复自定义标签配置:with-close="true"样式错乱问题 > div { display: inline-block; @@ -273,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; @@ -417,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); } @@ -434,7 +433,6 @@ // 一层tab页签: card类型 &&--card { - &.@{tabs-prefix-cls}--left .@{tabs-prefix-cls}__nav, &.@{tabs-prefix-cls}--right .@{tabs-prefix-cls}__nav { width: 120px; @@ -990,7 +988,6 @@ &&--left, &&--right { .@{tabs-prefix-cls} { - &__header, &__nav-wrap { height: 100%; @@ -1104,7 +1101,6 @@ } .@{tab-pane-prefix-cls} { - .@{tabs-prefix-cls}__header, .@{tabs-prefix-cls}__nav-wrap { float: inherit; @@ -1235,7 +1231,6 @@ &.is-left, &.is-right { - .@{tabs-prefix-cls}__nav-prev, .@{tabs-prefix-cls}__nav-next { display: none; @@ -1324,172 +1319,24 @@ } .slideInRight-enter { - -webkit-animation: slideInRight-enter 0.3s; - animation: slideInRight-enter 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: slideInRight-leave 0.3s; + animation: tab-slide-right-out var(--tv-motion-tab-speed); } .slideInLeft-enter { - -webkit-animation: slideInLeft-enter 0.3s; - animation: slideInLeft-enter 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: slideInLeft-leave 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); - } + animation: tab-slide-left-out var(--tv-motion-tab-speed); } - - @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..734c3b686c 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 var(--tv-motion-arrow-speed); } .@{css-prefix}transition-carousel-arrow-left-leave-active { - animation: animation-left 0.3s reverse; + animation: arrow-left-carousel var(--tv-motion-arrow-speed) reverse; } .@{css-prefix}transition-carousel-arrow-right-enter, @@ -35,35 +36,9 @@ } .@{css-prefix}transition-carousel-arrow-right-enter-active { - animation: animation-right 0.3s; + animation: arrow-right-carousel var(--tv-motion-arrow-speed); } .@{css-prefix}transition-carousel-arrow-right-leave-active { - animation: animation-right 0.3s 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; - } + animation: arrow-right-carousel var(--tv-motion-arrow-speed) reverse; } diff --git a/packages/theme/src/transition/icon.less b/packages/theme/src/transition/icon.less index 6a94e8c0e1..87518c25a7 100644 --- a/packages/theme/src/transition/icon.less +++ b/packages/theme/src/transition/icon.less @@ -11,48 +11,21 @@ */ @import '../custom.less'; +@import '../motion/index.less'; // 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: scale-in 0.3s; + animation: bounce-in var(--tv-motion-bounce-speed); } .@{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); - } -} - -@keyframes scale-in { - 0% { - transform: scale(0); - } - - 50% { - transform: scale(1.2); - } - - 100% { - transform: scale(1); - } -} + animation: bounce-in var(--tv-motion-bounce-speed) reverse; +} \ No newline at end of file diff --git a/packages/theme/src/transition/timepicker.less b/packages/theme/src/transition/timepicker.less index 81d25ce8c9..1792c74dae 100644 --- a/packages/theme/src/transition/timepicker.less +++ b/packages/theme/src/transition/timepicker.less @@ -11,35 +11,12 @@ */ @import '../custom.less'; +@import '../motion/index.less'; .@{css-prefix}transition-timepicker { - animation: fadein 0.3s; + animation: fade-in-timepicker var(--tv-motion-fade-speed); } .@{css-prefix}transition-timepicker-up { - animation: fadeup 0.3s; -} - -@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; - } -} + animation: fade-up-timepicker var(--tv-motion-fade-speed); +} \ No newline at end of file diff --git a/packages/theme/src/tree/index.less b/packages/theme/src/tree/index.less index 37e209ab28..460538bd4c 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'; @@ -475,27 +476,4 @@ 0.3s padding-top ease-in-out, 0.3s padding-bottom ease-in-out; } -} - -@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; - } -} +} \ No newline at end of file