@luanlu/mk-motion 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -4
- package/src/a11y/focus-trap.ts +64 -0
- package/src/a11y/keyboard.ts +43 -0
- package/src/components/alert/alert.css +111 -0
- package/src/components/alert/alert.ts +107 -0
- package/src/components/avatar/avatar.css +112 -0
- package/src/components/avatar/avatar.ts +175 -0
- package/src/components/breadcrumb/breadcrumb.css +31 -0
- package/src/components/breadcrumb/breadcrumb.ts +71 -0
- package/src/components/button/button.css +108 -0
- package/src/components/button/button.ts +140 -0
- package/src/components/card/card.css +52 -0
- package/src/components/card/card.ts +87 -0
- package/src/components/collapse/collapse.css +76 -0
- package/src/components/collapse/collapse.ts +168 -0
- package/src/components/dialog/dialog.css +78 -0
- package/src/components/dialog/dialog.ts +164 -0
- package/src/components/drawer/drawer.css +73 -0
- package/src/components/drawer/drawer.ts +131 -0
- package/src/components/empty/empty.css +36 -0
- package/src/components/empty/empty.ts +85 -0
- package/src/components/form/checkbox.css +56 -0
- package/src/components/form/checkbox.ts +119 -0
- package/src/components/form/radio.css +57 -0
- package/src/components/form/radio.ts +153 -0
- package/src/components/form/select.css +91 -0
- package/src/components/form/select.ts +174 -0
- package/src/components/form/slider.css +56 -0
- package/src/components/form/slider.ts +148 -0
- package/src/components/input/input.css +92 -0
- package/src/components/input/input.ts +162 -0
- package/src/components/layout/divider.css +32 -0
- package/src/components/layout/divider.ts +42 -0
- package/src/components/layout/row.css +64 -0
- package/src/components/layout/row.ts +57 -0
- package/src/components/layout/space.css +14 -0
- package/src/components/layout/space.ts +48 -0
- package/src/components/loading/loading.css +37 -0
- package/src/components/loading/loading.ts +46 -0
- package/src/components/menu/menu.css +121 -0
- package/src/components/menu/menu.ts +187 -0
- package/src/components/message/message.css +64 -0
- package/src/components/message/message.ts +96 -0
- package/src/components/popover/popover.css +73 -0
- package/src/components/popover/popover.ts +279 -0
- package/src/components/progress/progress.css +112 -0
- package/src/components/progress/progress.ts +171 -0
- package/src/components/steps/steps.css +127 -0
- package/src/components/steps/steps.ts +102 -0
- package/src/components/styles/components.css +28 -0
- package/src/components/styles/reset.css +24 -0
- package/src/components/styles/tokens.css +248 -0
- package/src/components/styles/variables.css +24 -0
- package/src/components/switch/switch.css +53 -0
- package/src/components/switch/switch.ts +103 -0
- package/src/components/table/table.css +192 -0
- package/src/components/table/table.ts +370 -0
- package/src/components/tabs/tabs.css +138 -0
- package/src/components/tabs/tabs.ts +211 -0
- package/src/components/tag/tag.css +123 -0
- package/src/components/tag/tag.ts +112 -0
- package/src/components/tooltip/tooltip.css +66 -0
- package/src/components/tooltip/tooltip.ts +185 -0
- package/src/core/animator.ts +124 -0
- package/src/core/timeline.ts +128 -0
- package/src/core/utils.ts +47 -0
- package/src/effects/glitch.ts +99 -0
- package/src/effects/particle.ts +134 -0
- package/src/effects/text-split.ts +95 -0
- package/src/effects/wave-text.ts +88 -0
- package/src/gesture/draggable.ts +130 -0
- package/src/gesture/spring.ts +152 -0
- package/src/index.ts +162 -0
- package/src/interactive/coverflow.ts +100 -0
- package/src/interactive/cursor-trail.ts +113 -0
- package/src/interactive/flip-card.ts +114 -0
- package/src/interactive/magnetic.ts +121 -0
- package/src/micro/hover-lift.ts +94 -0
- package/src/micro/ripple.ts +130 -0
- package/src/motion/component-motion.ts +177 -0
- package/src/presets/index.ts +69 -0
- package/src/scroll/scroll-trigger.ts +104 -0
- package/src/styles/animations.css +135 -0
- package/src/styles/element-plus.css +174 -0
- package/src/text/count-up.ts +108 -0
- package/src/text/typewriter.ts +109 -0
- package/src/theme/dark.css +19 -0
- package/src/theme/light.css +19 -0
- package/src/theme/theme.ts +65 -0
- package/src/transitions/blur-reveal.ts +92 -0
- package/src/transitions/collapse.ts +112 -0
- package/src/transitions/lazy-image.ts +87 -0
- package/src/transitions/list.ts +75 -0
- package/src/transitions/loading.ts +95 -0
- package/src/transitions/parallax.ts +60 -0
- package/src/transitions/shimmer.ts +105 -0
- package/src/transitions/toast.ts +151 -0
- package/src/types.d.ts +4 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { Animator } from '../core/animator.ts'
|
|
2
|
+
import type { AnimationName } from '../core/utils.ts'
|
|
3
|
+
|
|
4
|
+
export type MicroAnimation = 'lift' | 'glow' | 'scale' | 'slideUp' | 'none'
|
|
5
|
+
|
|
6
|
+
export interface MotionOptions {
|
|
7
|
+
/** Mount entrance animation */
|
|
8
|
+
enter?: 'fadeIn' | 'slideInUp' | 'slideInDown' | 'slideInLeft' | 'slideInRight' | 'zoomIn' | 'bounceIn' | 'none'
|
|
9
|
+
/** Unmount exit animation */
|
|
10
|
+
exit?: 'fadeOut' | 'slideOutUp' | 'slideOutDown' | 'zoomOut' | 'none'
|
|
11
|
+
/** Hover micro-interaction */
|
|
12
|
+
hover?: MicroAnimation
|
|
13
|
+
/** Active/press micro-interaction */
|
|
14
|
+
active?: 'press' | 'none'
|
|
15
|
+
/** Focus ring animation */
|
|
16
|
+
focus?: 'ring' | 'none'
|
|
17
|
+
/** Duration in ms */
|
|
18
|
+
duration?: number
|
|
19
|
+
/** Delay in ms */
|
|
20
|
+
delay?: number
|
|
21
|
+
/** Easing */
|
|
22
|
+
easing?: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const defaultOptions: Required<MotionOptions> = {
|
|
26
|
+
enter: 'fadeIn',
|
|
27
|
+
exit: 'fadeOut',
|
|
28
|
+
hover: 'none',
|
|
29
|
+
active: 'none',
|
|
30
|
+
focus: 'none',
|
|
31
|
+
duration: 250,
|
|
32
|
+
delay: 0,
|
|
33
|
+
easing: 'cubic-bezier(0.16, 1, 0.3, 1)',
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Attach motion behaviors to a DOM element.
|
|
38
|
+
* Returns controller to play enter/exit and manage state animations.
|
|
39
|
+
*/
|
|
40
|
+
export function withMotion(el: HTMLElement, options: MotionOptions = {}) {
|
|
41
|
+
const opts = { ...defaultOptions, ...options }
|
|
42
|
+
const animator = opts.enter !== 'none' ? new Animator(el) : null
|
|
43
|
+
const style = el.style
|
|
44
|
+
const originalTransition = style.transition
|
|
45
|
+
|
|
46
|
+
// Hover
|
|
47
|
+
let hoverActive = false
|
|
48
|
+
function onMouseEnter() {
|
|
49
|
+
if (opts.hover === 'none') return
|
|
50
|
+
hoverActive = true
|
|
51
|
+
applyHover(true)
|
|
52
|
+
}
|
|
53
|
+
function onMouseLeave() {
|
|
54
|
+
if (!hoverActive) return
|
|
55
|
+
hoverActive = false
|
|
56
|
+
applyHover(false)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function applyHover(active: boolean) {
|
|
60
|
+
const t = `transform ${opts.duration}ms ${opts.easing}, box-shadow ${opts.duration}ms ${opts.easing}`
|
|
61
|
+
switch (opts.hover) {
|
|
62
|
+
case 'lift':
|
|
63
|
+
style.transition = t
|
|
64
|
+
style.transform = active ? 'translateY(-2px)' : ''
|
|
65
|
+
style.boxShadow = active ? 'var(--mk-shadow-md)' : ''
|
|
66
|
+
break
|
|
67
|
+
case 'glow':
|
|
68
|
+
style.transition = `box-shadow ${opts.duration}ms ${opts.easing}`
|
|
69
|
+
style.boxShadow = active ? 'var(--mk-shadow-glow)' : ''
|
|
70
|
+
break
|
|
71
|
+
case 'scale':
|
|
72
|
+
style.transition = `transform ${opts.duration}ms ${opts.easing}`
|
|
73
|
+
style.transform = active ? 'scale(1.02)' : ''
|
|
74
|
+
break
|
|
75
|
+
case 'slideUp':
|
|
76
|
+
style.transition = t
|
|
77
|
+
style.transform = active ? 'translateY(-4px)' : ''
|
|
78
|
+
break
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Active / Press
|
|
83
|
+
function onMouseDown() {
|
|
84
|
+
if (opts.active === 'press') {
|
|
85
|
+
style.transition = `transform ${opts.duration * 0.5}ms ${opts.easing}`
|
|
86
|
+
style.transform = 'scale(0.97)'
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function onMouseUp() {
|
|
90
|
+
if (opts.active === 'press') {
|
|
91
|
+
style.transform = hoverActive ? (opts.hover === 'lift' ? 'translateY(-2px)' : opts.hover === 'scale' ? 'scale(1.02)' : '') : ''
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Focus ring
|
|
96
|
+
function onFocus() {
|
|
97
|
+
if (opts.focus === 'ring') {
|
|
98
|
+
style.outline = 'none'
|
|
99
|
+
style.boxShadow = '0 0 0 2px var(--mk-primary-muted), 0 0 0 4px var(--mk-primary)'
|
|
100
|
+
style.transition = `box-shadow ${opts.duration}ms ${opts.easing}`
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function onBlur() {
|
|
104
|
+
if (opts.focus === 'ring') {
|
|
105
|
+
style.boxShadow = ''
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Attach listeners
|
|
110
|
+
el.addEventListener('mouseenter', onMouseEnter)
|
|
111
|
+
el.addEventListener('mouseleave', onMouseLeave)
|
|
112
|
+
el.addEventListener('mousedown', onMouseDown)
|
|
113
|
+
el.addEventListener('mouseup', onMouseUp)
|
|
114
|
+
el.addEventListener('focus', onFocus)
|
|
115
|
+
el.addEventListener('blur', onBlur)
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
/** Play entrance animation */
|
|
119
|
+
async playEnter() {
|
|
120
|
+
if (!animator || opts.enter === 'none') return
|
|
121
|
+
await animator.animate(opts.enter, { duration: opts.duration, delay: opts.delay })
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
/** Play exit animation. Returns a Promise that resolves when animation completes. */
|
|
125
|
+
async playExit() {
|
|
126
|
+
if (!animator || opts.exit === 'none') return
|
|
127
|
+
await animator.animate(opts.exit, { duration: opts.duration })
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
/** Programmatically set hover state */
|
|
131
|
+
setHover(active: boolean) {
|
|
132
|
+
if (active) onMouseEnter()
|
|
133
|
+
else onMouseLeave()
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
/** Clean up all listeners and styles */
|
|
137
|
+
destroy() {
|
|
138
|
+
el.removeEventListener('mouseenter', onMouseEnter)
|
|
139
|
+
el.removeEventListener('mouseleave', onMouseLeave)
|
|
140
|
+
el.removeEventListener('mousedown', onMouseDown)
|
|
141
|
+
el.removeEventListener('mouseup', onMouseUp)
|
|
142
|
+
el.removeEventListener('focus', onFocus)
|
|
143
|
+
el.removeEventListener('blur', onBlur)
|
|
144
|
+
style.transition = originalTransition
|
|
145
|
+
style.transform = ''
|
|
146
|
+
style.boxShadow = ''
|
|
147
|
+
style.outline = ''
|
|
148
|
+
animator?.stop()
|
|
149
|
+
},
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Stagger children entrance animation.
|
|
155
|
+
*/
|
|
156
|
+
export function staggerEnter(
|
|
157
|
+
container: HTMLElement,
|
|
158
|
+
selector: string,
|
|
159
|
+
_animation?: AnimationName,
|
|
160
|
+
options?: { duration?: number; stagger?: number; delay?: number }
|
|
161
|
+
) {
|
|
162
|
+
const children = container.querySelectorAll(selector)
|
|
163
|
+
if (children.length === 0) return
|
|
164
|
+
|
|
165
|
+
const delay = options?.delay ?? 100
|
|
166
|
+
const stagger = options?.stagger ?? 80
|
|
167
|
+
const duration = options?.duration ?? 400
|
|
168
|
+
|
|
169
|
+
children.forEach((el, i) => {
|
|
170
|
+
const htmlEl = el as HTMLElement
|
|
171
|
+
htmlEl.style.opacity = '0'
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
htmlEl.style.transition = `opacity ${duration}ms ease`
|
|
174
|
+
htmlEl.style.opacity = '1'
|
|
175
|
+
}, delay + i * stagger)
|
|
176
|
+
})
|
|
177
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { AnimationOptions } from '../core/utils.ts'
|
|
2
|
+
import { Animator } from '../core/animator.ts'
|
|
3
|
+
|
|
4
|
+
function $(el: HTMLElement | string) {
|
|
5
|
+
return new Animator(el)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/* ---------- Fade ---------- */
|
|
9
|
+
export function fadeIn(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
10
|
+
return $(el).animate('fadeIn', opts)
|
|
11
|
+
}
|
|
12
|
+
export function fadeOut(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
13
|
+
return $(el).animate('fadeOut', opts)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* ---------- Slide ---------- */
|
|
17
|
+
export function slideInUp(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
18
|
+
return $(el).animate('slideInUp', opts)
|
|
19
|
+
}
|
|
20
|
+
export function slideInDown(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
21
|
+
return $(el).animate('slideInDown', opts)
|
|
22
|
+
}
|
|
23
|
+
export function slideInLeft(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
24
|
+
return $(el).animate('slideInLeft', opts)
|
|
25
|
+
}
|
|
26
|
+
export function slideInRight(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
27
|
+
return $(el).animate('slideInRight', opts)
|
|
28
|
+
}
|
|
29
|
+
export function slideOutUp(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
30
|
+
return $(el).animate('slideOutUp', opts)
|
|
31
|
+
}
|
|
32
|
+
export function slideOutDown(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
33
|
+
return $(el).animate('slideOutDown', opts)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* ---------- Zoom ---------- */
|
|
37
|
+
export function zoomIn(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
38
|
+
return $(el).animate('zoomIn', opts)
|
|
39
|
+
}
|
|
40
|
+
export function zoomOut(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
41
|
+
return $(el).animate('zoomOut', opts)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* ---------- Bounce ---------- */
|
|
45
|
+
export function bounceIn(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
46
|
+
return $(el).animate('bounceIn', opts)
|
|
47
|
+
}
|
|
48
|
+
export function bounceOut(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
49
|
+
return $(el).animate('bounceOut', opts)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* ---------- Flip ---------- */
|
|
53
|
+
export function flipInX(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
54
|
+
return $(el).animate('flipInX', opts)
|
|
55
|
+
}
|
|
56
|
+
export function flipInY(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
57
|
+
return $(el).animate('flipInY', opts)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* ---------- Misc ---------- */
|
|
61
|
+
export function shake(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
62
|
+
return $(el).animate('shake', opts)
|
|
63
|
+
}
|
|
64
|
+
export function pulse(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
65
|
+
return $(el).animate('pulse', opts)
|
|
66
|
+
}
|
|
67
|
+
export function rotateIn(el: HTMLElement | string, opts?: AnimationOptions) {
|
|
68
|
+
return $(el).animate('rotateIn', opts)
|
|
69
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { AnimationName } from '../core/utils.ts'
|
|
2
|
+
|
|
3
|
+
export interface ScrollTriggerOptions {
|
|
4
|
+
threshold?: number // 0~1,元素进入视口多少比例时触发
|
|
5
|
+
rootMargin?: string // 类似 CSS margin,扩大/缩小视口判定范围
|
|
6
|
+
once?: boolean // 是否只触发一次
|
|
7
|
+
duration?: number
|
|
8
|
+
easing?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const DEFAULT_SCROLL_OPTS: Required<ScrollTriggerOptions> = {
|
|
12
|
+
threshold: 0.2,
|
|
13
|
+
rootMargin: '0px',
|
|
14
|
+
once: true,
|
|
15
|
+
duration: 500,
|
|
16
|
+
easing: 'ease',
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class ScrollTrigger {
|
|
20
|
+
private observer: IntersectionObserver | null = null
|
|
21
|
+
private elements = new Map<Element, { name: AnimationName; opts: ScrollTriggerOptions }>()
|
|
22
|
+
|
|
23
|
+
watch(
|
|
24
|
+
selector: string | Element | Element[],
|
|
25
|
+
animationName: AnimationName,
|
|
26
|
+
options: ScrollTriggerOptions = {}
|
|
27
|
+
): this {
|
|
28
|
+
const opts = { ...DEFAULT_SCROLL_OPTS, ...options }
|
|
29
|
+
let targets: Element[]
|
|
30
|
+
if (typeof selector === 'string') {
|
|
31
|
+
targets = Array.from(document.querySelectorAll(selector))
|
|
32
|
+
} else if (Array.isArray(selector)) {
|
|
33
|
+
targets = selector
|
|
34
|
+
} else {
|
|
35
|
+
targets = [selector as Element]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!this.observer) {
|
|
39
|
+
this.observer = new IntersectionObserver(
|
|
40
|
+
(entries) => this.handleEntries(entries),
|
|
41
|
+
{
|
|
42
|
+
threshold: opts.threshold,
|
|
43
|
+
rootMargin: opts.rootMargin,
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
targets.forEach((el) => {
|
|
49
|
+
this.elements.set(el, { name: animationName, opts })
|
|
50
|
+
this.observer!.observe(el)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
return this
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private handleEntries(entries: IntersectionObserverEntry[]): void {
|
|
57
|
+
entries.forEach((entry) => {
|
|
58
|
+
if (entry.isIntersecting) {
|
|
59
|
+
const config = this.elements.get(entry.target)
|
|
60
|
+
if (!config) return
|
|
61
|
+
|
|
62
|
+
const htmlEl = entry.target as HTMLElement
|
|
63
|
+
const className = `mk-animated mk-${config.name}`
|
|
64
|
+
|
|
65
|
+
htmlEl.classList.add(...className.split(' '))
|
|
66
|
+
htmlEl.style.setProperty('--mk-duration', `${config.opts.duration}ms`)
|
|
67
|
+
htmlEl.style.setProperty('--mk-easing', config.opts.easing!)
|
|
68
|
+
|
|
69
|
+
const onEnd = (e: AnimationEvent) => {
|
|
70
|
+
if (e.animationName.startsWith('mk-')) {
|
|
71
|
+
htmlEl.removeEventListener('animationend', onEnd)
|
|
72
|
+
if (config.opts.once) {
|
|
73
|
+
htmlEl.classList.remove(...className.split(' '))
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
htmlEl.addEventListener('animationend', onEnd)
|
|
79
|
+
|
|
80
|
+
if (config.opts.once) {
|
|
81
|
+
this.observer?.unobserve(entry.target)
|
|
82
|
+
this.elements.delete(entry.target)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
destroy(): void {
|
|
89
|
+
this.observer?.disconnect()
|
|
90
|
+
this.observer = null
|
|
91
|
+
this.elements.clear()
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 快捷方法:为选择器下的所有元素添加滚动触发动画
|
|
97
|
+
*/
|
|
98
|
+
export function scrollAnimate(
|
|
99
|
+
selector: string | Element | Element[],
|
|
100
|
+
animationName: AnimationName,
|
|
101
|
+
options?: ScrollTriggerOptions
|
|
102
|
+
): ScrollTrigger {
|
|
103
|
+
return new ScrollTrigger().watch(selector, animationName, options)
|
|
104
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/* ========== Fade ========== */
|
|
2
|
+
@keyframes mk-fadeIn {
|
|
3
|
+
from { opacity: 0; }
|
|
4
|
+
to { opacity: 1; }
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
@keyframes mk-fadeOut {
|
|
8
|
+
from { opacity: 1; }
|
|
9
|
+
to { opacity: 0; }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* ========== Slide ========== */
|
|
13
|
+
@keyframes mk-slideInUp {
|
|
14
|
+
from { opacity: 0; transform: translate3d(0, 30px, 0); }
|
|
15
|
+
to { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@keyframes mk-slideInDown {
|
|
19
|
+
from { opacity: 0; transform: translate3d(0, -30px, 0); }
|
|
20
|
+
to { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@keyframes mk-slideInLeft {
|
|
24
|
+
from { opacity: 0; transform: translate3d(-30px, 0, 0); }
|
|
25
|
+
to { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@keyframes mk-slideInRight {
|
|
29
|
+
from { opacity: 0; transform: translate3d(30px, 0, 0); }
|
|
30
|
+
to { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@keyframes mk-slideOutUp {
|
|
34
|
+
from { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
35
|
+
to { opacity: 0; transform: translate3d(0, -30px, 0); }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@keyframes mk-slideOutDown {
|
|
39
|
+
from { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
40
|
+
to { opacity: 0; transform: translate3d(0, 30px, 0); }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* ========== Zoom ========== */
|
|
44
|
+
@keyframes mk-zoomIn {
|
|
45
|
+
from { opacity: 0; transform: scale3d(0.85, 0.85, 0.85); }
|
|
46
|
+
to { opacity: 1; transform: scale3d(1, 1, 1); }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@keyframes mk-zoomOut {
|
|
50
|
+
from { opacity: 1; transform: scale3d(1, 1, 1); }
|
|
51
|
+
to { opacity: 0; transform: scale3d(0.85, 0.85, 0.85); }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* ========== Bounce ========== */
|
|
55
|
+
@keyframes mk-bounceIn {
|
|
56
|
+
0% { opacity: 0; transform: scale3d(0.3, 0.3, 0.3); }
|
|
57
|
+
20% { transform: scale3d(1.1, 1.1, 1.1); }
|
|
58
|
+
40% { transform: scale3d(0.9, 0.9, 0.9); }
|
|
59
|
+
60% { opacity: 1; transform: scale3d(1.03, 1.03, 1.03); }
|
|
60
|
+
80% { transform: scale3d(0.97, 0.97, 0.97); }
|
|
61
|
+
100% { opacity: 1; transform: scale3d(1, 1, 1); }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@keyframes mk-bounceOut {
|
|
65
|
+
20% { transform: scale3d(0.9, 0.9, 0.9); }
|
|
66
|
+
50%, 55% { opacity: 1; transform: scale3d(1.1, 1.1, 1.1); }
|
|
67
|
+
100% { opacity: 0; transform: scale3d(0.3, 0.3, 0.3); }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* ========== Flip ========== */
|
|
71
|
+
@keyframes mk-flipInX {
|
|
72
|
+
from { opacity: 0; transform: perspective(400px) rotate3d(1, 0, 0, 90deg); }
|
|
73
|
+
40% { transform: perspective(400px) rotate3d(1, 0, 0, -20deg); }
|
|
74
|
+
60% { opacity: 1; transform: perspective(400px) rotate3d(1, 0, 0, 10deg); }
|
|
75
|
+
80% { transform: perspective(400px) rotate3d(1, 0, 0, -5deg); }
|
|
76
|
+
to { transform: perspective(400px); }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@keyframes mk-flipInY {
|
|
80
|
+
from { opacity: 0; transform: perspective(400px) rotate3d(0, 1, 0, 90deg); }
|
|
81
|
+
40% { transform: perspective(400px) rotate3d(0, 1, 0, -20deg); }
|
|
82
|
+
60% { opacity: 1; transform: perspective(400px) rotate3d(0, 1, 0, 10deg); }
|
|
83
|
+
80% { transform: perspective(400px) rotate3d(0, 1, 0, -5deg); }
|
|
84
|
+
to { transform: perspective(400px); }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* ========== Shake ========== */
|
|
88
|
+
@keyframes mk-shake {
|
|
89
|
+
0%, 100% { transform: translate3d(0, 0, 0); }
|
|
90
|
+
10%, 30%, 50%, 70%, 90% { transform: translate3d(-8px, 0, 0); }
|
|
91
|
+
20%, 40%, 60%, 80% { transform: translate3d(8px, 0, 0); }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* ========== Pulse ========== */
|
|
95
|
+
@keyframes mk-pulse {
|
|
96
|
+
0% { transform: scale3d(1, 1, 1); }
|
|
97
|
+
50% { transform: scale3d(1.05, 1.05, 1.05); }
|
|
98
|
+
100% { transform: scale3d(1, 1, 1); }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* ========== Rotate ========== */
|
|
102
|
+
@keyframes mk-rotateIn {
|
|
103
|
+
from { opacity: 0; transform: rotate3d(0, 0, 1, -200deg); }
|
|
104
|
+
to { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* ========== Base animation class ========== */
|
|
108
|
+
.mk-animated {
|
|
109
|
+
animation-duration: var(--mk-duration, 0.5s);
|
|
110
|
+
animation-timing-function: var(--mk-easing, ease);
|
|
111
|
+
animation-fill-mode: both;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.mk-animated.mk-infinite {
|
|
115
|
+
animation-iteration-count: infinite;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* ========== Animation presets ========== */
|
|
119
|
+
.mk-fadeIn { animation-name: mk-fadeIn; }
|
|
120
|
+
.mk-fadeOut { animation-name: mk-fadeOut; }
|
|
121
|
+
.mk-slideInUp { animation-name: mk-slideInUp; }
|
|
122
|
+
.mk-slideInDown { animation-name: mk-slideInDown; }
|
|
123
|
+
.mk-slideInLeft { animation-name: mk-slideInLeft; }
|
|
124
|
+
.mk-slideInRight { animation-name: mk-slideInRight; }
|
|
125
|
+
.mk-slideOutUp { animation-name: mk-slideOutUp; }
|
|
126
|
+
.mk-slideOutDown { animation-name: mk-slideOutDown; }
|
|
127
|
+
.mk-zoomIn { animation-name: mk-zoomIn; }
|
|
128
|
+
.mk-zoomOut { animation-name: mk-zoomOut; }
|
|
129
|
+
.mk-bounceIn { animation-name: mk-bounceIn; }
|
|
130
|
+
.mk-bounceOut { animation-name: mk-bounceOut; }
|
|
131
|
+
.mk-flipInX { animation-name: mk-flipInX; }
|
|
132
|
+
.mk-flipInY { animation-name: mk-flipInY; }
|
|
133
|
+
.mk-shake { animation-name: mk-shake; }
|
|
134
|
+
.mk-pulse { animation-name: mk-pulse; }
|
|
135
|
+
.mk-rotateIn { animation-name: mk-rotateIn; }
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/* ========== Element Plus 风格动画 ========== */
|
|
2
|
+
|
|
3
|
+
/* ----- Fade ----- */
|
|
4
|
+
@keyframes mk-fadeIn {
|
|
5
|
+
from { opacity: 0; }
|
|
6
|
+
to { opacity: 1; }
|
|
7
|
+
}
|
|
8
|
+
@keyframes mk-fadeOut {
|
|
9
|
+
from { opacity: 1; }
|
|
10
|
+
to { opacity: 0; }
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@keyframes mk-fadeInLinear {
|
|
14
|
+
from { opacity: 0; }
|
|
15
|
+
to { opacity: 1; }
|
|
16
|
+
}
|
|
17
|
+
@keyframes mk-fadeOutLinear {
|
|
18
|
+
from { opacity: 1; }
|
|
19
|
+
to { opacity: 0; }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@keyframes mk-fadeInUp {
|
|
23
|
+
from { opacity: 0; transform: translate3d(0, 20px, 0); }
|
|
24
|
+
to { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
25
|
+
}
|
|
26
|
+
@keyframes mk-fadeOutUp {
|
|
27
|
+
from { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
28
|
+
to { opacity: 0; transform: translate3d(0, -20px, 0); }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@keyframes mk-fadeInDown {
|
|
32
|
+
from { opacity: 0; transform: translate3d(0, -20px, 0); }
|
|
33
|
+
to { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
34
|
+
}
|
|
35
|
+
@keyframes mk-fadeOutDown {
|
|
36
|
+
from { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
37
|
+
to { opacity: 0; transform: translate3d(0, 20px, 0); }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@keyframes mk-fadeInLeft {
|
|
41
|
+
from { opacity: 0; transform: translate3d(20px, 0, 0); }
|
|
42
|
+
to { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
43
|
+
}
|
|
44
|
+
@keyframes mk-fadeOutLeft {
|
|
45
|
+
from { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
46
|
+
to { opacity: 0; transform: translate3d(-20px, 0, 0); }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@keyframes mk-fadeInRight {
|
|
50
|
+
from { opacity: 0; transform: translate3d(-20px, 0, 0); }
|
|
51
|
+
to { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
52
|
+
}
|
|
53
|
+
@keyframes mk-fadeOutRight {
|
|
54
|
+
from { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
55
|
+
to { opacity: 0; transform: translate3d(20px, 0, 0); }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* ----- Zoom ----- */
|
|
59
|
+
@keyframes mk-zoomInCenter {
|
|
60
|
+
from { opacity: 0; transform: scale3d(0.7, 0.7, 0.7); }
|
|
61
|
+
to { opacity: 1; transform: scale3d(1, 1, 1); }
|
|
62
|
+
}
|
|
63
|
+
@keyframes mk-zoomOutCenter {
|
|
64
|
+
from { opacity: 1; transform: scale3d(1, 1, 1); }
|
|
65
|
+
to { opacity: 0; transform: scale3d(0.7, 0.7, 0.7); }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@keyframes mk-zoomInTop {
|
|
69
|
+
from { opacity: 0; transform: scale3d(0.7, 0.7, 0.7); transform-origin: center top; }
|
|
70
|
+
to { opacity: 1; transform: scale3d(1, 1, 1); transform-origin: center top; }
|
|
71
|
+
}
|
|
72
|
+
@keyframes mk-zoomOutTop {
|
|
73
|
+
from { opacity: 1; transform: scale3d(1, 1, 1); transform-origin: center top; }
|
|
74
|
+
to { opacity: 0; transform: scale3d(0.7, 0.7, 0.7); transform-origin: center top; }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@keyframes mk-zoomInBottom {
|
|
78
|
+
from { opacity: 0; transform: scale3d(0.7, 0.7, 0.7); transform-origin: center bottom; }
|
|
79
|
+
to { opacity: 1; transform: scale3d(1, 1, 1); transform-origin: center bottom; }
|
|
80
|
+
}
|
|
81
|
+
@keyframes mk-zoomOutBottom {
|
|
82
|
+
from { opacity: 1; transform: scale3d(1, 1, 1); transform-origin: center bottom; }
|
|
83
|
+
to { opacity: 0; transform: scale3d(0.7, 0.7, 0.7); transform-origin: center bottom; }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* ----- Slide (for Drawer / Modal) ----- */
|
|
87
|
+
@keyframes mk-slideInRight {
|
|
88
|
+
from { transform: translate3d(100%, 0, 0); }
|
|
89
|
+
to { transform: translate3d(0, 0, 0); }
|
|
90
|
+
}
|
|
91
|
+
@keyframes mk-slideOutRight {
|
|
92
|
+
from { transform: translate3d(0, 0, 0); }
|
|
93
|
+
to { transform: translate3d(100%, 0, 0); }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@keyframes mk-slideInLeft {
|
|
97
|
+
from { transform: translate3d(-100%, 0, 0); }
|
|
98
|
+
to { transform: translate3d(0, 0, 0); }
|
|
99
|
+
}
|
|
100
|
+
@keyframes mk-slideOutLeft {
|
|
101
|
+
from { transform: translate3d(0, 0, 0); }
|
|
102
|
+
to { transform: translate3d(-100%, 0, 0); }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@keyframes mk-slideInTop {
|
|
106
|
+
from { transform: translate3d(0, -100%, 0); }
|
|
107
|
+
to { transform: translate3d(0, 0, 0); }
|
|
108
|
+
}
|
|
109
|
+
@keyframes mk-slideOutTop {
|
|
110
|
+
from { transform: translate3d(0, 0, 0); }
|
|
111
|
+
to { transform: translate3d(0, -100%, 0); }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@keyframes mk-slideInBottom {
|
|
115
|
+
from { transform: translate3d(0, 100%, 0); }
|
|
116
|
+
to { transform: translate3d(0, 0, 0); }
|
|
117
|
+
}
|
|
118
|
+
@keyframes mk-slideOutBottom {
|
|
119
|
+
from { transform: translate3d(0, 0, 0); }
|
|
120
|
+
to { transform: translate3d(0, 100%, 0); }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* ----- List stagger ----- */
|
|
124
|
+
@keyframes mk-listItemIn {
|
|
125
|
+
from { opacity: 0; transform: translate3d(0, 16px, 0); }
|
|
126
|
+
to { opacity: 1; transform: translate3d(0, 0, 0); }
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* ----- Spinner ----- */
|
|
130
|
+
@keyframes mk-spin {
|
|
131
|
+
from { transform: rotate(0deg); }
|
|
132
|
+
to { transform: rotate(360deg); }
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* ----- Base class ----- */
|
|
136
|
+
.mk-transition {
|
|
137
|
+
animation-duration: var(--mk-duration, 0.3s);
|
|
138
|
+
animation-timing-function: var(--mk-easing, ease-in-out);
|
|
139
|
+
animation-fill-mode: both;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* ----- Preset classes ----- */
|
|
143
|
+
.mk-fade-in { animation-name: mk-fadeIn; }
|
|
144
|
+
.mk-fade-out { animation-name: mk-fadeOut; }
|
|
145
|
+
.mk-fade-in-linear { animation-name: mk-fadeInLinear; }
|
|
146
|
+
.mk-fade-out-linear { animation-name: mk-fadeOutLinear; }
|
|
147
|
+
.mk-fade-in-up { animation-name: mk-fadeInUp; }
|
|
148
|
+
.mk-fade-out-up { animation-name: mk-fadeOutUp; }
|
|
149
|
+
.mk-fade-in-down { animation-name: mk-fadeInDown; }
|
|
150
|
+
.mk-fade-out-down { animation-name: mk-fadeOutDown; }
|
|
151
|
+
.mk-fade-in-left { animation-name: mk-fadeInLeft; }
|
|
152
|
+
.mk-fade-out-left { animation-name: mk-fadeOutLeft; }
|
|
153
|
+
.mk-fade-in-right { animation-name: mk-fadeInRight; }
|
|
154
|
+
.mk-fade-out-right { animation-name: mk-fadeOutRight; }
|
|
155
|
+
|
|
156
|
+
.mk-zoom-in-center { animation-name: mk-zoomInCenter; }
|
|
157
|
+
.mk-zoom-out-center { animation-name: mk-zoomOutCenter; }
|
|
158
|
+
.mk-zoom-in-top { animation-name: mk-zoomInTop; }
|
|
159
|
+
.mk-zoom-out-top { animation-name: mk-zoomOutTop; }
|
|
160
|
+
.mk-zoom-in-bottom { animation-name: mk-zoomInBottom; }
|
|
161
|
+
.mk-zoom-out-bottom { animation-name: mk-zoomOutBottom; }
|
|
162
|
+
|
|
163
|
+
.mk-slide-in-right { animation-name: mk-slideInRight; }
|
|
164
|
+
.mk-slide-out-right { animation-name: mk-slideOutRight; }
|
|
165
|
+
.mk-slide-in-left { animation-name: mk-slideInLeft; }
|
|
166
|
+
.mk-slide-out-left { animation-name: mk-slideOutLeft; }
|
|
167
|
+
.mk-slide-in-top { animation-name: mk-slideInTop; }
|
|
168
|
+
.mk-slide-out-top { animation-name: mk-slideOutTop; }
|
|
169
|
+
.mk-slide-in-bottom { animation-name: mk-slideInBottom; }
|
|
170
|
+
.mk-slide-out-bottom { animation-name: mk-slideOutBottom; }
|
|
171
|
+
|
|
172
|
+
.mk-list-item-in { animation-name: mk-listItemIn; }
|
|
173
|
+
|
|
174
|
+
.mk-spin { animation: mk-spin 1s linear infinite; }
|