@arcblock/ux 1.17.10 → 1.17.13
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.
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import Lottie from 'react-lottie-player';
|
|
5
|
+
import lottieJson from './default-animation.json';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 用于长时间等待的用的动画组件
|
|
9
|
+
* 动画会随着时间的变化而逐步加快播放速度,好适应用户的等待心理
|
|
10
|
+
* @param {Object} animationData lottie json 动画数据
|
|
11
|
+
* @param {Number} size 动画的尺寸,单位px
|
|
12
|
+
* @param {String|Array} message 动画下方的文字;数组情况下会在一定时间切换文案
|
|
13
|
+
* @param {Number} messageDuration 动画下方的文字为数组时,每个文案的持续时间;默认5000ms
|
|
14
|
+
* @param {Array} tips 底部的提示元素
|
|
15
|
+
* @param {Number} tipsDuration 底部提示的切换时间,单位毫秒,默认3000ms
|
|
16
|
+
* @param {Number} speed 动画默认的播放速度
|
|
17
|
+
* @param {Number} maybeDuration 整个动画大概的持续时间,单位毫秒,用于计算增量下的动画速度,默认两分钟(120000ms)
|
|
18
|
+
* @param {Number} increaseSpeed 在 maybeDuration 时间下增加的速度,默认为0(不增加速度)
|
|
19
|
+
* @returns element
|
|
20
|
+
*/
|
|
21
|
+
export default function AnimationWaiter({
|
|
22
|
+
animationData,
|
|
23
|
+
size,
|
|
24
|
+
message,
|
|
25
|
+
messageDuration,
|
|
26
|
+
tips,
|
|
27
|
+
tipsDuration,
|
|
28
|
+
maybeDuration,
|
|
29
|
+
speed,
|
|
30
|
+
increaseSpeed,
|
|
31
|
+
...rest
|
|
32
|
+
}) {
|
|
33
|
+
const [tipsId, setTipsId] = useState(0);
|
|
34
|
+
const [currentSpeed, setCurrentSpeed] = useState(speed);
|
|
35
|
+
const [desc, setDesc] = useState('');
|
|
36
|
+
// 动画的开始时间
|
|
37
|
+
const startTime = useRef(new Date().getTime());
|
|
38
|
+
|
|
39
|
+
// 省略号
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (!message) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let timer1;
|
|
46
|
+
let msgId = 0;
|
|
47
|
+
|
|
48
|
+
if (Array.isArray(message)) {
|
|
49
|
+
setDesc(message[msgId]);
|
|
50
|
+
timer1 = setInterval(() => {
|
|
51
|
+
msgId++;
|
|
52
|
+
if (msgId >= message.length) {
|
|
53
|
+
msgId = 0;
|
|
54
|
+
}
|
|
55
|
+
setDesc(message[msgId]);
|
|
56
|
+
}, messageDuration);
|
|
57
|
+
} else {
|
|
58
|
+
setDesc(message);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// eslint-disable-next-line consistent-return
|
|
62
|
+
return () => {
|
|
63
|
+
clearInterval(timer1);
|
|
64
|
+
};
|
|
65
|
+
}, [message, messageDuration]);
|
|
66
|
+
|
|
67
|
+
// tips
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (!tips.length) {
|
|
70
|
+
return () => {};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const timer = setTimeout(() => {
|
|
74
|
+
let nextId = tipsId + 1;
|
|
75
|
+
|
|
76
|
+
if (nextId >= tips.length) {
|
|
77
|
+
nextId = 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
setTipsId(nextId);
|
|
81
|
+
}, tipsDuration);
|
|
82
|
+
|
|
83
|
+
return () => clearTimeout(timer);
|
|
84
|
+
}, [tips, tipsDuration, tipsId]);
|
|
85
|
+
|
|
86
|
+
// 动画speed
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
const timer = setTimeout(() => {
|
|
89
|
+
const diffTime = new Date().getTime() - startTime.current;
|
|
90
|
+
|
|
91
|
+
let percentage = diffTime / maybeDuration;
|
|
92
|
+
if (percentage > 1) {
|
|
93
|
+
percentage = 1;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const newSpeed = speed + increaseSpeed * percentage;
|
|
97
|
+
|
|
98
|
+
setCurrentSpeed(newSpeed);
|
|
99
|
+
}, 1000);
|
|
100
|
+
|
|
101
|
+
return () => clearTimeout(timer);
|
|
102
|
+
}, [currentSpeed]);
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<Container {...rest}>
|
|
106
|
+
<Lottie
|
|
107
|
+
loop
|
|
108
|
+
animationData={animationData || lottieJson}
|
|
109
|
+
play
|
|
110
|
+
speed={currentSpeed}
|
|
111
|
+
style={{
|
|
112
|
+
width: size,
|
|
113
|
+
height: size,
|
|
114
|
+
}}
|
|
115
|
+
/>
|
|
116
|
+
{message && (
|
|
117
|
+
<div className="waiter-message">
|
|
118
|
+
{desc}
|
|
119
|
+
<span className="waiter-loading" />
|
|
120
|
+
</div>
|
|
121
|
+
)}
|
|
122
|
+
|
|
123
|
+
{tips.length ? (
|
|
124
|
+
<div className="waiter-tips-container">
|
|
125
|
+
{tips.map((e, index) => {
|
|
126
|
+
return (
|
|
127
|
+
<div
|
|
128
|
+
className={`waiter-tips-block ${tipsId === index ? 'show-tips' : ''}`}
|
|
129
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
130
|
+
key={index}>
|
|
131
|
+
{e}
|
|
132
|
+
</div>
|
|
133
|
+
);
|
|
134
|
+
})}
|
|
135
|
+
</div>
|
|
136
|
+
) : (
|
|
137
|
+
''
|
|
138
|
+
)}
|
|
139
|
+
</Container>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
AnimationWaiter.propTypes = {
|
|
144
|
+
animationData: PropTypes.any,
|
|
145
|
+
size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
146
|
+
message: PropTypes.any,
|
|
147
|
+
messageDuration: PropTypes.number,
|
|
148
|
+
tips: PropTypes.array,
|
|
149
|
+
tipsDuration: PropTypes.number,
|
|
150
|
+
speed: PropTypes.number,
|
|
151
|
+
maybeDuration: PropTypes.number,
|
|
152
|
+
increaseSpeed: PropTypes.number,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
AnimationWaiter.defaultProps = {
|
|
156
|
+
animationData: null,
|
|
157
|
+
size: '',
|
|
158
|
+
message: '',
|
|
159
|
+
messageDuration: 5000,
|
|
160
|
+
tips: [],
|
|
161
|
+
tipsDuration: 5000,
|
|
162
|
+
speed: 1,
|
|
163
|
+
maybeDuration: 120000,
|
|
164
|
+
increaseSpeed: 0,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const Container = styled.div`
|
|
168
|
+
display: flex;
|
|
169
|
+
justify-content: center;
|
|
170
|
+
align-items: center;
|
|
171
|
+
flex-direction: column;
|
|
172
|
+
width: 100%;
|
|
173
|
+
height: 100%;
|
|
174
|
+
|
|
175
|
+
.waiter-message {
|
|
176
|
+
font-weight: 700;
|
|
177
|
+
font-size: 18px;
|
|
178
|
+
line-height: 22px;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.waiter-tips-container {
|
|
182
|
+
position: relative;
|
|
183
|
+
margin-top: auto;
|
|
184
|
+
width: 100%;
|
|
185
|
+
.waiter-tips-block {
|
|
186
|
+
position: absolute;
|
|
187
|
+
bottom: 0;
|
|
188
|
+
left: 0;
|
|
189
|
+
width: 100%;
|
|
190
|
+
opacity: 0;
|
|
191
|
+
pointer-events: none;
|
|
192
|
+
z-index: 1;
|
|
193
|
+
transform: translate(-20px, 0);
|
|
194
|
+
transition: all ease 0.4s;
|
|
195
|
+
&.show-tips {
|
|
196
|
+
opacity: 1;
|
|
197
|
+
pointer-events: auto;
|
|
198
|
+
z-index: 2;
|
|
199
|
+
transform: translate(0, 0);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.waiter-loading::after {
|
|
205
|
+
display: inline-block;
|
|
206
|
+
animation: dotty steps(1, end) 2s infinite;
|
|
207
|
+
content: '';
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
@keyframes dotty {
|
|
211
|
+
0% {
|
|
212
|
+
content: '';
|
|
213
|
+
}
|
|
214
|
+
25% {
|
|
215
|
+
content: '.';
|
|
216
|
+
}
|
|
217
|
+
50% {
|
|
218
|
+
content: '..';
|
|
219
|
+
}
|
|
220
|
+
75% {
|
|
221
|
+
content: '...';
|
|
222
|
+
}
|
|
223
|
+
100% {
|
|
224
|
+
content: '';
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
`;
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ActionButton from './ActionButton';
|
|
2
2
|
import ActivityIndicator from './ActivityIndicator';
|
|
3
3
|
import Alert from './Alert';
|
|
4
|
+
import AnimationWaiter from './AnimationWaiter';
|
|
4
5
|
import Async from './Async';
|
|
5
6
|
import Badge from './Badge';
|
|
6
7
|
import Button from './Button';
|
|
@@ -33,6 +34,7 @@ export {
|
|
|
33
34
|
ActionButton,
|
|
34
35
|
ActivityIndicator,
|
|
35
36
|
Alert,
|
|
37
|
+
AnimationWaiter,
|
|
36
38
|
Async,
|
|
37
39
|
Badge,
|
|
38
40
|
Button,
|