@plotdb/lotion 0.1.0
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/CHANGELOG.md +27 -0
- package/LICENSE +21 -0
- package/README.md +190 -0
- package/audio/beats.py +93 -0
- package/audio/bgm.py +181 -0
- package/audio/common.py +30 -0
- package/audio/mix.py +51 -0
- package/audio/sfx.py +93 -0
- package/block/player.js +16 -0
- package/cli.js +390 -0
- package/index.css +191 -0
- package/index.js +437 -0
- package/index.min.css +1 -0
- package/index.min.js +1 -0
- package/package.json +1 -0
- package/prompt/explainer.md +71 -0
- package/prompt/ui-loop.md +497 -0
package/index.css
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
.lotion {
|
|
2
|
+
--lotion-bg: #eceae5;
|
|
3
|
+
--lotion-paper: #fbfaf7;
|
|
4
|
+
--lotion-ink: #18181a;
|
|
5
|
+
--lotion-mute: #8a877f;
|
|
6
|
+
--lotion-line: #d9d6cf;
|
|
7
|
+
position: relative;
|
|
8
|
+
border: 1px solid var(--lotion-line);
|
|
9
|
+
border-radius: 12px;
|
|
10
|
+
overflow: hidden;
|
|
11
|
+
outline: none;
|
|
12
|
+
}
|
|
13
|
+
.lotion .lotion-viewport {
|
|
14
|
+
position: relative;
|
|
15
|
+
width: 100%;
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
background: var(--lotion-bg);
|
|
18
|
+
}
|
|
19
|
+
.lotion .lotion-stage {
|
|
20
|
+
position: absolute;
|
|
21
|
+
left: 0;
|
|
22
|
+
top: 0;
|
|
23
|
+
transform-origin: 0 0;
|
|
24
|
+
background: var(--lotion-bg);
|
|
25
|
+
overflow: hidden;
|
|
26
|
+
line-height: normal;
|
|
27
|
+
}
|
|
28
|
+
.lotion .lotion-bar {
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
gap: 18px;
|
|
32
|
+
height: 64px;
|
|
33
|
+
padding: 0 24px;
|
|
34
|
+
background: var(--lotion-paper);
|
|
35
|
+
border-top: 1px solid var(--lotion-line);
|
|
36
|
+
user-select: none;
|
|
37
|
+
}
|
|
38
|
+
.lotion .lotion-btn {
|
|
39
|
+
flex: none;
|
|
40
|
+
width: 40px;
|
|
41
|
+
height: 40px;
|
|
42
|
+
border-radius: 50%;
|
|
43
|
+
background: var(--lotion-ink);
|
|
44
|
+
color: #fff;
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
cursor: pointer;
|
|
49
|
+
}
|
|
50
|
+
.lotion .lotion-play:before {
|
|
51
|
+
content: "";
|
|
52
|
+
margin-left: 3px;
|
|
53
|
+
border-style: solid;
|
|
54
|
+
border-width: 7px 0 7px 12px;
|
|
55
|
+
border-color: transparent transparent transparent #fff;
|
|
56
|
+
}
|
|
57
|
+
.lotion.lotion-playing .lotion-play:before {
|
|
58
|
+
margin-left: 0;
|
|
59
|
+
width: 4px;
|
|
60
|
+
height: 14px;
|
|
61
|
+
border-width: 0 4px;
|
|
62
|
+
border-color: #fff;
|
|
63
|
+
}
|
|
64
|
+
.lotion .lotion-fs {
|
|
65
|
+
background: transparent;
|
|
66
|
+
color: var(--lotion-ink);
|
|
67
|
+
border: 1px solid var(--lotion-line);
|
|
68
|
+
}
|
|
69
|
+
.lotion .lotion-time {
|
|
70
|
+
font: 15px/1 sans-serif;
|
|
71
|
+
color: var(--lotion-mute);
|
|
72
|
+
font-variant-numeric: tabular-nums;
|
|
73
|
+
white-space: nowrap;
|
|
74
|
+
}
|
|
75
|
+
.lotion .lotion-track {
|
|
76
|
+
position: relative;
|
|
77
|
+
flex: 1;
|
|
78
|
+
height: 40px;
|
|
79
|
+
cursor: pointer;
|
|
80
|
+
}
|
|
81
|
+
.lotion .lotion-rail,
|
|
82
|
+
.lotion .lotion-fill {
|
|
83
|
+
position: absolute;
|
|
84
|
+
left: 0;
|
|
85
|
+
top: 18px;
|
|
86
|
+
height: 4px;
|
|
87
|
+
border-radius: 2px;
|
|
88
|
+
}
|
|
89
|
+
.lotion .lotion-rail {
|
|
90
|
+
right: 0;
|
|
91
|
+
background: var(--lotion-line);
|
|
92
|
+
}
|
|
93
|
+
.lotion .lotion-fill {
|
|
94
|
+
background: var(--lotion-ink);
|
|
95
|
+
}
|
|
96
|
+
.lotion .lotion-knob {
|
|
97
|
+
position: absolute;
|
|
98
|
+
top: 13px;
|
|
99
|
+
width: 14px;
|
|
100
|
+
height: 14px;
|
|
101
|
+
margin-left: -7px;
|
|
102
|
+
border-radius: 50%;
|
|
103
|
+
background: var(--lotion-ink);
|
|
104
|
+
}
|
|
105
|
+
.lotion .lotion-chapters {
|
|
106
|
+
position: absolute;
|
|
107
|
+
inset: 0;
|
|
108
|
+
pointer-events: none;
|
|
109
|
+
}
|
|
110
|
+
.lotion .lotion-ch {
|
|
111
|
+
position: absolute;
|
|
112
|
+
top: 14px;
|
|
113
|
+
width: 2px;
|
|
114
|
+
height: 12px;
|
|
115
|
+
margin-left: -1px;
|
|
116
|
+
border-radius: 1px;
|
|
117
|
+
background: var(--lotion-mute);
|
|
118
|
+
opacity: 0.5;
|
|
119
|
+
}
|
|
120
|
+
.lotion.lotion-loading .lotion-stage {
|
|
121
|
+
visibility: hidden;
|
|
122
|
+
}
|
|
123
|
+
.lotion.lotion-loading .lotion-bar {
|
|
124
|
+
opacity: 0.5;
|
|
125
|
+
pointer-events: none;
|
|
126
|
+
}
|
|
127
|
+
.lotion .lotion-loading-screen {
|
|
128
|
+
position: absolute;
|
|
129
|
+
inset: 0;
|
|
130
|
+
display: flex;
|
|
131
|
+
align-items: center;
|
|
132
|
+
justify-content: center;
|
|
133
|
+
background: var(--lotion-bg);
|
|
134
|
+
color: var(--lotion-mute);
|
|
135
|
+
}
|
|
136
|
+
.lotion .lotion-spinner {
|
|
137
|
+
width: 36px;
|
|
138
|
+
height: 36px;
|
|
139
|
+
border-radius: 50%;
|
|
140
|
+
border: 3px solid var(--lotion-line);
|
|
141
|
+
border-top-color: var(--lotion-ink);
|
|
142
|
+
animation: lotion-spin 0.8s linear infinite;
|
|
143
|
+
}
|
|
144
|
+
.lotion:fullscreen {
|
|
145
|
+
display: flex;
|
|
146
|
+
flex-direction: column;
|
|
147
|
+
border: 0;
|
|
148
|
+
border-radius: 0;
|
|
149
|
+
}
|
|
150
|
+
.lotion:fullscreen .lotion-viewport {
|
|
151
|
+
flex: 1;
|
|
152
|
+
aspect-ratio: auto !important;
|
|
153
|
+
}
|
|
154
|
+
.lotion:fullscreen .lotion-bar {
|
|
155
|
+
flex: none;
|
|
156
|
+
}
|
|
157
|
+
.lotion.lotion-render {
|
|
158
|
+
position: fixed;
|
|
159
|
+
inset: 0;
|
|
160
|
+
z-index: 99999;
|
|
161
|
+
border: 0;
|
|
162
|
+
border-radius: 0;
|
|
163
|
+
}
|
|
164
|
+
.lotion.lotion-render .lotion-viewport {
|
|
165
|
+
width: 100vw;
|
|
166
|
+
height: 100vh;
|
|
167
|
+
aspect-ratio: auto !important;
|
|
168
|
+
}
|
|
169
|
+
.lotion.lotion-render .lotion-bar {
|
|
170
|
+
display: none;
|
|
171
|
+
}
|
|
172
|
+
@-moz-keyframes lotion-spin {
|
|
173
|
+
to {
|
|
174
|
+
transform: rotate(360deg);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
@-webkit-keyframes lotion-spin {
|
|
178
|
+
to {
|
|
179
|
+
transform: rotate(360deg);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
@-o-keyframes lotion-spin {
|
|
183
|
+
to {
|
|
184
|
+
transform: rotate(360deg);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
@keyframes lotion-spin {
|
|
188
|
+
to {
|
|
189
|
+
transform: rotate(360deg);
|
|
190
|
+
}
|
|
191
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
(function(){
|
|
2
|
+
var PI, sin, cos, exp, sqrt, round, clamp, lerp, ss, spring, presets, track, vis, bump, typing, hex, mixc, rgb, mk, put, txt, NS, svg, player, ref$, lotion;
|
|
3
|
+
PI = Math.PI, sin = Math.sin, cos = Math.cos, exp = Math.exp, sqrt = Math.sqrt, round = Math.round;
|
|
4
|
+
clamp = function(v, a, b){
|
|
5
|
+
a == null && (a = 0);
|
|
6
|
+
b == null && (b = 1);
|
|
7
|
+
if (v < a) {
|
|
8
|
+
return a;
|
|
9
|
+
} else if (v > b) {
|
|
10
|
+
return b;
|
|
11
|
+
} else {
|
|
12
|
+
return v;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
lerp = function(a, b, f){
|
|
16
|
+
return a + (b - a) * f;
|
|
17
|
+
};
|
|
18
|
+
ss = function(x){
|
|
19
|
+
x = clamp(x);
|
|
20
|
+
return x * x * (3 - 2 * x);
|
|
21
|
+
};
|
|
22
|
+
spring = function(t, w, z){
|
|
23
|
+
var wd;
|
|
24
|
+
w == null && (w = 14);
|
|
25
|
+
z == null && (z = 0.8);
|
|
26
|
+
if (t <= 0) {
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
if (z >= 1) {
|
|
30
|
+
return 1 - exp(-w * t) * (1 + w * t);
|
|
31
|
+
}
|
|
32
|
+
wd = w * sqrt(1 - z * z);
|
|
33
|
+
return 1 - exp(-z * w * t) * (cos(wd * t) + (z * w / wd) * sin(wd * t));
|
|
34
|
+
};
|
|
35
|
+
presets = {
|
|
36
|
+
fast: {
|
|
37
|
+
w: 22,
|
|
38
|
+
z: 0.86
|
|
39
|
+
},
|
|
40
|
+
std: {
|
|
41
|
+
w: 14,
|
|
42
|
+
z: 0.8
|
|
43
|
+
},
|
|
44
|
+
soft: {
|
|
45
|
+
w: 9,
|
|
46
|
+
z: 0.9
|
|
47
|
+
},
|
|
48
|
+
move: {
|
|
49
|
+
w: 11,
|
|
50
|
+
z: 0.85
|
|
51
|
+
},
|
|
52
|
+
ease: {
|
|
53
|
+
w: 10,
|
|
54
|
+
z: 1
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
track = function(keys, opt){
|
|
58
|
+
var p, def;
|
|
59
|
+
opt == null && (opt = 'std');
|
|
60
|
+
p = function(o){
|
|
61
|
+
if (typeof o === 'string') {
|
|
62
|
+
return presets[o];
|
|
63
|
+
} else {
|
|
64
|
+
return o;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
def = p(opt);
|
|
68
|
+
return function(t){
|
|
69
|
+
var v, i$, to$, i, k, c;
|
|
70
|
+
v = keys[0][1];
|
|
71
|
+
for (i$ = 1, to$ = keys.length; i$ < to$; ++i$) {
|
|
72
|
+
i = i$;
|
|
73
|
+
k = keys[i];
|
|
74
|
+
c = k[2] ? p(k[2]) : def;
|
|
75
|
+
v += (k[1] - keys[i - 1][1]) * spring(t - k[0], c.w, c.z);
|
|
76
|
+
}
|
|
77
|
+
return v;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
vis = function(t, t0, t1, din, dout){
|
|
81
|
+
t1 == null && (t1 = 1e9);
|
|
82
|
+
din == null && (din = 0.4);
|
|
83
|
+
dout == null && (dout = 0.35);
|
|
84
|
+
return ss((t - t0) / din) * (1 - ss((t - t1) / dout));
|
|
85
|
+
};
|
|
86
|
+
bump = function(t, t0, d){
|
|
87
|
+
d == null && (d = 0.6);
|
|
88
|
+
if (t < t0 || t > t0 + d) {
|
|
89
|
+
return 0;
|
|
90
|
+
} else {
|
|
91
|
+
return Math.pow(sin(PI * (t - t0) / d), 2);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
typing = function(t, t0, text, dt){
|
|
95
|
+
var chars;
|
|
96
|
+
dt == null && (dt = 0.06);
|
|
97
|
+
chars = Array.from(text);
|
|
98
|
+
return chars.slice(0, clamp(Math.floor((t - t0) / dt) + 1, 0, chars.length)).join('');
|
|
99
|
+
};
|
|
100
|
+
hex = function(h){
|
|
101
|
+
return [1, 3, 5].map(function(i){
|
|
102
|
+
return parseInt(h.slice(i, i + 2), 16);
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
mixc = function(a, b, f){
|
|
106
|
+
return [0, 1, 2].map(function(i){
|
|
107
|
+
return lerp(a[i], b[i], f);
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
rgb = function(c, a){
|
|
111
|
+
if (a != null) {
|
|
112
|
+
return "rgba(" + c.map(function(it){
|
|
113
|
+
return round(it);
|
|
114
|
+
}).join(',') + "," + a + ")";
|
|
115
|
+
} else {
|
|
116
|
+
return "rgb(" + c.map(function(it){
|
|
117
|
+
return round(it);
|
|
118
|
+
}).join(',') + ")";
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
mk = function(cls, html, parent, prefix){
|
|
122
|
+
var e;
|
|
123
|
+
cls == null && (cls = '');
|
|
124
|
+
html == null && (html = '');
|
|
125
|
+
prefix == null && (prefix = '');
|
|
126
|
+
e = document.createElement('div');
|
|
127
|
+
e.className = cls.split(' ').filter(function(it){
|
|
128
|
+
return it;
|
|
129
|
+
}).map(function(it){
|
|
130
|
+
return prefix + it;
|
|
131
|
+
}).join(' ');
|
|
132
|
+
e.innerHTML = html;
|
|
133
|
+
if (parent) {
|
|
134
|
+
parent.appendChild(e);
|
|
135
|
+
}
|
|
136
|
+
return e;
|
|
137
|
+
};
|
|
138
|
+
put = function(e, x, y, s, o, opt){
|
|
139
|
+
var hide, ref$;
|
|
140
|
+
s == null && (s = 1);
|
|
141
|
+
o == null && (o = 1);
|
|
142
|
+
opt == null && (opt = {});
|
|
143
|
+
hide = (ref$ = opt.hide) != null ? ref$ : true;
|
|
144
|
+
if (hide && o <= 0.002) {
|
|
145
|
+
if (e._lv !== false) {
|
|
146
|
+
e.style.visibility = 'hidden';
|
|
147
|
+
e._lv = false;
|
|
148
|
+
}
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (hide && e._lv !== true) {
|
|
152
|
+
e.style.visibility = 'visible';
|
|
153
|
+
e._lv = true;
|
|
154
|
+
}
|
|
155
|
+
e.style.transform = "translate(" + x.toFixed(2) + "px," + y.toFixed(2) + "px) scale(" + s.toFixed(4) + ")";
|
|
156
|
+
e.style.opacity = o.toFixed(3);
|
|
157
|
+
if (opt.blur != null) {
|
|
158
|
+
return e.style.filter = opt.blur > 0.05 ? "blur(" + opt.blur.toFixed(2) + "px)" : '';
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
txt = function(e, v){
|
|
162
|
+
if (e._lt !== v) {
|
|
163
|
+
e.innerHTML = v;
|
|
164
|
+
return e._lt = v;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
NS = 'http://www.w3.org/2000/svg';
|
|
168
|
+
svg = function(tag, attrs, parent){
|
|
169
|
+
var e, k, v;
|
|
170
|
+
attrs == null && (attrs = {});
|
|
171
|
+
e = document.createElementNS(NS, tag);
|
|
172
|
+
for (k in attrs) {
|
|
173
|
+
v = attrs[k];
|
|
174
|
+
e.setAttribute(k, v);
|
|
175
|
+
}
|
|
176
|
+
if (parent) {
|
|
177
|
+
parent.appendChild(e);
|
|
178
|
+
}
|
|
179
|
+
return e;
|
|
180
|
+
};
|
|
181
|
+
player = function(opt){
|
|
182
|
+
var this$ = this;
|
|
183
|
+
opt == null && (opt = {});
|
|
184
|
+
this.opt = opt;
|
|
185
|
+
this.root = typeof opt.root === 'string'
|
|
186
|
+
? document.querySelector(opt.root)
|
|
187
|
+
: opt.root;
|
|
188
|
+
this.width = opt.width || 1920;
|
|
189
|
+
this.height = opt.height || 1080;
|
|
190
|
+
this.duration = opt.duration || 0;
|
|
191
|
+
this.chapters = opt.chapters || [];
|
|
192
|
+
this.t = 0;
|
|
193
|
+
this.playing = false;
|
|
194
|
+
this.last = null;
|
|
195
|
+
this.started = false;
|
|
196
|
+
this.ready = new Promise(function(res){
|
|
197
|
+
return this$.readyRes = res;
|
|
198
|
+
});
|
|
199
|
+
this.renderMode = /[?&]render\b/.test(location.search);
|
|
200
|
+
this.init();
|
|
201
|
+
return this;
|
|
202
|
+
};
|
|
203
|
+
player.prototype = (ref$ = Object.create(Object.prototype), ref$.constructor = player, ref$.init = function(){
|
|
204
|
+
var r, ref$, html, q, this$ = this;
|
|
205
|
+
r = this.root;
|
|
206
|
+
r.classList.add('lotion');
|
|
207
|
+
if (!r.hasAttribute('tabindex')) {
|
|
208
|
+
r.setAttribute('tabindex', 0);
|
|
209
|
+
}
|
|
210
|
+
this.viewport = mk('lotion-viewport', '', r);
|
|
211
|
+
this.stage = mk('lotion-stage', '', this.viewport);
|
|
212
|
+
ref$ = this.stage.style;
|
|
213
|
+
ref$.width = this.width + "px";
|
|
214
|
+
ref$.height = this.height + "px";
|
|
215
|
+
this.viewport.style.aspectRatio = this.width + " / " + this.height;
|
|
216
|
+
r.classList.add('lotion-loading');
|
|
217
|
+
if (this.opt.loading !== false) {
|
|
218
|
+
html = typeof this.opt.loading === 'string' ? this.opt.loading : '<div class="lotion-spinner"></div>';
|
|
219
|
+
this.loading = mk('lotion-loading-screen', html, this.viewport);
|
|
220
|
+
}
|
|
221
|
+
this.bar = mk('lotion-bar', '<div class="lotion-btn lotion-play"></div>\n<div class="lotion-track"><div class="lotion-rail"></div><div class="lotion-fill"></div>\n<div class="lotion-chapters"></div><div class="lotion-knob"></div></div>\n<div class="lotion-time"></div>\n<div class="lotion-btn lotion-fs" title="全螢幕"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"\nstroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M2 6V2h4M10 2h4v4M14 10v4h-4M6 14H2v-4"/></svg></div>', r);
|
|
222
|
+
q = function(n){
|
|
223
|
+
return this$.bar.querySelector(".lotion-" + n);
|
|
224
|
+
};
|
|
225
|
+
this.el = {
|
|
226
|
+
play: q('play'),
|
|
227
|
+
fill: q('fill'),
|
|
228
|
+
knob: q('knob'),
|
|
229
|
+
time: q('time'),
|
|
230
|
+
track: q('track'),
|
|
231
|
+
chapters: q('chapters'),
|
|
232
|
+
fs: q('fs')
|
|
233
|
+
};
|
|
234
|
+
this.chapters.map(function(arg$){
|
|
235
|
+
var t, name, e;
|
|
236
|
+
t = arg$[0], name = arg$[1];
|
|
237
|
+
e = mk('lotion-ch', '', this$.el.chapters);
|
|
238
|
+
e.title = name;
|
|
239
|
+
return e.style.left = 100 * t / this$.duration + "%";
|
|
240
|
+
});
|
|
241
|
+
this.bind();
|
|
242
|
+
if (this.renderMode) {
|
|
243
|
+
r.classList.add('lotion-render');
|
|
244
|
+
}
|
|
245
|
+
this.fit();
|
|
246
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
247
|
+
return new ResizeObserver(function(){
|
|
248
|
+
return this$.fit();
|
|
249
|
+
}).observe(this.viewport);
|
|
250
|
+
} else {
|
|
251
|
+
return window.addEventListener('resize', function(){
|
|
252
|
+
return this$.fit();
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}, ref$.start = function(){
|
|
256
|
+
var m, this$ = this;
|
|
257
|
+
this.started = true;
|
|
258
|
+
this.root.classList.remove('lotion-loading');
|
|
259
|
+
if (this.loading) {
|
|
260
|
+
this.loading.remove();
|
|
261
|
+
}
|
|
262
|
+
if (this.renderMode) {
|
|
263
|
+
window.seek = function(t){
|
|
264
|
+
return this$.opt.seek(t);
|
|
265
|
+
};
|
|
266
|
+
window.DURATION = this.duration;
|
|
267
|
+
if (this.opt.cues) {
|
|
268
|
+
window.cues = this.opt.cues;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
this.readyRes(this);
|
|
272
|
+
m = /[?&]t=([\d.]+)/.exec(location.search);
|
|
273
|
+
this.seek(m
|
|
274
|
+
? +m[1]
|
|
275
|
+
: this.renderMode
|
|
276
|
+
? 0
|
|
277
|
+
: this.opt.start || 0);
|
|
278
|
+
if (this.opt.autoplay && !this.renderMode) {
|
|
279
|
+
document.fonts.ready.then(function(){
|
|
280
|
+
return this$.play(true);
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
return this;
|
|
284
|
+
}, ref$.bind = function(){
|
|
285
|
+
var dragging, fromEvent, this$ = this;
|
|
286
|
+
this.el.play.addEventListener('click', function(e){
|
|
287
|
+
e.stopPropagation();
|
|
288
|
+
return this$.toggle();
|
|
289
|
+
});
|
|
290
|
+
this.el.fs.addEventListener('click', function(e){
|
|
291
|
+
e.stopPropagation();
|
|
292
|
+
return this$.fullscreen();
|
|
293
|
+
});
|
|
294
|
+
this.viewport.addEventListener('click', function(){
|
|
295
|
+
this$.root.focus();
|
|
296
|
+
return this$.toggle();
|
|
297
|
+
});
|
|
298
|
+
dragging = false;
|
|
299
|
+
fromEvent = function(e){
|
|
300
|
+
var b;
|
|
301
|
+
b = this$.el.track.getBoundingClientRect();
|
|
302
|
+
return this$.seek(this$.duration * clamp((e.clientX - b.left) / b.width));
|
|
303
|
+
};
|
|
304
|
+
this.el.track.addEventListener('pointerdown', function(e){
|
|
305
|
+
dragging = true;
|
|
306
|
+
this$.el.track.setPointerCapture(e.pointerId);
|
|
307
|
+
return fromEvent(e);
|
|
308
|
+
});
|
|
309
|
+
this.el.track.addEventListener('pointermove', function(e){
|
|
310
|
+
if (dragging) {
|
|
311
|
+
return fromEvent(e);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
this.el.track.addEventListener('pointerup', function(){
|
|
315
|
+
return dragging = false;
|
|
316
|
+
});
|
|
317
|
+
return this.root.addEventListener('keydown', function(e){
|
|
318
|
+
var starts, ref$;
|
|
319
|
+
starts = this$.chapters.map(function(c){
|
|
320
|
+
return c[0];
|
|
321
|
+
});
|
|
322
|
+
if (e.code === 'Space') {
|
|
323
|
+
e.preventDefault();
|
|
324
|
+
return this$.toggle();
|
|
325
|
+
} else if (e.key === 'f') {
|
|
326
|
+
return this$.fullscreen();
|
|
327
|
+
} else if (e.key === 'ArrowRight') {
|
|
328
|
+
return this$.seek((ref$ = starts.find(function(s){
|
|
329
|
+
return s > this$.t + 0.05;
|
|
330
|
+
})) != null
|
|
331
|
+
? ref$
|
|
332
|
+
: this$.duration);
|
|
333
|
+
} else if (e.key === 'ArrowLeft') {
|
|
334
|
+
return this$.seek((ref$ = starts.filter(function(s){
|
|
335
|
+
return s < this$.t - 0.5;
|
|
336
|
+
}).pop()) != null ? ref$ : 0);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
}, ref$.fit = function(){
|
|
340
|
+
var w, h, s;
|
|
341
|
+
w = this.viewport.clientWidth;
|
|
342
|
+
h = this.viewport.clientHeight;
|
|
343
|
+
if (!w || !h) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
s = Math.min(w / this.width, h / this.height);
|
|
347
|
+
return this.stage.style.transform = "translate(" + (w - this.width * s) / 2 + "px," + (h - this.height * s) / 2 + "px) scale(" + s + ")";
|
|
348
|
+
}, ref$.fmt = function(t){
|
|
349
|
+
return Math.floor(t / 60) + ":" + ("0" + Math.floor(t % 60)).slice(-2);
|
|
350
|
+
}, ref$.seek = function(t){
|
|
351
|
+
var p, ch;
|
|
352
|
+
if (!this.started) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
this.t = t = clamp(t, 0, this.duration);
|
|
356
|
+
this.opt.seek(t);
|
|
357
|
+
p = 100 * t / this.duration + "%";
|
|
358
|
+
this.el.fill.style.width = p;
|
|
359
|
+
this.el.knob.style.left = p;
|
|
360
|
+
ch = this.chapters.filter(function(c){
|
|
361
|
+
return c[0] <= t;
|
|
362
|
+
}).pop();
|
|
363
|
+
this.el.time.textContent = (ch ? ch[1] + " · " : '') + (this.fmt(t) + " / " + this.fmt(this.duration));
|
|
364
|
+
return this.root.classList.toggle('lotion-playing', this.playing);
|
|
365
|
+
}, ref$.tick = function(now){
|
|
366
|
+
var this$ = this;
|
|
367
|
+
if (!this.playing) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (this.last != null) {
|
|
371
|
+
this.seek(this.t + (now - this.last) / 1000);
|
|
372
|
+
}
|
|
373
|
+
this.last = now;
|
|
374
|
+
if (this.t >= this.duration) {
|
|
375
|
+
this.playing = false;
|
|
376
|
+
this.seek(this.t);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
return requestAnimationFrame(function(n){
|
|
380
|
+
return this$.tick(n);
|
|
381
|
+
});
|
|
382
|
+
}, ref$.play = function(go){
|
|
383
|
+
var this$ = this;
|
|
384
|
+
go == null && (go = true);
|
|
385
|
+
if (!this.started) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
if (go && this.t >= this.duration) {
|
|
389
|
+
this.t = 0;
|
|
390
|
+
}
|
|
391
|
+
this.playing = go;
|
|
392
|
+
this.last = null;
|
|
393
|
+
this.seek(this.t);
|
|
394
|
+
if (go) {
|
|
395
|
+
return requestAnimationFrame(function(n){
|
|
396
|
+
return this$.tick(n);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}, ref$.pause = function(){
|
|
400
|
+
return this.play(false);
|
|
401
|
+
}, ref$.toggle = function(){
|
|
402
|
+
return this.play(!this.playing);
|
|
403
|
+
}, ref$.fullscreen = function(){
|
|
404
|
+
var d;
|
|
405
|
+
d = document;
|
|
406
|
+
if (d.fullscreenElement || d.webkitFullscreenElement) {
|
|
407
|
+
(d.exitFullscreen || d.webkitExitFullscreen).call(d);
|
|
408
|
+
} else {
|
|
409
|
+
(this.root.requestFullscreen || this.root.webkitRequestFullscreen).call(this.root);
|
|
410
|
+
}
|
|
411
|
+
return this.root.focus();
|
|
412
|
+
}, ref$);
|
|
413
|
+
lotion = {
|
|
414
|
+
clamp: clamp,
|
|
415
|
+
lerp: lerp,
|
|
416
|
+
ss: ss,
|
|
417
|
+
spring: spring,
|
|
418
|
+
presets: presets,
|
|
419
|
+
track: track,
|
|
420
|
+
vis: vis,
|
|
421
|
+
bump: bump,
|
|
422
|
+
typing: typing,
|
|
423
|
+
hex: hex,
|
|
424
|
+
mixc: mixc,
|
|
425
|
+
rgb: rgb,
|
|
426
|
+
mk: mk,
|
|
427
|
+
put: put,
|
|
428
|
+
txt: txt,
|
|
429
|
+
svg: svg,
|
|
430
|
+
player: player
|
|
431
|
+
};
|
|
432
|
+
if (typeof module != 'undefined' && module !== null) {
|
|
433
|
+
module.exports = lotion;
|
|
434
|
+
} else if (typeof window != 'undefined' && window !== null) {
|
|
435
|
+
window.lotion = lotion;
|
|
436
|
+
}
|
|
437
|
+
}).call(this);
|
package/index.min.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.lotion{--lotion-bg:#eceae5;--lotion-paper:#fbfaf7;--lotion-ink:#18181a;--lotion-mute:#8a877f;--lotion-line:#d9d6cf;position:relative;border:1px solid var(--lotion-line);border-radius:12px;overflow:hidden;outline:none}.lotion .lotion-viewport{position:relative;width:100%;overflow:hidden;background:var(--lotion-bg)}.lotion .lotion-stage{position:absolute;left:0;top:0;transform-origin:0 0;background:var(--lotion-bg);overflow:hidden;line-height:normal}.lotion .lotion-bar{display:flex;align-items:center;gap:18px;height:64px;padding:0 24px;background:var(--lotion-paper);border-top:1px solid var(--lotion-line);user-select:none}.lotion .lotion-btn{flex:none;width:40px;height:40px;border-radius:50%;background:var(--lotion-ink);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer}.lotion .lotion-play:before{content:"";margin-left:3px;border-style:solid;border-width:7px 0 7px 12px;border-color:transparent transparent transparent #fff}.lotion.lotion-playing .lotion-play:before{margin-left:0;width:4px;height:14px;border-width:0 4px;border-color:#fff}.lotion .lotion-fs{background:transparent;color:var(--lotion-ink);border:1px solid var(--lotion-line)}.lotion .lotion-time{font:15px/1 sans-serif;color:var(--lotion-mute);font-variant-numeric:tabular-nums;white-space:nowrap}.lotion .lotion-track{position:relative;flex:1;height:40px;cursor:pointer}.lotion .lotion-rail,.lotion .lotion-fill{position:absolute;left:0;top:18px;height:4px;border-radius:2px}.lotion .lotion-rail{right:0;background:var(--lotion-line)}.lotion .lotion-fill{background:var(--lotion-ink)}.lotion .lotion-knob{position:absolute;top:13px;width:14px;height:14px;margin-left:-7px;border-radius:50%;background:var(--lotion-ink)}.lotion .lotion-chapters{position:absolute;inset:0;pointer-events:none}.lotion .lotion-ch{position:absolute;top:14px;width:2px;height:12px;margin-left:-1px;border-radius:1px;background:var(--lotion-mute);opacity:.5}.lotion.lotion-loading .lotion-stage{visibility:hidden}.lotion.lotion-loading .lotion-bar{opacity:.5;pointer-events:none}.lotion .lotion-loading-screen{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:var(--lotion-bg);color:var(--lotion-mute)}.lotion .lotion-spinner{width:36px;height:36px;border-radius:50%;border:3px solid var(--lotion-line);border-top-color:var(--lotion-ink);animation:lotion-spin .8s linear infinite}.lotion:fullscreen{display:flex;flex-direction:column;border:0;border-radius:0}.lotion:fullscreen .lotion-viewport{flex:1;aspect-ratio:auto !important}.lotion:fullscreen .lotion-bar{flex:none}.lotion.lotion-render{position:fixed;inset:0;z-index:99999;border:0;border-radius:0}.lotion.lotion-render .lotion-viewport{width:100vw;height:100vh;aspect-ratio:auto !important}.lotion.lotion-render .lotion-bar{display:none}@-moz-keyframes lotion-spin{to{transform:rotate(360deg)}}@-webkit-keyframes lotion-spin{to{transform:rotate(360deg)}}@-o-keyframes lotion-spin{to{transform:rotate(360deg)}}@keyframes lotion-spin{to{transform:rotate(360deg)}}
|
package/index.min.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(){var t,n=Math.PI,r=Math.sin,s=Math.cos,o=Math.exp,l=Math.sqrt,e=Math.round,u=function(t,i,e){return null==e&&(e=1),t<(i=null==i?0:i)?i:e<t?e:t},a=function(t,i,e){return t+(i-t)*e},h=function(t){return(t=u(t))*t*(3-2*t)},c=function(t,i,e){var n;return null==i&&(i=14),t<=0?0:1<=(e=null==e?.8:e)?1-o(-i*t)*(1+i*t):(n=i*l(1-e*e),1-o(-e*i*t)*(s(n*t)+e*i/n*r(n*t)))},i={fast:{w:22,z:.86},std:{w:14,z:.8},soft:{w:9,z:.9},move:{w:11,z:.85},ease:{w:10,z:1}},d=function(l,t){var u,a=(u=function(t){return"string"==typeof t?i[t]:t})(t=null==t?"std":t);return function(t){for(var i,e,n,r=l[0][1],s=1,o=l.length;s<o;++s)n=(e=l[i=s])[2]?u(e[2]):a,r+=(e[1]-l[i-1][1])*c(t-e[0],n.w,n.z);return r}},f=function(t,i,e,n,r){return h((t-i)/(n=null==n?.4:n))*(1-h((t-(e=null==e?1e9:e))/(r=null==r?.35:r)))},p=function(t,i,e){return null==e&&(e=.6),t<i||i+e<t?0:Math.pow(r(n*(t-i)/e),2)},v=function(t,i,e,n){return null==n&&(n=.06),(e=Array.from(e)).slice(0,u(Math.floor((t-i)/n)+1,0,e.length)).join("")},g=function(i){return[1,3,5].map(function(t){return parseInt(i.slice(t,t+2),16)})},w=function(i,e,n){return[0,1,2].map(function(t){return a(i[t],e[t],n)})},y=function(t,i){return null!=i?"rgba("+t.map(function(t){return e(t)}).join(",")+","+i+")":"rgb("+t.map(function(t){return e(t)}).join(",")+")"},m=function(t,i,e,n){var r;return null==t&&(t=""),null==i&&(i=""),null==n&&(n=""),(r=document.createElement("div")).className=t.split(" ").filter(function(t){return t}).map(function(t){return n+t}).join(" "),r.innerHTML=i,e&&e.appendChild(r),r},k=function(t,i,e,n,r,s){var o;if(null==n&&(n=1),null==r&&(r=1),!((o=null==(o=(s=null==s?{}:s).hide)||o)&&r<=.002))return o&&!0!==t._lv&&(t.style.visibility="visible",t._lv=!0),t.style.transform="translate("+i.toFixed(2)+"px,"+e.toFixed(2)+"px) scale("+n.toFixed(4)+")",t.style.opacity=r.toFixed(3),null!=s.blur?t.style.filter=.05<s.blur?"blur("+s.blur.toFixed(2)+"px)":"":void 0;!1!==t._lv&&(t.style.visibility="hidden",t._lv=!1)},b=function(t,i){if(t._lt!==i)return t.innerHTML=i,t._lt=i},x=function(t,i,e){var n,r,s;for(r in null==i&&(i={}),n=document.createElementNS("http://www.w3.org/2000/svg",t),i)s=i[r],n.setAttribute(r,s);return e&&e.appendChild(n),n},M=function(t){var i=this;return this.opt=t=null==t?{}:t,this.root="string"==typeof t.root?document.querySelector(t.root):t.root,this.width=t.width||1920,this.height=t.height||1080,this.duration=t.duration||0,this.chapters=t.chapters||[],this.t=0,this.playing=!1,this.last=null,this.started=!1,this.ready=new Promise(function(t){return i.readyRes=t}),this.renderMode=/[?&]render\b/.test(location.search),this.init(),this};M.prototype=((t=Object.create(Object.prototype)).constructor=M,t.init=function(){var t,n=this,i=this.root;return i.classList.add("lotion"),i.hasAttribute("tabindex")||i.setAttribute("tabindex",0),this.viewport=m("lotion-viewport","",i),this.stage=m("lotion-stage","",this.viewport),(t=this.stage.style).width=this.width+"px",t.height=this.height+"px",this.viewport.style.aspectRatio=this.width+" / "+this.height,i.classList.add("lotion-loading"),!1!==this.opt.loading&&(t="string"==typeof this.opt.loading?this.opt.loading:'<div class="lotion-spinner"></div>',this.loading=m("lotion-loading-screen",t,this.viewport)),this.bar=m("lotion-bar",'<div class="lotion-btn lotion-play"></div>\n<div class="lotion-track"><div class="lotion-rail"></div><div class="lotion-fill"></div>\n<div class="lotion-chapters"></div><div class="lotion-knob"></div></div>\n<div class="lotion-time"></div>\n<div class="lotion-btn lotion-fs" title="全螢幕"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"\nstroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M2 6V2h4M10 2h4v4M14 10v4h-4M6 14H2v-4"/></svg></div>',i),this.el={play:(t=function(t){return n.bar.querySelector(".lotion-"+t)})("play"),fill:t("fill"),knob:t("knob"),time:t("time"),track:t("track"),chapters:t("chapters"),fs:t("fs")},this.chapters.map(function(t){var i=t[0],t=t[1],e=m("lotion-ch","",n.el.chapters);return e.title=t,e.style.left=100*i/n.duration+"%"}),this.bind(),this.renderMode&&i.classList.add("lotion-render"),this.fit(),"undefined"!=typeof ResizeObserver?new ResizeObserver(function(){return n.fit()}).observe(this.viewport):window.addEventListener("resize",function(){return n.fit()})},t.start=function(){var t,i=this;return this.started=!0,this.root.classList.remove("lotion-loading"),this.loading&&this.loading.remove(),this.renderMode&&(window.seek=function(t){return i.opt.seek(t)},window.DURATION=this.duration,this.opt.cues)&&(window.cues=this.opt.cues),this.readyRes(this),t=/[?&]t=([\d.]+)/.exec(location.search),this.seek(t?+t[1]:!this.renderMode&&this.opt.start||0),this.opt.autoplay&&!this.renderMode&&document.fonts.ready.then(function(){return i.play(!0)}),this},t.bind=function(){var i,e,n=this;return this.el.play.addEventListener("click",function(t){return t.stopPropagation(),n.toggle()}),this.el.fs.addEventListener("click",function(t){return t.stopPropagation(),n.fullscreen()}),this.viewport.addEventListener("click",function(){return n.root.focus(),n.toggle()}),i=!1,e=function(t){var i=n.el.track.getBoundingClientRect();return n.seek(n.duration*u((t.clientX-i.left)/i.width))},this.el.track.addEventListener("pointerdown",function(t){return i=!0,n.el.track.setPointerCapture(t.pointerId),e(t)}),this.el.track.addEventListener("pointermove",function(t){if(i)return e(t)}),this.el.track.addEventListener("pointerup",function(){return i=!1}),this.root.addEventListener("keydown",function(t){var i,e=n.chapters.map(function(t){return t[0]});return"Space"===t.code?(t.preventDefault(),n.toggle()):"f"===t.key?n.fullscreen():"ArrowRight"===t.key?n.seek(null!=(i=e.find(function(t){return t>n.t+.05}))?i:n.duration):"ArrowLeft"===t.key?n.seek(null!=(i=e.filter(function(t){return t<n.t-.5}).pop())?i:0):void 0})},t.fit=function(){var t,i=this.viewport.clientWidth,e=this.viewport.clientHeight;if(i&&e)return t=Math.min(i/this.width,e/this.height),this.stage.style.transform="translate("+(i-this.width*t)/2+"px,"+(e-this.height*t)/2+"px) scale("+t+")"},t.fmt=function(t){return Math.floor(t/60)+":"+("0"+Math.floor(t%60)).slice(-2)},t.seek=function(i){var t;if(this.started)return this.t=i=u(i,0,this.duration),this.opt.seek(i),t=100*i/this.duration+"%",this.el.fill.style.width=t,this.el.knob.style.left=t,t=this.chapters.filter(function(t){return t[0]<=i}).pop(),this.el.time.textContent=(t?t[1]+" · ":"")+this.fmt(i)+" / "+this.fmt(this.duration),this.root.classList.toggle("lotion-playing",this.playing)},t.tick=function(t){var i=this;if(this.playing){if(null!=this.last&&this.seek(this.t+(t-this.last)/1e3),this.last=t,!(this.t>=this.duration))return requestAnimationFrame(function(t){return i.tick(t)});this.playing=!1,this.seek(this.t)}},t.play=function(t){var i=this;if(null==t&&(t=!0),this.started)return t&&this.t>=this.duration&&(this.t=0),this.playing=t,this.last=null,this.seek(this.t),t?requestAnimationFrame(function(t){return i.tick(t)}):void 0},t.pause=function(){return this.play(!1)},t.toggle=function(){return this.play(!this.playing)},t.fullscreen=function(){var t=document;return t.fullscreenElement||t.webkitFullscreenElement?(t.exitFullscreen||t.webkitExitFullscreen).call(t):(this.root.requestFullscreen||this.root.webkitRequestFullscreen).call(this.root),this.root.focus()},t),t={clamp:u,lerp:a,ss:h,spring:c,presets:i,track:d,vis:f,bump:p,typing:v,hex:g,mixc:w,rgb:y,mk:m,put:k,txt:b,svg:x,player:M},"undefined"!=typeof module&&null!==module?module.exports=t:"undefined"!=typeof window&&null!==window&&(window.lotion=t)}.call(this);
|
package/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"author":"zbryikt","name":"@plotdb/lotion","version":"0.1.0","description":"deterministic motion toolkit: animation as a pure function of time, with player, frame renderer, block packaging and audio tools","license":"MIT","main":"index.min.js","browser":"index.min.js","bin":{"lotion":"./cli.js"},"homepage":"https://github.com/plotdb/lotion","repository":{"type":"git","url":"git+https://github.com/plotdb/lotion.git"},"scripts":{"start":"npx server -r web -o true"},"engines":{"node":">=14"},"keywords":["motion","animation","video","playwright","block"],"dependencies":{"@plotdb/block":"^5.7.3","@plotdb/csscope":"^5.0.4","@plotdb/rescope":"^5.1.0","@plotdb/semver":"^0.0.4","proxise":"^1.0.1"},"peerDependencies":{"playwright":">=1.40"},"peerDependenciesMeta":{"playwright":{"optional":true}},"devDependencies":{"@plotdb/guides":"github:plotdb/guides","@zbryikt/template":"^2.5.0","fedep":"^1.9.0","livescript":"^1.6.0","playwright":"^1.63.0","stylus":"^0.64.0","uglify-js":"^3.19.3"},"frontendDependencies":{"root":"web/static/assets/lib","modules":[]}}
|