FTXUI 6.1.9
C++ functional terminal UI.
载入中...
搜索中...
未找到
animation.cpp
浏览该文件的文档.
1#include <cmath> // for sin, pow, sqrt, cos
2#include <utility> // for move
3
5
6// NOLINTBEGIN(*-magic-numbers)
7namespace ftxui::animation {
8
9namespace easing {
10
11namespace {
12constexpr float kPi = 3.14159265358979323846f;
13constexpr float kPi2 = kPi / 2.f;
14} // namespace
15
16// 缓动函数取自:
17// https://github.com/warrenm/AHEasing/blob/master/AHEasing/easing.c
18//
19// 相应的许可证:
20// Copyright (c) 2011, Auerhaus Development, LLC
21//
22// 本程序是免费软件。在适用法律允许的范围内,它不带任何担保。您可以根据 Sam Hocevar 发布
23// 的“随你所欲公共许可证”第 2 版的条款重新分发和/或修改它。有关详细信息,请参阅
24// http://sam.zoy.org/wtfpl/COPYING。
25
26/// @brief 模仿直线 y = x
27float Linear(float p) {
28 return p;
29}
30
31/// @brief 模仿抛物线 y = x^2
32float QuadraticIn(float p) {
33 return p * p;
34}
35
36// @brief 模仿抛物线 y = -x^2 + 2x
37float QuadraticOut(float p) {
38 return -(p * (p - 2.f));
39}
40
41// @brief 模仿分段二次函数
42// y = (1/2)((2x)^2) ; [0, 0.5)
43// y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1]
44float QuadraticInOut(float p) {
45 return p < 0.5f ? 2.f * p * p : (-2.f * p * p) + (4.f * p) - 1.f;
46}
47
48// @brief 模仿三次函数 y = x^3
49float CubicIn(float p) {
50 return p * p * p;
51}
52
53// @brief 模仿三次函数 y = (x - 1)^3 + 1
54float CubicOut(float p) {
55 const float f = (p - 1.f);
56 return f * f * f + 1.f;
57}
58
59// @brief 模仿分段三次函数
60// y = (1/2)((2x)^3) ; [0, 0.5)
61// y = (1/2)((2x-2)^3 + 2) ; [0.5, 1]
62float CubicInOut(float p) {
63 if (p < 0.5f) {
64 return 4.f * p * p * p;
65 }
66 const float f = ((2.f * p) - 2.f);
67 return 0.5f * f * f * f + 1.f;
68}
69
70// @brief 模仿四次函数 x^4
71float QuarticIn(float p) {
72 return p * p * p * p;
73}
74
75// @brief 模仿四次函数 y = 1 - (x - 1)^4
76float QuarticOut(float p) {
77 const float f = (p - 1.f);
78 return f * f * f * (1.f - p) + 1.f;
79}
80
81// @brief 模仿分段四次函数
82// y = (1/2)((2x)^4) ; [0, 0.5)
83// y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1]
84float QuarticInOut(float p) {
85 if (p < 0.5f) {
86 return 8.f * p * p * p * p;
87 }
88 const float f = (p - 1.f);
89 return -8.f * f * f * f * f + 1.f;
90}
91
92// @brief 模仿五次函数 y = x^5
93float QuinticIn(float p) {
94 return p * p * p * p * p;
95}
96
97// @brief 模仿五次函数 y = (x - 1)^5 + 1
98float QuinticOut(float p) {
99 const float f = (p - 1.f);
100 return f * f * f * f * f + 1.f;
101}
102
103// @brief 模仿分段五次函数
104// y = (1/2)((2x)^5) ; [0, 0.5)
105// y = (1/2)((2x-2)^5 + 2) ; [0.5, 1]
106float QuinticInOut(float p) {
107 if (p < 0.5f) {
108 return 16.f * p * p * p * p * p;
109 }
110 const float f = ((2.f * p) - 2.f);
111 return 0.5f * f * f * f * f * f + 1.f;
112}
113
114// @brief 模仿四分之一周期的正弦波
115float SineIn(float p) {
116 return std::sin((p - 1.f) * kPi2) + 1.f;
117}
118
119// @brief 模仿四分之一周期的正弦波(不同相位)
120float SineOut(float p) {
121 return std::sin(p * kPi2);
122}
123
124// @brief 模仿半个正弦波
125float SineInOut(float p) {
126 return 0.5f * (1.f - std::cos(p * kPi));
127}
128
129// @brief 模仿单位圆的第四象限偏移
130float CircularIn(float p) {
131 return 1.f - std::sqrt(1.f - (p * p));
132}
133
134// @brief 模仿单位圆的第二象限偏移
135float CircularOut(float p) {
136 return std::sqrt((2.f - p) * p);
137}
138
139// @brief 模仿分段圆函数
140// y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5)
141// y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1]
142float CircularInOut(float p) {
143 if (p < 0.5f) {
144 return 0.5f * (1.f - std::sqrt(1.f - 4.f * (p * p)));
145 }
146 return 0.5f * (std::sqrt(-((2.f * p) - 3.f) * ((2.f * p) - 1.f)) + 1.f);
147}
148
149// @brief 模仿指数函数 y = 2^(10(x - 1))
150float ExponentialIn(float p) {
151 return (p == 0.f) ? p : std::pow(2.f, 10.f * (p - 1.f));
152}
153
154// @brief 模仿指数函数 y = -2^(-10x) + 1
155float ExponentialOut(float p) {
156 return (p == 1.f) ? p : 1.f - std::pow(2.f, -10.f * p);
157}
158
159// @brief 模仿分段指数函数
160// y = (1/2)2^(10(2x - 1)) ; [0,0.5)
161// y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1]
162float ExponentialInOut(float p) {
163 if (p == 0.f || p == 1.f) {
164 return p;
165 }
166
167 if (p < 0.5f) {
168 return 0.5f * std::pow(2.f, (20.f * p) - 10.f);
169 }
170 return -0.5f * std::pow(2.f, (-20.f * p) + 10.f) + 1.f;
171}
172
173// @brief 模仿阻尼正弦波 y = sin(13pi/2*x)*pow(2, 10 * (x - 1))
174float ElasticIn(float p) {
175 return std::sin(13.f * kPi2 * p) * std::pow(2.f, 10.f * (p - 1.f));
176}
177
178// @brief 模仿阻尼正弦波 y = sin(-13pi/2*(x + 1))*pow(2, -10x) + 1
179float ElasticOut(float p) {
180 return std::sin(-13.f * kPi2 * (p + 1.f)) * std::pow(2.f, -10.f * p) + 1.f;
181}
182
183// @brief 模仿分段指数阻尼正弦波:
184// y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5)
185// y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1]
186float ElasticInOut(float p) {
187 if (p < 0.5f) {
188 return 0.5f * std::sin(13.f * kPi2 * (2.f * p)) *
189 std::pow(2.f, 10.f * ((2.f * p) - 1.f));
190 }
191 return 0.5f * (std::sin(-13.f * kPi2 * ((2.f * p - 1.f) + 1.f)) *
192 std::pow(2.f, -10.f * (2.f * p - 1.f)) +
193 2.f);
194}
195
196// @brief 模仿过冲三次函数 y = x^3-x*sin(x*pi)
197float BackIn(float p) {
198 return p * p * p - p * std::sin(p * kPi);
199}
200
201// @brief 模仿过冲三次函数 y = 1-((1-x)^3-(1-x)*sin((1-x)*pi))
202float BackOut(float p) {
203 const float f = (1.f - p);
204 return 1.f - (f * f * f - f * std::sin(f * kPi));
205}
206
207// @brief 模仿分段过冲三次函数:
208// y = (1/2)*((2x)^3-(2x)*sin(2*x*pi)) ; [0, 0.5)
209// y = (1/2)*(1-((1-x)^3-(1-x)*sin((1-x)*pi))+1) ; [0.5, 1]
210float BackInOut(float p) {
211 if (p < 0.5f) {
212 const float f = 2.f * p;
213 return 0.5f * (f * f * f - f * std::sin(f * kPi));
214 }
215 const float f = (1.f - (2.f * p - 1.f));
216 return 0.5f * (1.f - (f * f * f - f * std::sin(f * kPi))) + 0.5f;
217}
218
219float BounceIn(float p) {
220 return 1.f - BounceOut(1.f - p);
221}
222
223float BounceOut(float p) {
224 if (p < 4.f / 11.f) {
225 return (121.f * p * p) / 16.f;
226 }
227
228 if (p < 8.f / 11.f) {
229 return (363.f / 40.f * p * p) - (99.f / 10.f * p) + 17.f / 5.f;
230 }
231
232 if (p < 9.f / 10.f) {
233 return (4356.f / 361.f * p * p) - (35442.f / 1805.f * p) + 16061.f / 1805.f;
234 }
235
236 return (54.f / 5.f * p * p) - (513 / 25.f * p) + 268 / 25.f;
237}
238
239float BounceInOut(float p) {
240 if (p < 0.5f) {
241 return 0.5f * BounceIn(p * 2.f);
242 }
243 return 0.5f * BounceOut(p * 2.f - 1.f) + 0.5f;
244}
245
246} // namespace easing
247
249 float to,
250 Duration duration,
251 easing::Function easing_function,
252 Duration delay)
253 : value_(from),
254 from_(*from),
255 to_(to),
256 duration_(duration),
257 easing_function_(std::move(easing_function)),
258 current_(-delay) {
260}
261
263 current_ += params.duration();
264
265 if (current_ >= duration_) {
266 *value_ = to_;
267 return;
268 }
269
270 if (current_ <= Duration()) {
271 *value_ = from_;
272 } else {
273 *value_ = from_ + (to_ - from_) * easing_function_(current_ / duration_);
274 }
275
277}
278
279} // namespace ftxui::animation
280
281// NOLINTEND(*-magic-numbers)
Animator(float *from, float to=0.f, Duration duration=std::chrono::milliseconds(250), easing::Function easing_function=easing::Linear, Duration delay=std::chrono::milliseconds(0))
Duration duration() const
此动画步骤表示的持续时间。
void RequestAnimationFrame()
RequestAnimationFrame 是一个请求在下一个动画周期中绘制新帧的函数。
FTXUI ftxui::animation::easing:: 命名空间
float Linear(float p)
模仿直线 y = x
float QuadraticIn(float p)
模仿抛物线 y = x^2
std::function< float(float)> Function
FTXUI ftxui::animation:: 命名空间
std::chrono::duration< float > Duration
std::string value_