@5even7/dlc-ui 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 +15 -0
- package/LICENSE +21 -0
- package/README.md +248 -0
- package/dist/capsule.cjs +1036 -0
- package/dist/capsule.mjs +831 -0
- package/dist/color.cjs +929 -0
- package/dist/color.mjs +760 -0
- package/dist/index.cjs +2430 -0
- package/dist/index.mjs +2431 -0
- package/dist/index.umd.js +2436 -0
- package/dist/index.umd.min.js +1 -0
- package/dist/progress.cjs +1751 -0
- package/dist/progress.mjs +1658 -0
- package/dist/vue2.cjs +2483 -0
- package/dist/vue2.mjs +2426 -0
- package/dist/vue3.cjs +2485 -0
- package/dist/vue3.mjs +2428 -0
- package/package.json +121 -0
- package/styles/base.css +54 -0
- package/styles/capsule.css +81 -0
- package/styles/color.css +18 -0
- package/styles/progress.css +107 -0
- package/styles/theme.css +4 -0
- package/types/capsule.d.ts +13 -0
- package/types/color.d.ts +13 -0
- package/types/index.d.ts +204 -0
- package/types/progress.d.ts +14 -0
- package/types/vue2.d.ts +1 -0
- package/types/vue3.d.ts +47 -0
package/dist/vue2.cjs
ADDED
|
@@ -0,0 +1,2483 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function _arrayLikeToArray(r, a) {
|
|
4
|
+
(null == a || a > r.length) && (a = r.length);
|
|
5
|
+
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
|
|
6
|
+
return n;
|
|
7
|
+
}
|
|
8
|
+
function _arrayWithHoles(r) {
|
|
9
|
+
if (Array.isArray(r)) return r;
|
|
10
|
+
}
|
|
11
|
+
function _arrayWithoutHoles(r) {
|
|
12
|
+
if (Array.isArray(r)) return _arrayLikeToArray(r);
|
|
13
|
+
}
|
|
14
|
+
function _assertClassBrand(e, t, n) {
|
|
15
|
+
if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
|
|
16
|
+
throw new TypeError("Private element is not present on this object");
|
|
17
|
+
}
|
|
18
|
+
function _checkPrivateRedeclaration(e, t) {
|
|
19
|
+
if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
|
|
20
|
+
}
|
|
21
|
+
function _classCallCheck(a, n) {
|
|
22
|
+
if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
|
|
23
|
+
}
|
|
24
|
+
function _classPrivateMethodInitSpec(e, a) {
|
|
25
|
+
_checkPrivateRedeclaration(e, a), a.add(e);
|
|
26
|
+
}
|
|
27
|
+
function _defineProperties(e, r) {
|
|
28
|
+
for (var t = 0; t < r.length; t++) {
|
|
29
|
+
var o = r[t];
|
|
30
|
+
o.enumerable = o.enumerable || false, o.configurable = true, "value" in o && (o.writable = true), Object.defineProperty(e, _toPropertyKey(o.key), o);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function _createClass(e, r, t) {
|
|
34
|
+
return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", {
|
|
35
|
+
writable: false
|
|
36
|
+
}), e;
|
|
37
|
+
}
|
|
38
|
+
function _createForOfIteratorHelper(r, e) {
|
|
39
|
+
var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
|
|
40
|
+
if (!t) {
|
|
41
|
+
if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) {
|
|
42
|
+
t && (r = t);
|
|
43
|
+
var n = 0,
|
|
44
|
+
F = function () {};
|
|
45
|
+
return {
|
|
46
|
+
s: F,
|
|
47
|
+
n: function () {
|
|
48
|
+
return n >= r.length ? {
|
|
49
|
+
done: true
|
|
50
|
+
} : {
|
|
51
|
+
done: false,
|
|
52
|
+
value: r[n++]
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
e: function (r) {
|
|
56
|
+
throw r;
|
|
57
|
+
},
|
|
58
|
+
f: F
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
62
|
+
}
|
|
63
|
+
var o,
|
|
64
|
+
a = true,
|
|
65
|
+
u = false;
|
|
66
|
+
return {
|
|
67
|
+
s: function () {
|
|
68
|
+
t = t.call(r);
|
|
69
|
+
},
|
|
70
|
+
n: function () {
|
|
71
|
+
var r = t.next();
|
|
72
|
+
return a = r.done, r;
|
|
73
|
+
},
|
|
74
|
+
e: function (r) {
|
|
75
|
+
u = true, o = r;
|
|
76
|
+
},
|
|
77
|
+
f: function () {
|
|
78
|
+
try {
|
|
79
|
+
a || null == t.return || t.return();
|
|
80
|
+
} finally {
|
|
81
|
+
if (u) throw o;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function _defineProperty(e, r, t) {
|
|
87
|
+
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
88
|
+
value: t,
|
|
89
|
+
enumerable: true,
|
|
90
|
+
configurable: true,
|
|
91
|
+
writable: true
|
|
92
|
+
}) : e[r] = t, e;
|
|
93
|
+
}
|
|
94
|
+
function _iterableToArray(r) {
|
|
95
|
+
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
|
|
96
|
+
}
|
|
97
|
+
function _iterableToArrayLimit(r, l) {
|
|
98
|
+
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
|
|
99
|
+
if (null != t) {
|
|
100
|
+
var e,
|
|
101
|
+
n,
|
|
102
|
+
i,
|
|
103
|
+
u,
|
|
104
|
+
a = [],
|
|
105
|
+
f = true,
|
|
106
|
+
o = false;
|
|
107
|
+
try {
|
|
108
|
+
if (i = (t = t.call(r)).next, 0 === l) {
|
|
109
|
+
if (Object(t) !== t) return;
|
|
110
|
+
f = !1;
|
|
111
|
+
} else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
|
|
112
|
+
} catch (r) {
|
|
113
|
+
o = true, n = r;
|
|
114
|
+
} finally {
|
|
115
|
+
try {
|
|
116
|
+
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
|
|
117
|
+
} finally {
|
|
118
|
+
if (o) throw n;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return a;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function _nonIterableRest() {
|
|
125
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
126
|
+
}
|
|
127
|
+
function _nonIterableSpread() {
|
|
128
|
+
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
129
|
+
}
|
|
130
|
+
function ownKeys(e, r) {
|
|
131
|
+
var t = Object.keys(e);
|
|
132
|
+
if (Object.getOwnPropertySymbols) {
|
|
133
|
+
var o = Object.getOwnPropertySymbols(e);
|
|
134
|
+
r && (o = o.filter(function (r) {
|
|
135
|
+
return Object.getOwnPropertyDescriptor(e, r).enumerable;
|
|
136
|
+
})), t.push.apply(t, o);
|
|
137
|
+
}
|
|
138
|
+
return t;
|
|
139
|
+
}
|
|
140
|
+
function _objectSpread2(e) {
|
|
141
|
+
for (var r = 1; r < arguments.length; r++) {
|
|
142
|
+
var t = null != arguments[r] ? arguments[r] : {};
|
|
143
|
+
r % 2 ? ownKeys(Object(t), true).forEach(function (r) {
|
|
144
|
+
_defineProperty(e, r, t[r]);
|
|
145
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
|
|
146
|
+
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return e;
|
|
150
|
+
}
|
|
151
|
+
function _slicedToArray(r, e) {
|
|
152
|
+
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
|
|
153
|
+
}
|
|
154
|
+
function _toConsumableArray(r) {
|
|
155
|
+
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
|
|
156
|
+
}
|
|
157
|
+
function _toPrimitive(t, r) {
|
|
158
|
+
if ("object" != typeof t || !t) return t;
|
|
159
|
+
var e = t[Symbol.toPrimitive];
|
|
160
|
+
if (void 0 !== e) {
|
|
161
|
+
var i = e.call(t, r);
|
|
162
|
+
if ("object" != typeof i) return i;
|
|
163
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
164
|
+
}
|
|
165
|
+
return ("string" === r ? String : Number)(t);
|
|
166
|
+
}
|
|
167
|
+
function _toPropertyKey(t) {
|
|
168
|
+
var i = _toPrimitive(t, "string");
|
|
169
|
+
return "symbol" == typeof i ? i : i + "";
|
|
170
|
+
}
|
|
171
|
+
function _typeof(o) {
|
|
172
|
+
"@babel/helpers - typeof";
|
|
173
|
+
|
|
174
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
|
|
175
|
+
return typeof o;
|
|
176
|
+
} : function (o) {
|
|
177
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
178
|
+
}, _typeof(o);
|
|
179
|
+
}
|
|
180
|
+
function _unsupportedIterableToArray(r, a) {
|
|
181
|
+
if (r) {
|
|
182
|
+
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
183
|
+
var t = {}.toString.call(r).slice(8, -1);
|
|
184
|
+
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Tiny event emitter. Accepts any event name so the API stays open for
|
|
190
|
+
* future events (hover, click, custom) without breaking changes.
|
|
191
|
+
*/
|
|
192
|
+
function createEmitter() {
|
|
193
|
+
// Plain object storage (no Map/Set) so the legacy build has no API
|
|
194
|
+
// dependencies beyond what IE11 provides.
|
|
195
|
+
var listeners = Object.create(null);
|
|
196
|
+
return {
|
|
197
|
+
on: function on(event, fn) {
|
|
198
|
+
if (!listeners[event]) listeners[event] = [];
|
|
199
|
+
listeners[event].push(fn);
|
|
200
|
+
return function () {
|
|
201
|
+
var current = listeners[event];
|
|
202
|
+
if (current) {
|
|
203
|
+
var index = current.indexOf(fn);
|
|
204
|
+
if (index !== -1) current.splice(index, 1);
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
},
|
|
208
|
+
off: function off(event, fn) {
|
|
209
|
+
var current = listeners[event];
|
|
210
|
+
if (!current) return false;
|
|
211
|
+
var index = current.indexOf(fn);
|
|
212
|
+
if (index === -1) return false;
|
|
213
|
+
current.splice(index, 1);
|
|
214
|
+
return true;
|
|
215
|
+
},
|
|
216
|
+
emit: function emit(event) {
|
|
217
|
+
var current = listeners[event];
|
|
218
|
+
if (!current) return;
|
|
219
|
+
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
220
|
+
args[_key - 1] = arguments[_key];
|
|
221
|
+
}
|
|
222
|
+
var _iterator = _createForOfIteratorHelper(current.slice()),
|
|
223
|
+
_step;
|
|
224
|
+
try {
|
|
225
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
226
|
+
var fn = _step.value;
|
|
227
|
+
fn.apply(void 0, args);
|
|
228
|
+
}
|
|
229
|
+
} catch (err) {
|
|
230
|
+
_iterator.e(err);
|
|
231
|
+
} finally {
|
|
232
|
+
_iterator.f();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
var UNIT_PATTERN = /^[\d.]+(?:px|%|vw|vh|vmin|vmax|em|rem)$/;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Normalize a size option to a CSS length string.
|
|
242
|
+
* Accepts numbers (treated as px) or strings with px/%, vw/vh/vmin/vmax, em/rem.
|
|
243
|
+
*/
|
|
244
|
+
function parseSize(value) {
|
|
245
|
+
if (typeof value === 'number') {
|
|
246
|
+
if (!Number.isFinite(value) || value < 0) throw new Error("Invalid size: ".concat(value));
|
|
247
|
+
return "".concat(value, "px");
|
|
248
|
+
}
|
|
249
|
+
if (typeof value !== 'string') throw new Error("Invalid size: ".concat(String(value)));
|
|
250
|
+
var trimmed = value.trim();
|
|
251
|
+
if (!trimmed) throw new Error('Invalid size: empty string');
|
|
252
|
+
if (/^\d+(?:\.\d+)?$/.test(trimmed)) return "".concat(trimmed, "px");
|
|
253
|
+
if (!UNIT_PATTERN.test(trimmed)) {
|
|
254
|
+
throw new Error("Invalid size or unsupported unit: \"".concat(value, "\" (use px, %, vw, vh, vmin, vmax, em, rem)"));
|
|
255
|
+
}
|
|
256
|
+
return trimmed;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
var QUALITY_TIERS = {
|
|
260
|
+
low: {
|
|
261
|
+
dpr: 1
|
|
262
|
+
},
|
|
263
|
+
medium: {
|
|
264
|
+
dpr: 1.5
|
|
265
|
+
},
|
|
266
|
+
high: {
|
|
267
|
+
dpr: 2
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
function autoDprCap() {
|
|
271
|
+
var nav = typeof navigator !== 'undefined' ? navigator : null;
|
|
272
|
+
var memory = nav && typeof nav.deviceMemory === 'number' ? nav.deviceMemory : 8;
|
|
273
|
+
var cores = nav && typeof nav.hardwareConcurrency === 'number' ? nav.hardwareConcurrency : 8;
|
|
274
|
+
return memory <= 4 || cores <= 4 ? 1.5 : 2;
|
|
275
|
+
}
|
|
276
|
+
function dprCapFor(quality) {
|
|
277
|
+
if (quality === 'auto') return autoDprCap();
|
|
278
|
+
var tier = QUALITY_TIERS[quality] || QUALITY_TIERS.medium;
|
|
279
|
+
return tier.dpr;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Merge defaults < preset < user. Unknown user keys are preserved so the
|
|
284
|
+
* component API can grow (new props, cssVars, callbacks) without a breaking
|
|
285
|
+
* change.
|
|
286
|
+
*/
|
|
287
|
+
function normalizeOptions(defaults, preset, user) {
|
|
288
|
+
// undefined means "not provided" (e.g. Vue $props with unset props):
|
|
289
|
+
// drop those keys before merging so defaults/preset values survive.
|
|
290
|
+
var omitUndefined = function omitUndefined(source) {
|
|
291
|
+
var result = {};
|
|
292
|
+
for (var _i = 0, _Object$keys = Object.keys(source); _i < _Object$keys.length; _i++) {
|
|
293
|
+
var key = _Object$keys[_i];
|
|
294
|
+
if (source[key] !== undefined) result[key] = source[key];
|
|
295
|
+
}
|
|
296
|
+
return result;
|
|
297
|
+
};
|
|
298
|
+
var presetOptions = omitUndefined(preset && _typeof(preset) === 'object' ? preset : {});
|
|
299
|
+
var userOptions = omitUndefined(user && _typeof(user) === 'object' ? user : {});
|
|
300
|
+
return _objectSpread2(_objectSpread2(_objectSpread2({}, defaults), presetOptions), userOptions);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* 公共色板:NC-01~NC-06 的四色组(底色 / 主色 / 辅色 / 高光色)。
|
|
305
|
+
* Capsule 预置与 dlc-color 等组件共用,新增色板只改这里。
|
|
306
|
+
*/
|
|
307
|
+
var PALETTES$1 = {
|
|
308
|
+
original: ['#FFF3EA', '#F5B27A', '#F67BC6', '#A978E8'],
|
|
309
|
+
ocean: ['#EAF6FF', '#8FD0FF', '#3B87F6', '#6B58E9'],
|
|
310
|
+
klein: ['#EDF2FF', '#2F58D5', '#1B2040', '#E07A43'],
|
|
311
|
+
ultraviolet: ['#F2EEFF', '#B99AF1', '#8F74DB', '#D7D85C'],
|
|
312
|
+
chrome: ['#F5F6F8', '#B9C0CC', '#7F8793', '#4A4F59'],
|
|
313
|
+
plus: ['#FFF0E6', '#F6C26B', '#F98A64', '#E86D74']
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Capsule 预置:仅星云材质 NC-01~NC-06(NC-07~09 aurora 已移除)。
|
|
318
|
+
* 颜色引用公共色板,seed/speed 决定形态与流速。
|
|
319
|
+
*/
|
|
320
|
+
var CAPSULE_PRESETS = [{
|
|
321
|
+
id: 'original',
|
|
322
|
+
code: 'NC-01',
|
|
323
|
+
name: 'ORIGINAL',
|
|
324
|
+
group: 'warm',
|
|
325
|
+
seed: 1.7,
|
|
326
|
+
speed: 0.5,
|
|
327
|
+
colors: _toConsumableArray(PALETTES$1.original)
|
|
328
|
+
}, {
|
|
329
|
+
id: 'ocean',
|
|
330
|
+
code: 'NC-02',
|
|
331
|
+
name: 'OCEAN',
|
|
332
|
+
group: 'cold',
|
|
333
|
+
seed: 8.2,
|
|
334
|
+
speed: 0.48,
|
|
335
|
+
colors: _toConsumableArray(PALETTES$1.ocean)
|
|
336
|
+
}, {
|
|
337
|
+
id: 'klein',
|
|
338
|
+
code: 'NC-03',
|
|
339
|
+
name: 'KLEIN',
|
|
340
|
+
group: 'cold',
|
|
341
|
+
seed: 14.1,
|
|
342
|
+
speed: 0.49,
|
|
343
|
+
colors: _toConsumableArray(PALETTES$1.klein)
|
|
344
|
+
}, {
|
|
345
|
+
id: 'ultraviolet',
|
|
346
|
+
code: 'NC-04',
|
|
347
|
+
name: 'ULTRAVIOLET',
|
|
348
|
+
group: 'cold',
|
|
349
|
+
seed: 23.4,
|
|
350
|
+
speed: 0.47,
|
|
351
|
+
colors: _toConsumableArray(PALETTES$1.ultraviolet)
|
|
352
|
+
}, {
|
|
353
|
+
id: 'chrome',
|
|
354
|
+
code: 'NC-05',
|
|
355
|
+
name: 'CHROME',
|
|
356
|
+
group: 'cold',
|
|
357
|
+
seed: 37.8,
|
|
358
|
+
speed: 0.42,
|
|
359
|
+
colors: _toConsumableArray(PALETTES$1.chrome)
|
|
360
|
+
}, {
|
|
361
|
+
id: 'plus',
|
|
362
|
+
code: 'NC-06',
|
|
363
|
+
name: 'PLUS',
|
|
364
|
+
group: 'warm',
|
|
365
|
+
seed: 51.3,
|
|
366
|
+
speed: 0.5,
|
|
367
|
+
colors: _toConsumableArray(PALETTES$1.plus)
|
|
368
|
+
}];
|
|
369
|
+
|
|
370
|
+
var PROGRESS_PRESETS = [{
|
|
371
|
+
id: 'model-training',
|
|
372
|
+
code: 'NC-10',
|
|
373
|
+
name: 'MODEL TRAINING',
|
|
374
|
+
subtitle: 'SHA 4.5 + 100 2026 TKN',
|
|
375
|
+
group: 'progress',
|
|
376
|
+
initialProgress: 43,
|
|
377
|
+
edgeStyle: 'flow',
|
|
378
|
+
colors: ['#2B1025', '#FF3F94', '#FF8A3D', '#FFF06A']
|
|
379
|
+
}, {
|
|
380
|
+
id: 'agent-migration',
|
|
381
|
+
code: 'NC-11',
|
|
382
|
+
name: 'AGENT MIGRATION',
|
|
383
|
+
subtitle: 'TRANSFERRING PROTOCOL',
|
|
384
|
+
group: 'progress',
|
|
385
|
+
initialProgress: 33,
|
|
386
|
+
edgeStyle: 'flow',
|
|
387
|
+
colors: ['#101C37', '#245BFF', '#00CFFF', '#5DFFE6']
|
|
388
|
+
}, {
|
|
389
|
+
id: 'visual-training',
|
|
390
|
+
code: 'NC-12',
|
|
391
|
+
name: 'VISUAL TRAINING',
|
|
392
|
+
subtitle: 'GENERATING POWER ++',
|
|
393
|
+
group: 'progress',
|
|
394
|
+
initialProgress: 58,
|
|
395
|
+
edgeStyle: 'flow',
|
|
396
|
+
colors: ['#21142D', '#7042FF', '#42F58D', '#C4FF8A']
|
|
397
|
+
}, {
|
|
398
|
+
id: 'tide',
|
|
399
|
+
code: 'NC-13',
|
|
400
|
+
name: 'TIDE',
|
|
401
|
+
subtitle: 'MOON PULL / COAST',
|
|
402
|
+
group: 'progress',
|
|
403
|
+
initialProgress: 30,
|
|
404
|
+
edgeStyle: 'tide',
|
|
405
|
+
colors: ['#0A2239', '#2E9BFF', '#7FE3FF', '#EAF9FF']
|
|
406
|
+
}];
|
|
407
|
+
|
|
408
|
+
[].concat(_toConsumableArray(CAPSULE_PRESETS), _toConsumableArray(PROGRESS_PRESETS));
|
|
409
|
+
function validatePreset(preset) {
|
|
410
|
+
return Boolean(preset && typeof preset.id === 'string' && typeof preset.code === 'string' && typeof preset.name === 'string' && Number.isFinite(preset.seed) && Number.isFinite(preset.speed) && Array.isArray(preset.colors) && preset.colors.length === 4);
|
|
411
|
+
}
|
|
412
|
+
function validateProgressPreset(preset) {
|
|
413
|
+
return Boolean(preset && typeof preset.id === 'string' && typeof preset.code === 'string' && typeof preset.name === 'string' && preset.group === 'progress' && Number.isFinite(preset.initialProgress) && ['flow', 'tide'].indexOf(preset.edgeStyle || 'flow') !== -1 && Array.isArray(preset.colors) && preset.colors.length === 4);
|
|
414
|
+
}
|
|
415
|
+
function getPreset(kind, ref) {
|
|
416
|
+
var list = kind === 'capsule' ? CAPSULE_PRESETS : kind === 'progress' ? PROGRESS_PRESETS : null;
|
|
417
|
+
if (!list) throw new Error("Unknown preset kind: ".concat(kind, " (use \"capsule\" or \"progress\")"));
|
|
418
|
+
if (ref && _typeof(ref) === 'object') {
|
|
419
|
+
var valid = kind === 'capsule' ? validatePreset(ref) : validateProgressPreset(ref);
|
|
420
|
+
if (!valid) throw new Error("Invalid ".concat(kind, " preset object"));
|
|
421
|
+
return ref;
|
|
422
|
+
}
|
|
423
|
+
var key = String(ref).trim().toLowerCase();
|
|
424
|
+
var found = list.find(function (preset) {
|
|
425
|
+
return preset.id.toLowerCase() === key || preset.code.toLowerCase() === key || preset.name.toLowerCase() === key;
|
|
426
|
+
});
|
|
427
|
+
if (!found) throw new Error("Unknown ".concat(kind, " preset: ").concat(ref));
|
|
428
|
+
return found;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
var DEFAULTS = {
|
|
432
|
+
capsule: {
|
|
433
|
+
width: '100%',
|
|
434
|
+
height: 160,
|
|
435
|
+
quality: 'auto',
|
|
436
|
+
renderer: 'auto',
|
|
437
|
+
respectReducedMotion: true,
|
|
438
|
+
interactive: true,
|
|
439
|
+
mouseColor: true,
|
|
440
|
+
showCopy: true
|
|
441
|
+
},
|
|
442
|
+
progress: {
|
|
443
|
+
width: 454,
|
|
444
|
+
height: 104,
|
|
445
|
+
min: 0,
|
|
446
|
+
max: 100,
|
|
447
|
+
draggable: true,
|
|
448
|
+
keyboard: true,
|
|
449
|
+
edgeStyle: 'flow',
|
|
450
|
+
quality: 'auto',
|
|
451
|
+
renderer: 'auto',
|
|
452
|
+
showCopy: true,
|
|
453
|
+
respectReducedMotion: true
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* All user-facing copy lives here so wording/brand changes never require a
|
|
459
|
+
* global search. Templates use {brand} {code} {name} placeholders.
|
|
460
|
+
*/
|
|
461
|
+
var COPY = {
|
|
462
|
+
brandName: '画境观屿',
|
|
463
|
+
dragLabel: 'DRAG',
|
|
464
|
+
valueSuffix: '%',
|
|
465
|
+
progressAria: '{brand} {code} 加载进度',
|
|
466
|
+
capsuleAria: '打开 {name} 沉浸预览'
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
function hexToRgb01$1(hex) {
|
|
470
|
+
var normalized = hex.replace('#', '');
|
|
471
|
+
var value = Number.parseInt(normalized, 16);
|
|
472
|
+
return [(value >> 16 & 255) / 255, (value >> 8 & 255) / 255, (value & 255) / 255];
|
|
473
|
+
}
|
|
474
|
+
function hexToRgba(hex) {
|
|
475
|
+
var alpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
476
|
+
var normalized = hex.replace('#', '');
|
|
477
|
+
var value = Number.parseInt(normalized, 16);
|
|
478
|
+
var red = value >> 16 & 255;
|
|
479
|
+
var green = value >> 8 & 255;
|
|
480
|
+
var blue = value & 255;
|
|
481
|
+
return "rgba(".concat(red, ", ").concat(green, ", ").concat(blue, ", ").concat(alpha, ")");
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
var VERTEX_SHADER$1 = "#version 300 es\nin vec2 a_position;\nout vec2 v_uv;\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}";
|
|
485
|
+
var FRAGMENT_SHADER$1 = "#version 300 es\nprecision highp float;\n\nin vec2 v_uv;\nout vec4 outColor;\n\nuniform vec2 u_resolution;\nuniform float u_time;\nuniform float u_seed;\nuniform float u_motion;\nuniform vec2 u_pointer;\nuniform vec3 u_colorA;\nuniform vec3 u_colorB;\nuniform vec3 u_colorC;\nuniform vec3 u_colorD;\n\nfloat hash21(vec2 p) {\n p = fract(p * vec2(123.34, 456.21));\n p += dot(p, p + 45.32 + u_seed);\n return fract(p.x * p.y);\n}\n\nfloat noise(vec2 p) {\n vec2 i = floor(p);\n vec2 f = fract(p);\n f = f * f * (3.0 - 2.0 * f);\n float a = hash21(i);\n float b = hash21(i + vec2(1.0, 0.0));\n float c = hash21(i + vec2(0.0, 1.0));\n float d = hash21(i + vec2(1.0, 1.0));\n return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);\n}\n\nfloat fbm(vec2 p) {\n float value = 0.0;\n float amplitude = 0.52;\n mat2 rotation = mat2(0.80, 0.60, -0.60, 0.80);\n for (int i = 0; i < 6; i++) {\n value += amplitude * noise(p);\n p = rotation * p * 2.03 + 17.7;\n amplitude *= 0.5;\n }\n return value;\n}\n\nfloat gaussian(float value, float center, float width) {\n return exp(-pow(value - center, 2.0) / max(width, 0.0001));\n}\n\nvec3 palette(float t) {\n t = clamp(t, 0.0, 1.0);\n vec3 shadow = mix(u_colorA, u_colorB, smoothstep(0.06, 0.62, t));\n vec3 body = mix(u_colorB, u_colorC, smoothstep(0.30, 0.82, t));\n vec3 highlight = mix(u_colorC, u_colorD, smoothstep(0.74, 1.0, t));\n vec3 restrained = mix(shadow, body, smoothstep(0.26, 0.72, t));\n return mix(restrained, highlight, smoothstep(0.78, 0.97, t));\n}\n\nvec3 renderNebula(vec2 uv, vec2 p, vec2 pointer, float distanceToPointer, float t) {\n vec2 delta = p - pointer;\n float influence = exp(-distanceToPointer * 4.6) * u_motion;\n float angle = influence * 1.7;\n mat2 swirl = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));\n p = pointer + swirl * delta;\n p += normalize(delta + 0.0001) * influence * 0.08;\n\n vec2 drift = vec2(t * 0.22, -t * 0.13);\n vec2 q = vec2(\n fbm(p * 1.35 + drift + u_seed),\n fbm(p * 1.35 + vec2(5.2, 1.3) - drift * 0.85)\n );\n vec2 r = vec2(\n fbm(p * 2.0 + 3.6 * q + vec2(1.7, 9.2) + t * 0.10),\n fbm(p * 2.0 + 3.0 * q + vec2(8.3, 2.8) - t * 0.085)\n );\n\n float cloud = fbm(p * 1.7 + 4.2 * r);\n float veins = fbm(p * 4.0 - 2.0 * q + t * 0.065);\n float nebula = smoothstep(0.18, 0.91, cloud * 0.9 + veins * 0.22);\n\n vec3 color = palette(nebula);\n color += u_colorD * pow(max(cloud - 0.63, 0.0), 2.0) * 1.05;\n color *= 0.78 + 0.34 * smoothstep(0.15, 0.9, veins);\n\n vec2 starGrid = floor((uv + vec2(u_seed * 0.013, 0.0)) * vec2(132.0, 58.0));\n vec2 starCell = fract(uv * vec2(132.0, 58.0)) - 0.5;\n float starRandom = hash21(starGrid);\n float starShape = smoothstep(0.075, 0.0, length(starCell));\n float starMask = step(0.989, starRandom) * starShape;\n float twinkle = 0.35 + 0.65 * sin(t * (1.0 + starRandom * 2.4) + starRandom * 40.0) * 0.5 + 0.5;\n color += starMask * twinkle * mix(u_colorC, u_colorD, starRandom) * 1.05;\n\n float pointerGlow = exp(-distanceToPointer * 7.0) * u_motion;\n color += u_colorD * pointerGlow * 0.28;\n return color;\n}\n\nvoid main() {\n vec2 uv = v_uv;\n vec2 p = uv - 0.5;\n p.x *= u_resolution.x / max(u_resolution.y, 1.0);\n\n vec2 pointer = u_pointer - 0.5;\n pointer.x *= u_resolution.x / max(u_resolution.y, 1.0);\n float distanceToPointer = length(p - pointer);\n\n vec3 color = renderNebula(uv, p, pointer, distanceToPointer, u_time);\n float vignette = smoothstep(0.94, 0.18, length((uv - 0.5) * vec2(1.0, 1.35)));\n color *= 0.70 + vignette * 0.42;\n color = pow(max(color, vec3(0.0)), vec3(0.88));\n\n outColor = vec4(color, 1.0);\n}";
|
|
486
|
+
function compileShader$1(gl, type, source) {
|
|
487
|
+
var shader = gl.createShader(type);
|
|
488
|
+
gl.shaderSource(shader, source);
|
|
489
|
+
gl.compileShader(shader);
|
|
490
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
491
|
+
var message = gl.getShaderInfoLog(shader) || 'Unknown shader compile error';
|
|
492
|
+
gl.deleteShader(shader);
|
|
493
|
+
throw new Error(message);
|
|
494
|
+
}
|
|
495
|
+
return shader;
|
|
496
|
+
}
|
|
497
|
+
function createProgram$1(gl) {
|
|
498
|
+
var vertex = compileShader$1(gl, gl.VERTEX_SHADER, VERTEX_SHADER$1);
|
|
499
|
+
var fragment = compileShader$1(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER$1);
|
|
500
|
+
var program = gl.createProgram();
|
|
501
|
+
gl.attachShader(program, vertex);
|
|
502
|
+
gl.attachShader(program, fragment);
|
|
503
|
+
gl.linkProgram(program);
|
|
504
|
+
gl.deleteShader(vertex);
|
|
505
|
+
gl.deleteShader(fragment);
|
|
506
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
507
|
+
var message = gl.getProgramInfoLog(program) || 'Unknown program link error';
|
|
508
|
+
gl.deleteProgram(program);
|
|
509
|
+
throw new Error(message);
|
|
510
|
+
}
|
|
511
|
+
return program;
|
|
512
|
+
}
|
|
513
|
+
var _CosmicRenderer_brand = /*#__PURE__*/new WeakSet();
|
|
514
|
+
var CosmicRenderer = /*#__PURE__*/function () {
|
|
515
|
+
function CosmicRenderer(canvas, preset) {
|
|
516
|
+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
517
|
+
_classCallCheck(this, CosmicRenderer);
|
|
518
|
+
_classPrivateMethodInitSpec(this, _CosmicRenderer_brand);
|
|
519
|
+
this.canvas = canvas;
|
|
520
|
+
this.preset = _objectSpread2({}, preset);
|
|
521
|
+
this.options = _objectSpread2({
|
|
522
|
+
dprCap: 1.75,
|
|
523
|
+
mouseColor: true
|
|
524
|
+
}, options);
|
|
525
|
+
this.gl = canvas.getContext('webgl2', {
|
|
526
|
+
alpha: false,
|
|
527
|
+
antialias: false,
|
|
528
|
+
depth: false,
|
|
529
|
+
powerPreference: 'high-performance',
|
|
530
|
+
preserveDrawingBuffer: false
|
|
531
|
+
});
|
|
532
|
+
if (!this.gl) throw new Error('WebGL2 is not available');
|
|
533
|
+
this.program = createProgram$1(this.gl);
|
|
534
|
+
this.locations = _assertClassBrand(_CosmicRenderer_brand, this, _getLocations).call(this);
|
|
535
|
+
this.pointer = [0.72, 0.45];
|
|
536
|
+
this.pointerTarget = _toConsumableArray(this.pointer);
|
|
537
|
+
this.motion = 0;
|
|
538
|
+
this.motionTarget = 0;
|
|
539
|
+
this.timeOffset = preset.seed * 0.73;
|
|
540
|
+
this.visible = true;
|
|
541
|
+
this.disposed = false;
|
|
542
|
+
_assertClassBrand(_CosmicRenderer_brand, this, _setupGeometry).call(this);
|
|
543
|
+
_assertClassBrand(_CosmicRenderer_brand, this, _bindEvents).call(this);
|
|
544
|
+
this.resize();
|
|
545
|
+
}
|
|
546
|
+
return _createClass(CosmicRenderer, [{
|
|
547
|
+
key: "setPreset",
|
|
548
|
+
value: function setPreset(preset) {
|
|
549
|
+
this.preset = _objectSpread2({}, preset);
|
|
550
|
+
this.timeOffset = preset.seed * 0.73;
|
|
551
|
+
}
|
|
552
|
+
}, {
|
|
553
|
+
key: "setDprCap",
|
|
554
|
+
value: function setDprCap(cap) {
|
|
555
|
+
this.options.dprCap = cap;
|
|
556
|
+
this.resize();
|
|
557
|
+
}
|
|
558
|
+
}, {
|
|
559
|
+
key: "randomize",
|
|
560
|
+
value: function randomize() {
|
|
561
|
+
this.preset.seed = Math.random() * 100;
|
|
562
|
+
this.timeOffset = Math.random() * 40;
|
|
563
|
+
}
|
|
564
|
+
}, {
|
|
565
|
+
key: "resize",
|
|
566
|
+
value: function resize() {
|
|
567
|
+
var dpr = Math.min(window.devicePixelRatio || 1, this.options.dprCap);
|
|
568
|
+
var rect = this.canvas.getBoundingClientRect();
|
|
569
|
+
var width = Math.max(2, Math.round(rect.width * dpr));
|
|
570
|
+
var height = Math.max(2, Math.round(rect.height * dpr));
|
|
571
|
+
if (this.canvas.width !== width || this.canvas.height !== height) {
|
|
572
|
+
this.canvas.width = width;
|
|
573
|
+
this.canvas.height = height;
|
|
574
|
+
this.gl.viewport(0, 0, width, height);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}, {
|
|
578
|
+
key: "draw",
|
|
579
|
+
value: function draw(elapsedSeconds) {
|
|
580
|
+
var paused = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
581
|
+
if (this.disposed || !this.visible) return;
|
|
582
|
+
this.resize();
|
|
583
|
+
var gl = this.gl;
|
|
584
|
+
this.pointer[0] += (this.pointerTarget[0] - this.pointer[0]) * 0.08;
|
|
585
|
+
this.pointer[1] += (this.pointerTarget[1] - this.pointer[1]) * 0.08;
|
|
586
|
+
this.motion += (this.motionTarget - this.motion) * 0.07;
|
|
587
|
+
gl.useProgram(this.program);
|
|
588
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
|
|
589
|
+
gl.enableVertexAttribArray(this.locations.position);
|
|
590
|
+
gl.vertexAttribPointer(this.locations.position, 2, gl.FLOAT, false, 0, 0);
|
|
591
|
+
var colors = this.preset.colors.map(hexToRgb01$1);
|
|
592
|
+
gl.uniform2f(this.locations.resolution, this.canvas.width, this.canvas.height);
|
|
593
|
+
gl.uniform1f(this.locations.time, this.timeOffset + (paused ? 0 : elapsedSeconds * this.preset.speed));
|
|
594
|
+
gl.uniform1f(this.locations.seed, this.preset.seed);
|
|
595
|
+
gl.uniform1f(this.locations.motion, this.motion);
|
|
596
|
+
gl.uniform2f(this.locations.pointer, this.pointer[0], this.pointer[1]);
|
|
597
|
+
gl.uniform3fv(this.locations.colorA, colors[0]);
|
|
598
|
+
gl.uniform3fv(this.locations.colorB, colors[1]);
|
|
599
|
+
gl.uniform3fv(this.locations.colorC, colors[2]);
|
|
600
|
+
gl.uniform3fv(this.locations.colorD, colors[3]);
|
|
601
|
+
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
602
|
+
}
|
|
603
|
+
}, {
|
|
604
|
+
key: "dispose",
|
|
605
|
+
value: function dispose() {
|
|
606
|
+
this.disposed = true;
|
|
607
|
+
var target = this.eventTarget || this.canvas;
|
|
608
|
+
target.removeEventListener('pointermove', this.onPointerMove);
|
|
609
|
+
target.removeEventListener('pointerdown', this.onPointerMove);
|
|
610
|
+
target.removeEventListener('pointerleave', this.onPointerLeave);
|
|
611
|
+
this.gl.deleteBuffer(this.buffer);
|
|
612
|
+
this.gl.deleteProgram(this.program);
|
|
613
|
+
var lose = this.gl.getExtension('WEBGL_lose_context');
|
|
614
|
+
if (lose) lose.loseContext();
|
|
615
|
+
}
|
|
616
|
+
}]);
|
|
617
|
+
}();
|
|
618
|
+
function _getLocations() {
|
|
619
|
+
var _this = this;
|
|
620
|
+
var gl = this.gl;
|
|
621
|
+
var uniform = function uniform(name) {
|
|
622
|
+
return gl.getUniformLocation(_this.program, name);
|
|
623
|
+
};
|
|
624
|
+
return {
|
|
625
|
+
position: gl.getAttribLocation(this.program, 'a_position'),
|
|
626
|
+
resolution: uniform('u_resolution'),
|
|
627
|
+
time: uniform('u_time'),
|
|
628
|
+
seed: uniform('u_seed'),
|
|
629
|
+
motion: uniform('u_motion'),
|
|
630
|
+
pointer: uniform('u_pointer'),
|
|
631
|
+
colorA: uniform('u_colorA'),
|
|
632
|
+
colorB: uniform('u_colorB'),
|
|
633
|
+
colorC: uniform('u_colorC'),
|
|
634
|
+
colorD: uniform('u_colorD')
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
function _setupGeometry() {
|
|
638
|
+
var gl = this.gl;
|
|
639
|
+
var vertices = new Float32Array([-1, -1, 3, -1, -1, 3]);
|
|
640
|
+
this.buffer = gl.createBuffer();
|
|
641
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
|
|
642
|
+
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
|
|
643
|
+
}
|
|
644
|
+
function _bindEvents() {
|
|
645
|
+
var _this2 = this;
|
|
646
|
+
if (this.options.mouseColor === false) return;
|
|
647
|
+
this.eventTarget = this.options.eventTarget || this.canvas.parentElement || this.canvas;
|
|
648
|
+
this.onPointerMove = function (event) {
|
|
649
|
+
var rect = _this2.canvas.getBoundingClientRect();
|
|
650
|
+
_this2.pointerTarget[0] = (event.clientX - rect.left) / Math.max(rect.width, 1);
|
|
651
|
+
_this2.pointerTarget[1] = 1 - (event.clientY - rect.top) / Math.max(rect.height, 1);
|
|
652
|
+
_this2.motionTarget = 1;
|
|
653
|
+
};
|
|
654
|
+
this.onPointerLeave = function () {
|
|
655
|
+
_this2.motionTarget = 0;
|
|
656
|
+
};
|
|
657
|
+
this.eventTarget.addEventListener('pointermove', this.onPointerMove, {
|
|
658
|
+
passive: true
|
|
659
|
+
});
|
|
660
|
+
this.eventTarget.addEventListener('pointerdown', this.onPointerMove, {
|
|
661
|
+
passive: true
|
|
662
|
+
});
|
|
663
|
+
this.eventTarget.addEventListener('pointerleave', this.onPointerLeave, {
|
|
664
|
+
passive: true
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
function rgb(color) {
|
|
669
|
+
var alpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
670
|
+
var _hexToRgb01$map = hexToRgb01$1(color).map(function (value) {
|
|
671
|
+
return Math.round(value * 255);
|
|
672
|
+
}),
|
|
673
|
+
_hexToRgb01$map2 = _slicedToArray(_hexToRgb01$map, 3),
|
|
674
|
+
r = _hexToRgb01$map2[0],
|
|
675
|
+
g = _hexToRgb01$map2[1],
|
|
676
|
+
b = _hexToRgb01$map2[2];
|
|
677
|
+
return "rgba(".concat(r, ", ").concat(g, ", ").concat(b, ", ").concat(alpha, ")");
|
|
678
|
+
}
|
|
679
|
+
var FallbackRenderer = /*#__PURE__*/function () {
|
|
680
|
+
function FallbackRenderer(canvas, preset) {
|
|
681
|
+
_classCallCheck(this, FallbackRenderer);
|
|
682
|
+
this.canvas = canvas;
|
|
683
|
+
this.preset = preset;
|
|
684
|
+
this.context = canvas.getContext('2d');
|
|
685
|
+
this.visible = true;
|
|
686
|
+
}
|
|
687
|
+
return _createClass(FallbackRenderer, [{
|
|
688
|
+
key: "resize",
|
|
689
|
+
value: function resize() {
|
|
690
|
+
var rect = this.canvas.getBoundingClientRect();
|
|
691
|
+
var dpr = Math.min(window.devicePixelRatio || 1, 1.5);
|
|
692
|
+
var width = Math.max(2, Math.round(rect.width * dpr));
|
|
693
|
+
var height = Math.max(2, Math.round(rect.height * dpr));
|
|
694
|
+
if (this.canvas.width !== width || this.canvas.height !== height) {
|
|
695
|
+
this.canvas.width = width;
|
|
696
|
+
this.canvas.height = height;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}, {
|
|
700
|
+
key: "drawNebula",
|
|
701
|
+
value: function drawNebula(time) {
|
|
702
|
+
var ctx = this.context;
|
|
703
|
+
var _this$canvas = this.canvas,
|
|
704
|
+
width = _this$canvas.width,
|
|
705
|
+
height = _this$canvas.height;
|
|
706
|
+
var gradient = ctx.createLinearGradient(0, 0, width, height);
|
|
707
|
+
gradient.addColorStop(0, this.preset.colors[0]);
|
|
708
|
+
gradient.addColorStop(0.38, this.preset.colors[1]);
|
|
709
|
+
gradient.addColorStop(0.72, this.preset.colors[2]);
|
|
710
|
+
gradient.addColorStop(1, this.preset.colors[3]);
|
|
711
|
+
ctx.fillStyle = gradient;
|
|
712
|
+
ctx.fillRect(0, 0, width, height);
|
|
713
|
+
ctx.globalCompositeOperation = 'screen';
|
|
714
|
+
for (var index = 0; index < 6; index += 1) {
|
|
715
|
+
var x = (0.5 + 0.45 * Math.sin(time * 0.32 + index * 1.7)) * width;
|
|
716
|
+
var y = (0.5 + 0.4 * Math.cos(time * 0.25 + index)) * height;
|
|
717
|
+
var radius = Math.max(width, height) * (0.08 + index % 3 * 0.04);
|
|
718
|
+
var glow = ctx.createRadialGradient(x, y, 0, x, y, radius);
|
|
719
|
+
glow.addColorStop(0, rgb(this.preset.colors[(index + 1) % 4], 0.24));
|
|
720
|
+
glow.addColorStop(1, rgb(this.preset.colors[index % 4], 0));
|
|
721
|
+
ctx.fillStyle = glow;
|
|
722
|
+
ctx.fillRect(x - radius, y - radius, radius * 2, radius * 2);
|
|
723
|
+
}
|
|
724
|
+
ctx.globalCompositeOperation = 'source-over';
|
|
725
|
+
}
|
|
726
|
+
}, {
|
|
727
|
+
key: "draw",
|
|
728
|
+
value: function draw(time) {
|
|
729
|
+
if (!this.visible) return;
|
|
730
|
+
this.resize();
|
|
731
|
+
this.drawNebula(time);
|
|
732
|
+
}
|
|
733
|
+
}, {
|
|
734
|
+
key: "setPreset",
|
|
735
|
+
value: function setPreset(preset) {
|
|
736
|
+
this.preset = preset;
|
|
737
|
+
}
|
|
738
|
+
}, {
|
|
739
|
+
key: "randomize",
|
|
740
|
+
value: function randomize() {}
|
|
741
|
+
}, {
|
|
742
|
+
key: "dispose",
|
|
743
|
+
value: function dispose() {}
|
|
744
|
+
}]);
|
|
745
|
+
}();
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Document-level shared rAF scheduler. Every component instance subscribes
|
|
749
|
+
* its own frame callback; the whole page runs ONE animation loop (like the
|
|
750
|
+
* original demo), which avoids jank from many competing rAF loops.
|
|
751
|
+
*/
|
|
752
|
+
var subscribers = [];
|
|
753
|
+
var running = false;
|
|
754
|
+
var rafId = 0;
|
|
755
|
+
var last = 0;
|
|
756
|
+
function tick(now) {
|
|
757
|
+
if (!running) return;
|
|
758
|
+
var delta = last ? Math.min((now - last) / 1000, 0.05) : 0;
|
|
759
|
+
last = now;
|
|
760
|
+
// Schedule the next frame BEFORE running callbacks so one throwing
|
|
761
|
+
// subscriber can never kill the whole animation loop.
|
|
762
|
+
rafId = requestAnimationFrame(tick);
|
|
763
|
+
{
|
|
764
|
+
var _iterator = _createForOfIteratorHelper(subscribers.slice()),
|
|
765
|
+
_step;
|
|
766
|
+
try {
|
|
767
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
768
|
+
var item = _step.value;
|
|
769
|
+
try {
|
|
770
|
+
if (!item.isPaused()) item.onFrame(delta, now);
|
|
771
|
+
} catch (error) {
|
|
772
|
+
console.warn('[dlc-ui] frame error:', error);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
} catch (err) {
|
|
776
|
+
_iterator.e(err);
|
|
777
|
+
} finally {
|
|
778
|
+
_iterator.f();
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
if (subscribers.length === 0) {
|
|
782
|
+
cancelAnimationFrame(rafId);
|
|
783
|
+
running = false;
|
|
784
|
+
rafId = 0;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
function start() {
|
|
788
|
+
if (running) return;
|
|
789
|
+
running = true;
|
|
790
|
+
last = 0;
|
|
791
|
+
rafId = requestAnimationFrame(tick);
|
|
792
|
+
}
|
|
793
|
+
function subscribeScheduler(onFrame, isPaused) {
|
|
794
|
+
var item = {
|
|
795
|
+
onFrame: onFrame,
|
|
796
|
+
isPaused: isPaused
|
|
797
|
+
};
|
|
798
|
+
subscribers.push(item);
|
|
799
|
+
start();
|
|
800
|
+
return function () {
|
|
801
|
+
var index = subscribers.indexOf(item);
|
|
802
|
+
if (index !== -1) subscribers.splice(index, 1);
|
|
803
|
+
if (subscribers.length === 0 && rafId) {
|
|
804
|
+
cancelAnimationFrame(rafId);
|
|
805
|
+
running = false;
|
|
806
|
+
rafId = 0;
|
|
807
|
+
}
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Gates drawing on "element intersects viewport AND the page tab is visible".
|
|
813
|
+
* Falls back to always-visible when IntersectionObserver is unavailable.
|
|
814
|
+
*/
|
|
815
|
+
function createVisibilityGuard(element) {
|
|
816
|
+
var intersecting = true;
|
|
817
|
+
var pageVisible = typeof document === 'undefined' || !document.hidden;
|
|
818
|
+
var disposed = false;
|
|
819
|
+
var observer = null;
|
|
820
|
+
if (typeof IntersectionObserver !== 'undefined') {
|
|
821
|
+
observer = new IntersectionObserver(function (entries) {
|
|
822
|
+
intersecting = entries.some(function (entry) {
|
|
823
|
+
return entry.isIntersecting;
|
|
824
|
+
});
|
|
825
|
+
}, {
|
|
826
|
+
rootMargin: '180px'
|
|
827
|
+
});
|
|
828
|
+
observer.observe(element);
|
|
829
|
+
}
|
|
830
|
+
var onVisibilityChange = function onVisibilityChange() {
|
|
831
|
+
pageVisible = typeof document !== 'undefined' && !document.hidden;
|
|
832
|
+
};
|
|
833
|
+
if (typeof document !== 'undefined') {
|
|
834
|
+
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
835
|
+
}
|
|
836
|
+
return {
|
|
837
|
+
isVisible: function isVisible() {
|
|
838
|
+
return intersecting && pageVisible;
|
|
839
|
+
},
|
|
840
|
+
dispose: function dispose() {
|
|
841
|
+
if (disposed) return;
|
|
842
|
+
disposed = true;
|
|
843
|
+
if (observer) observer.disconnect();
|
|
844
|
+
if (typeof document !== 'undefined') {
|
|
845
|
+
document.removeEventListener('visibilitychange', onVisibilityChange);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
function prefersReducedMotion$1() {
|
|
852
|
+
return typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
/**
|
|
856
|
+
* Mount a cosmic (nebula) capsule into `container`.
|
|
857
|
+
*
|
|
858
|
+
* Options: preset (id/code/name or object), width, height (number=px or
|
|
859
|
+
* string with px/%/vw/vh/em/rem), colors, seed, speed, quality, interactive,
|
|
860
|
+
* respectReducedMotion, copy, cssVars.
|
|
861
|
+
*/
|
|
862
|
+
function createCapsule(container) {
|
|
863
|
+
var _options$preset;
|
|
864
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
865
|
+
if (!container || typeof container.appendChild !== 'function') {
|
|
866
|
+
throw new Error('createCapsule: container element is required');
|
|
867
|
+
}
|
|
868
|
+
var preset = _objectSpread2({}, getPreset('capsule', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : 'NC-01'));
|
|
869
|
+
var merged = normalizeOptions(DEFAULTS.capsule, preset, options);
|
|
870
|
+
var copy = _objectSpread2(_objectSpread2({}, COPY), merged.copy || {});
|
|
871
|
+
var root = document.createElement('div');
|
|
872
|
+
root.className = 'hj-capsule-root hj-capsule-cosmic';
|
|
873
|
+
root.dataset.group = preset.group;
|
|
874
|
+
root.dataset.mode = 'nebula';
|
|
875
|
+
root.dataset.theme = preset.theme || 'light';
|
|
876
|
+
root.setAttribute('aria-label', copy.capsuleAria.replace('{name}', preset.name));
|
|
877
|
+
var copyEnabled = copy.enabled !== false && merged.showCopy !== false;
|
|
878
|
+
var copyText = function copyText(key, fallback) {
|
|
879
|
+
var value = copy[key];
|
|
880
|
+
return value === undefined ? fallback : value;
|
|
881
|
+
};
|
|
882
|
+
function buildCopyHtml() {
|
|
883
|
+
var codeText = copyText('code', preset.code);
|
|
884
|
+
var nameText = copyText('name', preset.name);
|
|
885
|
+
var subtitleText = copyText('subtitle', preset.subtitle);
|
|
886
|
+
var stateText = copyText('state', 'LIVE COSMIC STUDY');
|
|
887
|
+
var html = '';
|
|
888
|
+
if (codeText) html += "<span class=\"hj-capsule-code\">".concat(codeText, "</span>");
|
|
889
|
+
if (nameText) html += "<span class=\"hj-capsule-name\">".concat(nameText, "</span>");
|
|
890
|
+
if (subtitleText) html += "<span class=\"hj-capsule-brand\">".concat(subtitleText, "</span>");
|
|
891
|
+
if (stateText) html += "<span class=\"hj-capsule-state\">".concat(stateText, "</span>");
|
|
892
|
+
return html;
|
|
893
|
+
}
|
|
894
|
+
var copyLayer = document.createElement('div');
|
|
895
|
+
copyLayer.className = 'hj-capsule-copy';
|
|
896
|
+
var renderCopy = function renderCopy() {
|
|
897
|
+
if (copyEnabled) copyLayer.innerHTML = buildCopyHtml();
|
|
898
|
+
};
|
|
899
|
+
renderCopy();
|
|
900
|
+
var isHexColor = function isHexColor(value) {
|
|
901
|
+
return typeof value === 'string' && /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(value);
|
|
902
|
+
};
|
|
903
|
+
if (copy.background) {
|
|
904
|
+
root.style.setProperty('--hj-copy-bg', isHexColor(copy.background) ? "linear-gradient(90deg, ".concat(copy.background, " 0%, ").concat(copy.background, " 74%, ").concat(hexToRgba(copy.background, 0.97), " 84%, ").concat(hexToRgba(copy.background, 0), " 100%)") : copy.background);
|
|
905
|
+
}
|
|
906
|
+
if (copy.color) root.style.setProperty('--hj-copy-color', copy.color);
|
|
907
|
+
var canvas = document.createElement('canvas');
|
|
908
|
+
canvas.className = 'hj-capsule-canvas';
|
|
909
|
+
canvas.setAttribute('aria-hidden', 'true');
|
|
910
|
+
if (copyEnabled) root.appendChild(copyLayer);
|
|
911
|
+
root.appendChild(canvas);
|
|
912
|
+
container.appendChild(root);
|
|
913
|
+
var emitter = createEmitter();
|
|
914
|
+
var paused = merged.respectReducedMotion && prefersReducedMotion$1();
|
|
915
|
+
var renderer;
|
|
916
|
+
var useWebgl = merged.renderer !== 'canvas2d';
|
|
917
|
+
if (useWebgl) {
|
|
918
|
+
try {
|
|
919
|
+
renderer = new CosmicRenderer(canvas, merged, {
|
|
920
|
+
dprCap: dprCapFor(merged.quality)
|
|
921
|
+
});
|
|
922
|
+
} catch (error) {
|
|
923
|
+
renderer = new FallbackRenderer(canvas, merged);
|
|
924
|
+
emitter.emit('error', {
|
|
925
|
+
message: String(error && error.message ? error.message : error)
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
} else {
|
|
929
|
+
renderer = new FallbackRenderer(canvas, merged);
|
|
930
|
+
}
|
|
931
|
+
var applySize = function applySize() {
|
|
932
|
+
root.style.width = parseSize(merged.width);
|
|
933
|
+
root.style.height = parseSize(merged.height);
|
|
934
|
+
var vars = merged.cssVars || {};
|
|
935
|
+
for (var _i = 0, _Object$keys = Object.keys(vars); _i < _Object$keys.length; _i++) {
|
|
936
|
+
var name = _Object$keys[_i];
|
|
937
|
+
root.style.setProperty(name, vars[name]);
|
|
938
|
+
}
|
|
939
|
+
renderer.resize();
|
|
940
|
+
};
|
|
941
|
+
applySize();
|
|
942
|
+
var resizeObserver = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(function () {
|
|
943
|
+
return renderer.resize();
|
|
944
|
+
}) : null;
|
|
945
|
+
if (resizeObserver) resizeObserver.observe(root);else window.addEventListener('resize', renderer.resize);
|
|
946
|
+
var visibility = createVisibilityGuard(root);
|
|
947
|
+
if (merged.interactive !== false) {
|
|
948
|
+
root.addEventListener('pointerenter', function () {
|
|
949
|
+
return emitter.emit('pointerenter', {
|
|
950
|
+
preset: _objectSpread2({}, preset)
|
|
951
|
+
});
|
|
952
|
+
});
|
|
953
|
+
root.addEventListener('pointerleave', function () {
|
|
954
|
+
return emitter.emit('pointerleave', {
|
|
955
|
+
preset: _objectSpread2({}, preset)
|
|
956
|
+
});
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
root.addEventListener('click', function (event) {
|
|
960
|
+
emitter.emit('click', {
|
|
961
|
+
event: event,
|
|
962
|
+
preset: _objectSpread2({}, preset)
|
|
963
|
+
});
|
|
964
|
+
});
|
|
965
|
+
root.addEventListener('pointerdown', function (event) {
|
|
966
|
+
return emitter.emit('pointerdown', {
|
|
967
|
+
event: event,
|
|
968
|
+
preset: _objectSpread2({}, preset)
|
|
969
|
+
});
|
|
970
|
+
});
|
|
971
|
+
root.addEventListener('pointerup', function (event) {
|
|
972
|
+
return emitter.emit('pointerup', {
|
|
973
|
+
event: event,
|
|
974
|
+
preset: _objectSpread2({}, preset)
|
|
975
|
+
});
|
|
976
|
+
});
|
|
977
|
+
root.addEventListener('dblclick', function (event) {
|
|
978
|
+
return emitter.emit('dblclick', {
|
|
979
|
+
event: event,
|
|
980
|
+
preset: _objectSpread2({}, preset)
|
|
981
|
+
});
|
|
982
|
+
});
|
|
983
|
+
var animationTime = 0;
|
|
984
|
+
var unsubscribe = subscribeScheduler(function (delta) {
|
|
985
|
+
animationTime += delta;
|
|
986
|
+
if (visibility.isVisible()) renderer.draw(animationTime);
|
|
987
|
+
}, function () {
|
|
988
|
+
return paused;
|
|
989
|
+
});
|
|
990
|
+
emitter.emit('ready', {
|
|
991
|
+
preset: _objectSpread2({}, preset)
|
|
992
|
+
});
|
|
993
|
+
var syncCopy = function syncCopy() {
|
|
994
|
+
root.dataset.mode = 'nebula';
|
|
995
|
+
root.dataset.theme = preset.theme || 'light';
|
|
996
|
+
renderCopy();
|
|
997
|
+
};
|
|
998
|
+
return {
|
|
999
|
+
element: root,
|
|
1000
|
+
canvas: canvas,
|
|
1001
|
+
preset: preset,
|
|
1002
|
+
on: emitter.on,
|
|
1003
|
+
off: emitter.off,
|
|
1004
|
+
setPreset: function setPreset(ref) {
|
|
1005
|
+
var next = getPreset('capsule', ref);
|
|
1006
|
+
Object.assign(preset, next);
|
|
1007
|
+
renderer.setPreset(next);
|
|
1008
|
+
syncCopy();
|
|
1009
|
+
renderer.resize();
|
|
1010
|
+
emitter.emit('presetchange', {
|
|
1011
|
+
preset: _objectSpread2({}, next)
|
|
1012
|
+
});
|
|
1013
|
+
return this;
|
|
1014
|
+
},
|
|
1015
|
+
setColors: function setColors(colors) {
|
|
1016
|
+
if (!Array.isArray(colors) || colors.length !== 4) return this;
|
|
1017
|
+
preset.colors = colors;
|
|
1018
|
+
renderer.setPreset(_objectSpread2(_objectSpread2({}, preset), {}, {
|
|
1019
|
+
colors: colors
|
|
1020
|
+
}));
|
|
1021
|
+
return this;
|
|
1022
|
+
},
|
|
1023
|
+
setSize: function setSize(width, height) {
|
|
1024
|
+
if (width !== undefined) merged.width = width;
|
|
1025
|
+
if (height !== undefined) merged.height = height;
|
|
1026
|
+
applySize();
|
|
1027
|
+
return this;
|
|
1028
|
+
},
|
|
1029
|
+
randomize: function randomize() {
|
|
1030
|
+
renderer.randomize();
|
|
1031
|
+
return this;
|
|
1032
|
+
},
|
|
1033
|
+
pause: function pause() {
|
|
1034
|
+
paused = true;
|
|
1035
|
+
return this;
|
|
1036
|
+
},
|
|
1037
|
+
resume: function resume() {
|
|
1038
|
+
paused = false;
|
|
1039
|
+
return this;
|
|
1040
|
+
},
|
|
1041
|
+
setQuality: function setQuality(quality) {
|
|
1042
|
+
merged.quality = quality;
|
|
1043
|
+
if (typeof renderer.setDprCap === 'function') renderer.setDprCap(dprCapFor(quality));
|
|
1044
|
+
return this;
|
|
1045
|
+
},
|
|
1046
|
+
dispose: function dispose() {
|
|
1047
|
+
unsubscribe();
|
|
1048
|
+
visibility.dispose();
|
|
1049
|
+
if (resizeObserver) resizeObserver.disconnect();else window.removeEventListener('resize', renderer.resize);
|
|
1050
|
+
renderer.dispose();
|
|
1051
|
+
root.remove();
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
var PROGRESS_MOTION_WIDTH = 240;
|
|
1057
|
+
var PROGRESS_MOTION_HEIGHT = 80;
|
|
1058
|
+
var PROGRESS_MOTION_DURATION = 12.0;
|
|
1059
|
+
var PROGRESS_MOTION_MAX_PX = 40.0;
|
|
1060
|
+
var PROFILE_CONFIG = {
|
|
1061
|
+
'model-training': {
|
|
1062
|
+
seed: 0.37,
|
|
1063
|
+
broad: 0.58,
|
|
1064
|
+
middle: 0.25,
|
|
1065
|
+
detail: 0.13,
|
|
1066
|
+
lobe: 0.24
|
|
1067
|
+
},
|
|
1068
|
+
'agent-migration': {
|
|
1069
|
+
seed: 1.71,
|
|
1070
|
+
broad: 0.72,
|
|
1071
|
+
middle: 0.10,
|
|
1072
|
+
detail: 0.03,
|
|
1073
|
+
lobe: 0.18
|
|
1074
|
+
},
|
|
1075
|
+
'visual-training': {
|
|
1076
|
+
seed: 2.83,
|
|
1077
|
+
broad: 0.66,
|
|
1078
|
+
middle: 0.16,
|
|
1079
|
+
detail: 0.06,
|
|
1080
|
+
lobe: 0.23
|
|
1081
|
+
},
|
|
1082
|
+
// ponytail: first-pass tide = asymmetric time warp on the same motion pipeline.
|
|
1083
|
+
// Refine (foam line / wash streaks) in the shader after visual QA.
|
|
1084
|
+
'tide': {
|
|
1085
|
+
seed: 4.12,
|
|
1086
|
+
broad: 0.82,
|
|
1087
|
+
middle: 0.07,
|
|
1088
|
+
detail: 0.02,
|
|
1089
|
+
lobe: 0.30,
|
|
1090
|
+
warp: 0.5
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
var CACHE$1 = Object.create(null);
|
|
1094
|
+
function gaussian(value, center, width) {
|
|
1095
|
+
var delta = (value - center) / Math.max(width, 0.001);
|
|
1096
|
+
return Math.exp(-delta * delta);
|
|
1097
|
+
}
|
|
1098
|
+
function createMotionData(id) {
|
|
1099
|
+
var edgeStyle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'flow';
|
|
1100
|
+
var profile = edgeStyle === 'tide' ? PROFILE_CONFIG.tide : PROFILE_CONFIG[id] || PROFILE_CONFIG['visual-training'];
|
|
1101
|
+
var data = new Uint8Array(PROGRESS_MOTION_WIDTH * PROGRESS_MOTION_HEIGHT);
|
|
1102
|
+
for (var x = 0; x < PROGRESS_MOTION_WIDTH; x += 1) {
|
|
1103
|
+
var time = x / PROGRESS_MOTION_WIDTH * Math.PI * 2;
|
|
1104
|
+
if (profile.warp) time += profile.warp * Math.sin(time * 2);
|
|
1105
|
+
var centerA = 0.28 + Math.sin(time * 0.53 + profile.seed) * 0.13;
|
|
1106
|
+
var centerB = 0.70 + Math.cos(time * 0.47 + profile.seed * 1.7) * 0.12;
|
|
1107
|
+
for (var y = 0; y < PROGRESS_MOTION_HEIGHT; y += 1) {
|
|
1108
|
+
var ratio = y / Math.max(PROGRESS_MOTION_HEIGHT - 1, 1);
|
|
1109
|
+
var envelope = Math.pow(Math.max(Math.sin(Math.PI * ratio), 0), 0.48);
|
|
1110
|
+
var broad = Math.sin(ratio * Math.PI * 2 * 1.35 + time * 0.58 + profile.seed) * profile.broad;
|
|
1111
|
+
var middle = Math.sin(ratio * Math.PI * 2 * 3.2 - time * 0.91 + profile.seed * 2.1) * profile.middle;
|
|
1112
|
+
var detail = Math.sin(ratio * Math.PI * 2 * 6.1 + time * 1.31 + profile.seed * 3.2) * profile.detail;
|
|
1113
|
+
var lobes = (gaussian(ratio, centerA, 0.09) * Math.sin(time * 1.11 + profile.seed * 4.0) - gaussian(ratio, centerB, 0.10) * Math.cos(time * 0.97 + profile.seed * 3.3)) * profile.lobe;
|
|
1114
|
+
var normalized = Math.max(-1, Math.min(1, (broad + middle + detail + lobes) * envelope));
|
|
1115
|
+
data[y * PROGRESS_MOTION_WIDTH + x] = Math.round((normalized * 0.5 + 0.5) * 255);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
return data;
|
|
1119
|
+
}
|
|
1120
|
+
function getProgressMotionData(id) {
|
|
1121
|
+
var edgeStyle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'flow';
|
|
1122
|
+
var key = "".concat(id, ":").concat(edgeStyle);
|
|
1123
|
+
if (!CACHE$1[key]) CACHE$1[key] = createMotionData(id, edgeStyle);
|
|
1124
|
+
return CACHE$1[key];
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
function hexToRgb01(hex) {
|
|
1128
|
+
var value = Number.parseInt(hex.replace('#', ''), 16);
|
|
1129
|
+
return [(value >> 16 & 255) / 255, (value >> 8 & 255) / 255, (value & 255) / 255];
|
|
1130
|
+
}
|
|
1131
|
+
function stringSeed$1(value) {
|
|
1132
|
+
var hash = 2166136261;
|
|
1133
|
+
var _iterator = _createForOfIteratorHelper(value),
|
|
1134
|
+
_step;
|
|
1135
|
+
try {
|
|
1136
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
1137
|
+
var character = _step.value;
|
|
1138
|
+
hash ^= character.charCodeAt(0);
|
|
1139
|
+
hash = Math.imul(hash, 16777619);
|
|
1140
|
+
}
|
|
1141
|
+
} catch (err) {
|
|
1142
|
+
_iterator.e(err);
|
|
1143
|
+
} finally {
|
|
1144
|
+
_iterator.f();
|
|
1145
|
+
}
|
|
1146
|
+
return (hash >>> 0) / 4294967295;
|
|
1147
|
+
}
|
|
1148
|
+
var PROFILE_INDEX = {
|
|
1149
|
+
'model-training': 0,
|
|
1150
|
+
'agent-migration': 1,
|
|
1151
|
+
'visual-training': 2,
|
|
1152
|
+
'tide': 3
|
|
1153
|
+
};
|
|
1154
|
+
var MOTION_SCALE_FACTORS = {
|
|
1155
|
+
'model-training': 1.05,
|
|
1156
|
+
'agent-migration': 1.04,
|
|
1157
|
+
'visual-training': 1.04,
|
|
1158
|
+
'tide': 1.18
|
|
1159
|
+
};
|
|
1160
|
+
var VERTEX_SHADER = "#version 300 es\nin vec2 a_position;\nout vec2 v_uv;\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}";
|
|
1161
|
+
var FRAGMENT_SHADER = "#version 300 es\nprecision highp float;\n\nin vec2 v_uv;\nout vec4 outColor;\n\nuniform vec2 u_resolution;\nuniform float u_time;\nuniform float u_progress;\nuniform float u_seed;\nuniform float u_profile;\nuniform sampler2D u_motion;\nuniform sampler2D u_effect;\nuniform float u_hasEffect;\nuniform float u_effectFrames;\nuniform float u_motionDuration;\nuniform float u_motionScale;\nuniform vec3 u_dark;\nuniform vec3 u_accentA;\nuniform vec3 u_accentB;\nuniform vec3 u_glow;\n\nfloat hash21(vec2 p) {\n p = fract(p * vec2(123.34, 456.21));\n p += dot(p, p + 45.32 + u_seed * 11.7);\n return fract(p.x * p.y);\n}\n\nfloat noise(vec2 p) {\n vec2 i = floor(p);\n vec2 f = fract(p);\n f = f * f * (3.0 - 2.0 * f);\n float a = hash21(i);\n float b = hash21(i + vec2(1.0, 0.0));\n float c = hash21(i + vec2(0.0, 1.0));\n float d = hash21(i + vec2(1.0, 1.0));\n return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);\n}\n\nfloat fbm(vec2 p) {\n float value = 0.0;\n float amplitude = 0.55;\n mat2 rotation = mat2(0.82, 0.57, -0.57, 0.82);\n for (int i = 0; i < 6; i++) {\n value += noise(p) * amplitude;\n p = rotation * p * 2.02 + 13.7;\n amplitude *= 0.48;\n }\n return value;\n}\n\nfloat gaussian(float value, float center, float width) {\n float delta = (value - center) / max(width, 0.0001);\n return exp(-delta * delta);\n}\n\nfloat profileMix(float model, float agent, float visual) {\n if (u_profile < 0.5) return model;\n if (u_profile < 1.5) return agent;\n return visual;\n}\n\nfloat motionSample(float y, float t) {\n float phase = fract(t / max(u_motionDuration, 0.001));\n float captured = texture(u_motion, vec2(phase, 1.0 - clamp(y, 0.0, 1.0))).r;\n return (captured * 2.0 - 1.0) * u_motionScale;\n}\n\nfloat edgeDisplacement(float y, float t) {\n return motionSample(y, t);\n}\n\nfloat flowDisplacement(float y, float t) {\n return (\n motionSample(y - 0.024, t) * 0.08 +\n motionSample(y - 0.012, t) * 0.18 +\n motionSample(y, t) * 0.48 +\n motionSample(y + 0.012, t) * 0.18 +\n motionSample(y + 0.024, t) * 0.08\n );\n}\n\nfloat ellipseRing(vec2 p, float radius, float width) {\n return gaussian(length(p), radius, width);\n}\n\nvoid main() {\n vec2 uv = v_uv;\n float t = u_time;\n float edge = u_progress + edgeDisplacement(uv.y, t);\n float flowEdge = u_progress + flowDisplacement(uv.y, t);\n float d = uv.x - edge;\n float fd = uv.x - flowEdge;\n\n vec3 rightBase = vec3(0.125, 0.129, 0.145);\n vec3 color = rightBase;\n\n float leftMask = 1.0 - smoothstep(-0.001, 0.002, d);\n color = mix(color, u_dark, leftMask * profileMix(0.96, 0.92, 0.96));\n\n vec2 flowP = vec2((fd + 0.10) * 6.2, uv.y * 1.95);\n float flowA = fbm(flowP + vec2(-t * 0.22, t * 0.27) + u_seed * 1.7);\n float flowB = fbm(flowP * 1.52 + vec2(t * 0.28, -t * 0.36) + 8.2 + u_seed);\n float flowC = fbm(flowP * 2.25 + vec2(-t * 0.41, t * 0.46) + 19.0);\n\n float farCenter = profileMix(-0.060, -0.079, -0.045) + (flowA - 0.5) * profileMix(0.018, 0.022, 0.014);\n float midCenter = profileMix(-0.039, -0.052, -0.030) + (flowB - 0.5) * profileMix(0.013, 0.016, 0.010);\n float hotCenter = profileMix(-0.026, -0.029, -0.023) + (flowC - 0.5) * 0.010;\n\n float farBand = gaussian(fd, farCenter, profileMix(0.035, 0.049, 0.030));\n float midBand = gaussian(fd, midCenter, profileMix(0.026, 0.034, 0.026));\n float hotBand = gaussian(fd, hotCenter, profileMix(0.023, 0.027, 0.026));\n float darkTrough = gaussian(fd, profileMix(-0.050, -0.058, -0.044) + (flowB - 0.5) * 0.010, profileMix(0.020, 0.025, 0.021));\n\n float ringY = 0.47 + sin(t * 0.58 + u_seed * 2.4) * 0.12;\n vec2 ringP = vec2((fd + 0.086) / 0.078, (uv.y - ringY) / 0.25);\n ringP += vec2((flowB - 0.5) * 0.08, (flowA - 0.5) * 0.06);\n float ringTexture = fbm(ringP * 2.15 + vec2(t * 0.18, -t * 0.14) + u_seed * 1.9);\n float ring = ellipseRing(ringP, 0.66, 0.32) * (0.30 + 0.64 * ringTexture);\n float ringCore = gaussian(length(ringP), 0.25, 0.25);\n float ringPulse = smoothstep(0.58, 0.90, 0.5 + 0.5 * sin(t * 0.82 + u_seed * 4.1));\n float modelRing = ring * ringPulse * (1.0 - step(0.5, u_profile));\n float visualRing = ring * 0.16 * step(1.5, u_profile) * ringPulse;\n\n float cloudGate = leftMask * smoothstep(-0.30, -0.008, fd);\n float textureA = smoothstep(0.24, 0.92, flowA * 0.72 + flowB * 0.42);\n float textureB = smoothstep(0.28, 0.94, flowB * 0.68 + flowC * 0.38);\n\n vec3 hotColor = u_accentB;\n color += u_accentA * farBand * cloudGate * (0.07 + textureA * profileMix(0.42, 0.24, 0.40));\n color += u_accentB * midBand * cloudGate * (0.15 + textureB * profileMix(0.70, 0.46, 0.68));\n color += hotColor * hotBand * cloudGate * profileMix(0.88, 0.62, 0.84);\n float modelMask = 1.0 - step(0.5, u_profile);\n color += u_accentA * (modelRing + visualRing) * cloudGate * profileMix(0.54, 0.0, 0.34);\n color *= 1.0 - darkTrough * profileMix(0.44, 0.24, 0.24) * cloudGate;\n color *= 1.0 - ringCore * modelMask * ringPulse * 0.44 * cloudGate;\n\n float broadHalo = exp(-abs(d) * 96.0);\n float innerHalo = exp(-abs(d) * 176.0);\n float colorCore = exp(-abs(d) * 360.0);\n float sharpCore = exp(-abs(d) * 760.0);\n float leftGate = 1.0 - smoothstep(-0.003, 0.005, d);\n\n color += u_accentA * broadHalo * leftGate * profileMix(0.09, 0.04, 0.06);\n color += hotColor * innerHalo * leftGate * profileMix(0.76, 0.72, 0.78);\n color += u_glow * colorCore * profileMix(0.72, 0.34, 0.24);\n\n float whiteStrength = profileMix(0.10, 0.0, 0.0);\n color += vec3(1.0, 0.99, 0.91) * sharpCore * whiteStrength;\n\n float rightCut = smoothstep(0.001, 0.006, d);\n color = mix(color, rightBase, rightCut);\n\n float effectX = (d * 1257.0 + 260.0) / 320.0;\n float atlasPhase = fract(t / 12.0) * u_effectFrames;\n float atlasFrameA = floor(atlasPhase);\n float atlasFrameB = mod(atlasFrameA + 1.0, u_effectFrames);\n float atlasMix = smoothstep(0.0, 1.0, fract(atlasPhase));\n float atlasXA = (atlasFrameA + clamp(effectX, 0.0, 1.0)) / u_effectFrames;\n float atlasXB = (atlasFrameB + clamp(effectX, 0.0, 1.0)) / u_effectFrames;\n vec3 referenceA = texture(u_effect, vec2(atlasXA, uv.y)).rgb;\n vec3 referenceB = texture(u_effect, vec2(atlasXB, uv.y)).rgb;\n vec3 referenceColor = mix(referenceA, referenceB, atlasMix);\n float stripMask = smoothstep(0.0, 0.018, effectX) * (1.0 - smoothstep(0.982, 1.0, effectX));\n float referenceLeft = 1.0 - smoothstep(-0.026, -0.012, d);\n color = mix(color, referenceColor, stripMask * referenceLeft * u_hasEffect);\n\n outColor = vec4(clamp(color, 0.0, 1.0), 1.0);\n}";
|
|
1162
|
+
function compileShader(gl, type, source) {
|
|
1163
|
+
var shader = gl.createShader(type);
|
|
1164
|
+
gl.shaderSource(shader, source);
|
|
1165
|
+
gl.compileShader(shader);
|
|
1166
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
1167
|
+
var message = gl.getShaderInfoLog(shader) || 'Unknown shader compile error';
|
|
1168
|
+
gl.deleteShader(shader);
|
|
1169
|
+
throw new Error(message);
|
|
1170
|
+
}
|
|
1171
|
+
return shader;
|
|
1172
|
+
}
|
|
1173
|
+
function createProgram(gl) {
|
|
1174
|
+
var vertex = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER);
|
|
1175
|
+
var fragment = compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER);
|
|
1176
|
+
var program = gl.createProgram();
|
|
1177
|
+
gl.attachShader(program, vertex);
|
|
1178
|
+
gl.attachShader(program, fragment);
|
|
1179
|
+
gl.linkProgram(program);
|
|
1180
|
+
gl.deleteShader(vertex);
|
|
1181
|
+
gl.deleteShader(fragment);
|
|
1182
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
1183
|
+
var message = gl.getProgramInfoLog(program) || 'Unknown shader link error';
|
|
1184
|
+
gl.deleteProgram(program);
|
|
1185
|
+
throw new Error(message);
|
|
1186
|
+
}
|
|
1187
|
+
return program;
|
|
1188
|
+
}
|
|
1189
|
+
var ProgressFlowRenderer = /*#__PURE__*/function () {
|
|
1190
|
+
function ProgressFlowRenderer(canvas, preset) {
|
|
1191
|
+
var _PROFILE_INDEX$preset;
|
|
1192
|
+
_classCallCheck(this, ProgressFlowRenderer);
|
|
1193
|
+
var gl = canvas.getContext('webgl2', {
|
|
1194
|
+
alpha: false,
|
|
1195
|
+
antialias: true,
|
|
1196
|
+
premultipliedAlpha: false,
|
|
1197
|
+
powerPreference: 'high-performance'
|
|
1198
|
+
});
|
|
1199
|
+
if (!gl) throw new Error('WebGL2 unavailable');
|
|
1200
|
+
this.canvas = canvas;
|
|
1201
|
+
this.gl = gl;
|
|
1202
|
+
this.program = createProgram(gl);
|
|
1203
|
+
this.profile = preset.edgeStyle === 'tide' ? 3 : (_PROFILE_INDEX$preset = PROFILE_INDEX[preset.id]) !== null && _PROFILE_INDEX$preset !== void 0 ? _PROFILE_INDEX$preset : 2;
|
|
1204
|
+
this.seed = stringSeed$1("".concat(preset.id, "-shader")) * 13.7 + 1.0;
|
|
1205
|
+
this.colors = preset.colors.map(hexToRgb01);
|
|
1206
|
+
this.motionData = getProgressMotionData(preset.id, preset.edgeStyle);
|
|
1207
|
+
var motionFactor = preset.edgeStyle === 'tide' ? MOTION_SCALE_FACTORS.tide : MOTION_SCALE_FACTORS[preset.id] || 1.04;
|
|
1208
|
+
this.motionScale = PROGRESS_MOTION_MAX_PX * motionFactor / 1257;
|
|
1209
|
+
this.position = gl.getAttribLocation(this.program, 'a_position');
|
|
1210
|
+
this.uniforms = {
|
|
1211
|
+
resolution: gl.getUniformLocation(this.program, 'u_resolution'),
|
|
1212
|
+
time: gl.getUniformLocation(this.program, 'u_time'),
|
|
1213
|
+
progress: gl.getUniformLocation(this.program, 'u_progress'),
|
|
1214
|
+
seed: gl.getUniformLocation(this.program, 'u_seed'),
|
|
1215
|
+
profile: gl.getUniformLocation(this.program, 'u_profile'),
|
|
1216
|
+
motion: gl.getUniformLocation(this.program, 'u_motion'),
|
|
1217
|
+
effect: gl.getUniformLocation(this.program, 'u_effect'),
|
|
1218
|
+
hasEffect: gl.getUniformLocation(this.program, 'u_hasEffect'),
|
|
1219
|
+
effectFrames: gl.getUniformLocation(this.program, 'u_effectFrames'),
|
|
1220
|
+
motionDuration: gl.getUniformLocation(this.program, 'u_motionDuration'),
|
|
1221
|
+
motionScale: gl.getUniformLocation(this.program, 'u_motionScale'),
|
|
1222
|
+
dark: gl.getUniformLocation(this.program, 'u_dark'),
|
|
1223
|
+
accentA: gl.getUniformLocation(this.program, 'u_accentA'),
|
|
1224
|
+
accentB: gl.getUniformLocation(this.program, 'u_accentB'),
|
|
1225
|
+
glow: gl.getUniformLocation(this.program, 'u_glow')
|
|
1226
|
+
};
|
|
1227
|
+
this.buffer = gl.createBuffer();
|
|
1228
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
|
|
1229
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]), gl.STATIC_DRAW);
|
|
1230
|
+
this.motionTexture = gl.createTexture();
|
|
1231
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
1232
|
+
gl.bindTexture(gl.TEXTURE_2D, this.motionTexture);
|
|
1233
|
+
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
|
|
1234
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, PROGRESS_MOTION_WIDTH, PROGRESS_MOTION_HEIGHT, 0, gl.RED, gl.UNSIGNED_BYTE, this.motionData);
|
|
1235
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
1236
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
1237
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
|
|
1238
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
1239
|
+
this.effectTexture = gl.createTexture();
|
|
1240
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
1241
|
+
gl.bindTexture(gl.TEXTURE_2D, this.effectTexture);
|
|
1242
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, new Uint8Array([32, 33, 38]));
|
|
1243
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
1244
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
1245
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
1246
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
1247
|
+
this.effectUploaded = false;
|
|
1248
|
+
}
|
|
1249
|
+
return _createClass(ProgressFlowRenderer, [{
|
|
1250
|
+
key: "resize",
|
|
1251
|
+
value: function resize(width, height, dpr) {
|
|
1252
|
+
var pixelWidth = Math.max(1, Math.round(width * dpr));
|
|
1253
|
+
var pixelHeight = Math.max(1, Math.round(height * dpr));
|
|
1254
|
+
if (this.canvas.width !== pixelWidth || this.canvas.height !== pixelHeight) {
|
|
1255
|
+
this.canvas.width = pixelWidth;
|
|
1256
|
+
this.canvas.height = pixelHeight;
|
|
1257
|
+
}
|
|
1258
|
+
this.gl.viewport(0, 0, pixelWidth, pixelHeight);
|
|
1259
|
+
}
|
|
1260
|
+
}, {
|
|
1261
|
+
key: "draw",
|
|
1262
|
+
value: function draw(time, progress) {
|
|
1263
|
+
var effectImage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
|
1264
|
+
var gl = this.gl;
|
|
1265
|
+
gl.useProgram(this.program);
|
|
1266
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
|
|
1267
|
+
gl.enableVertexAttribArray(this.position);
|
|
1268
|
+
gl.vertexAttribPointer(this.position, 2, gl.FLOAT, false, 0, 0);
|
|
1269
|
+
gl.uniform2f(this.uniforms.resolution, this.canvas.width, this.canvas.height);
|
|
1270
|
+
gl.uniform1f(this.uniforms.time, time);
|
|
1271
|
+
gl.uniform1f(this.uniforms.progress, progress / 100);
|
|
1272
|
+
gl.uniform1f(this.uniforms.seed, this.seed);
|
|
1273
|
+
gl.uniform1f(this.uniforms.profile, this.profile);
|
|
1274
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
1275
|
+
gl.bindTexture(gl.TEXTURE_2D, this.motionTexture);
|
|
1276
|
+
gl.uniform1i(this.uniforms.motion, 0);
|
|
1277
|
+
gl.uniform1f(this.uniforms.motionDuration, PROGRESS_MOTION_DURATION);
|
|
1278
|
+
gl.uniform1f(this.uniforms.motionScale, this.motionScale);
|
|
1279
|
+
var hasEffect = this.effectUploaded ? 1 : 0;
|
|
1280
|
+
if (!this.effectUploaded && effectImage && effectImage.complete && effectImage.naturalWidth > 0) {
|
|
1281
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
1282
|
+
gl.bindTexture(gl.TEXTURE_2D, this.effectTexture);
|
|
1283
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
|
1284
|
+
try {
|
|
1285
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, effectImage);
|
|
1286
|
+
this.effectUploaded = true;
|
|
1287
|
+
hasEffect = 1;
|
|
1288
|
+
} catch (error) {
|
|
1289
|
+
console.warn('[画境观屿] 参考纹理图集上传失败,继续使用程序化降级。', error);
|
|
1290
|
+
}
|
|
1291
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
1292
|
+
}
|
|
1293
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
1294
|
+
gl.bindTexture(gl.TEXTURE_2D, this.effectTexture);
|
|
1295
|
+
gl.uniform1i(this.uniforms.effect, 1);
|
|
1296
|
+
gl.uniform1f(this.uniforms.hasEffect, hasEffect);
|
|
1297
|
+
gl.uniform1f(this.uniforms.effectFrames, 24);
|
|
1298
|
+
gl.uniform3fv(this.uniforms.dark, this.colors[0]);
|
|
1299
|
+
gl.uniform3fv(this.uniforms.accentA, this.colors[1]);
|
|
1300
|
+
gl.uniform3fv(this.uniforms.accentB, this.colors[2]);
|
|
1301
|
+
gl.uniform3fv(this.uniforms.glow, this.colors[3]);
|
|
1302
|
+
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
1303
|
+
}
|
|
1304
|
+
}, {
|
|
1305
|
+
key: "setColors",
|
|
1306
|
+
value: function setColors(colors) {
|
|
1307
|
+
this.colors = colors.map(hexToRgb01);
|
|
1308
|
+
}
|
|
1309
|
+
}, {
|
|
1310
|
+
key: "dispose",
|
|
1311
|
+
value: function dispose() {
|
|
1312
|
+
var gl = this.gl;
|
|
1313
|
+
gl.deleteBuffer(this.buffer);
|
|
1314
|
+
gl.deleteTexture(this.motionTexture);
|
|
1315
|
+
gl.deleteTexture(this.effectTexture);
|
|
1316
|
+
gl.deleteProgram(this.program);
|
|
1317
|
+
var lose = gl.getExtension('WEBGL_lose_context');
|
|
1318
|
+
if (lose) lose.loseContext();
|
|
1319
|
+
}
|
|
1320
|
+
}]);
|
|
1321
|
+
}();
|
|
1322
|
+
function createProgressFlowRenderer(canvas, preset) {
|
|
1323
|
+
try {
|
|
1324
|
+
return new ProgressFlowRenderer(canvas, preset);
|
|
1325
|
+
} catch (error) {
|
|
1326
|
+
console.warn('[画境观屿] 进度流体 WebGL2 不可用,使用 Canvas 2D 降级。', error);
|
|
1327
|
+
return null;
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
var PROGRESS_REFERENCE_DURATION = 12;
|
|
1332
|
+
var PROGRESS_REFERENCE_FRAME_COUNT = 24;
|
|
1333
|
+
var FRAME_WIDTH = 64;
|
|
1334
|
+
var FRAME_HEIGHT = 32;
|
|
1335
|
+
var CACHE = Object.create(null);
|
|
1336
|
+
var PALETTES = {
|
|
1337
|
+
'model-training': ['#20131f', '#ff3f94', '#ff8a3d', '#fff06a'],
|
|
1338
|
+
'agent-migration': ['#111a31', '#245bff', '#00cfff', '#5dffe6'],
|
|
1339
|
+
'visual-training': ['#1f172b', '#7042ff', '#42f58d', '#c4ff8a'],
|
|
1340
|
+
'tide': ['#0a2239', '#2e9bff', '#7fe3ff', '#eaf9ff']
|
|
1341
|
+
};
|
|
1342
|
+
function drawCloud(context, x, y, radiusX, radiusY, color, alpha) {
|
|
1343
|
+
context.save();
|
|
1344
|
+
context.translate(x, y);
|
|
1345
|
+
context.scale(1, radiusY / radiusX);
|
|
1346
|
+
var gradient = context.createRadialGradient(0, 0, 0, 0, 0, radiusX);
|
|
1347
|
+
gradient.addColorStop(0, "".concat(color).concat(Math.round(alpha * 255).toString(16).padStart(2, '0')));
|
|
1348
|
+
gradient.addColorStop(0.46, "".concat(color).concat(Math.round(alpha * 0.42 * 255).toString(16).padStart(2, '0')));
|
|
1349
|
+
gradient.addColorStop(1, "".concat(color, "00"));
|
|
1350
|
+
context.fillStyle = gradient;
|
|
1351
|
+
context.fillRect(-radiusX, -radiusX, radiusX * 2, radiusX * 2);
|
|
1352
|
+
context.restore();
|
|
1353
|
+
}
|
|
1354
|
+
function createAtlas(id) {
|
|
1355
|
+
var palette = PALETTES[id] || PALETTES['visual-training'];
|
|
1356
|
+
var canvas = document.createElement('canvas');
|
|
1357
|
+
canvas.width = FRAME_WIDTH * PROGRESS_REFERENCE_FRAME_COUNT;
|
|
1358
|
+
canvas.height = FRAME_HEIGHT;
|
|
1359
|
+
var context = canvas.getContext('2d');
|
|
1360
|
+
for (var frame = 0; frame < PROGRESS_REFERENCE_FRAME_COUNT; frame += 1) {
|
|
1361
|
+
var phase = frame / PROGRESS_REFERENCE_FRAME_COUNT * Math.PI * 2;
|
|
1362
|
+
var left = frame * FRAME_WIDTH;
|
|
1363
|
+
context.save();
|
|
1364
|
+
context.translate(left, 0);
|
|
1365
|
+
context.fillStyle = palette[0];
|
|
1366
|
+
context.fillRect(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
|
|
1367
|
+
context.globalCompositeOperation = 'screen';
|
|
1368
|
+
drawCloud(context, 35 + Math.sin(phase * 0.83) * 5, 10 + Math.cos(phase * 0.61) * 5, 27, 18, palette[1], id === 'agent-migration' ? 0.32 : 0.42);
|
|
1369
|
+
drawCloud(context, 45 + Math.cos(phase * 0.72) * 4, 23 + Math.sin(phase * 0.54) * 4, 22, 15, palette[2], 0.44);
|
|
1370
|
+
drawCloud(context, 53 + Math.sin(phase * 1.07) * 2, 16 + Math.cos(phase * 0.89) * 6, 12, 13, palette[3], id === 'model-training' ? 0.30 : 0.20);
|
|
1371
|
+
context.globalCompositeOperation = 'source-over';
|
|
1372
|
+
var trough = context.createRadialGradient(41, 16, 1, 41, 16, 17);
|
|
1373
|
+
trough.addColorStop(0, 'rgba(5,6,11,0.64)');
|
|
1374
|
+
trough.addColorStop(0.58, 'rgba(6,7,12,0.26)');
|
|
1375
|
+
trough.addColorStop(1, 'rgba(6,7,12,0)');
|
|
1376
|
+
context.fillStyle = trough;
|
|
1377
|
+
context.fillRect(20, 0, 44, FRAME_HEIGHT);
|
|
1378
|
+
context.restore();
|
|
1379
|
+
}
|
|
1380
|
+
var image = new Image();
|
|
1381
|
+
image.decoding = 'async';
|
|
1382
|
+
var state = {
|
|
1383
|
+
image: image,
|
|
1384
|
+
ready: false
|
|
1385
|
+
};
|
|
1386
|
+
image.addEventListener('load', function () {
|
|
1387
|
+
state.ready = true;
|
|
1388
|
+
}, {
|
|
1389
|
+
once: true
|
|
1390
|
+
});
|
|
1391
|
+
image.addEventListener('error', function () {
|
|
1392
|
+
state.ready = false;
|
|
1393
|
+
}, {
|
|
1394
|
+
once: true
|
|
1395
|
+
});
|
|
1396
|
+
image.src = canvas.toDataURL('image/png');
|
|
1397
|
+
return state;
|
|
1398
|
+
}
|
|
1399
|
+
function getProgressReferenceAtlas(id) {
|
|
1400
|
+
if (!CACHE[id]) CACHE[id] = createAtlas(id);
|
|
1401
|
+
return CACHE[id];
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
/**
|
|
1405
|
+
* Attach a WebGL2 fluid overlay to a progress capsule root.
|
|
1406
|
+
*
|
|
1407
|
+
* @param {object} params
|
|
1408
|
+
* @param {HTMLElement} params.root progress capsule root element
|
|
1409
|
+
* @param {HTMLCanvasElement} params.canvas 2D fallback canvas (kept beneath)
|
|
1410
|
+
* @param {object} params.preset progress preset
|
|
1411
|
+
* @param {() => number} params.getProgress reads the current progress value
|
|
1412
|
+
* @returns {{ update(flowTime: number): void, dispose(): void } | null}
|
|
1413
|
+
*/
|
|
1414
|
+
function attachProgressFlowOverlay(_ref) {
|
|
1415
|
+
var root = _ref.root,
|
|
1416
|
+
canvas = _ref.canvas,
|
|
1417
|
+
preset = _ref.preset,
|
|
1418
|
+
getProgress = _ref.getProgress;
|
|
1419
|
+
var overlay = document.createElement('canvas');
|
|
1420
|
+
overlay.className = 'hj-progress-canvas hj-progress-overlay';
|
|
1421
|
+
overlay.setAttribute('aria-hidden', 'true');
|
|
1422
|
+
canvas.insertAdjacentElement('afterend', overlay);
|
|
1423
|
+
var renderer = createProgressFlowRenderer(overlay, preset);
|
|
1424
|
+
if (!renderer) {
|
|
1425
|
+
overlay.remove();
|
|
1426
|
+
return null;
|
|
1427
|
+
}
|
|
1428
|
+
var atlas = getProgressReferenceAtlas(preset.id);
|
|
1429
|
+
root.classList.add('has-webgl-progress');
|
|
1430
|
+
var resize = function resize() {
|
|
1431
|
+
var bounds = root.getBoundingClientRect();
|
|
1432
|
+
var width = Math.max(1, bounds.width);
|
|
1433
|
+
var height = Math.max(1, bounds.height);
|
|
1434
|
+
var dpr = Math.min(window.devicePixelRatio || 1, 2);
|
|
1435
|
+
overlay.style.width = "".concat(width, "px");
|
|
1436
|
+
overlay.style.height = "".concat(height, "px");
|
|
1437
|
+
renderer.resize(width, height, dpr);
|
|
1438
|
+
};
|
|
1439
|
+
var resizeObserver = null;
|
|
1440
|
+
var onWindowResize = null;
|
|
1441
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
1442
|
+
resizeObserver = new ResizeObserver(resize);
|
|
1443
|
+
resizeObserver.observe(root);
|
|
1444
|
+
} else {
|
|
1445
|
+
onWindowResize = resize;
|
|
1446
|
+
window.addEventListener('resize', onWindowResize);
|
|
1447
|
+
}
|
|
1448
|
+
resize();
|
|
1449
|
+
return {
|
|
1450
|
+
update: function update(flowTime) {
|
|
1451
|
+
var effectTime = flowTime % PROGRESS_REFERENCE_DURATION;
|
|
1452
|
+
var progress = getProgress();
|
|
1453
|
+
renderer.draw(effectTime, Number.isFinite(progress) ? progress : preset.initialProgress, atlas.ready ? atlas.image : null);
|
|
1454
|
+
},
|
|
1455
|
+
setColors: function setColors(colors) {
|
|
1456
|
+
renderer.setColors(colors);
|
|
1457
|
+
},
|
|
1458
|
+
dispose: function dispose() {
|
|
1459
|
+
if (resizeObserver) resizeObserver.disconnect();
|
|
1460
|
+
if (onWindowResize) window.removeEventListener('resize', onWindowResize);
|
|
1461
|
+
renderer.dispose();
|
|
1462
|
+
overlay.remove();
|
|
1463
|
+
root.classList.remove('has-webgl-progress');
|
|
1464
|
+
}
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
var clamp = function clamp(value, min, max) {
|
|
1469
|
+
return Math.min(Math.max(value, min), max);
|
|
1470
|
+
};
|
|
1471
|
+
var SUPPORTS_CTX_FILTER = typeof CanvasRenderingContext2D !== 'undefined' && 'filter' in CanvasRenderingContext2D.prototype;
|
|
1472
|
+
function stringSeed(value) {
|
|
1473
|
+
var hash = 2166136261;
|
|
1474
|
+
var _iterator = _createForOfIteratorHelper(value),
|
|
1475
|
+
_step;
|
|
1476
|
+
try {
|
|
1477
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
1478
|
+
var character = _step.value;
|
|
1479
|
+
hash ^= character.charCodeAt(0);
|
|
1480
|
+
hash = Math.imul(hash, 16777619);
|
|
1481
|
+
}
|
|
1482
|
+
} catch (err) {
|
|
1483
|
+
_iterator.e(err);
|
|
1484
|
+
} finally {
|
|
1485
|
+
_iterator.f();
|
|
1486
|
+
}
|
|
1487
|
+
return (hash >>> 0) / 4294967295;
|
|
1488
|
+
}
|
|
1489
|
+
function interpolate(template, values) {
|
|
1490
|
+
return template.replace(/\{(\w+)\}/g, function (_, key) {
|
|
1491
|
+
return values[key] !== undefined ? values[key] : '';
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
function prefersReducedMotion() {
|
|
1495
|
+
return typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
1496
|
+
}
|
|
1497
|
+
var FLOW_PROFILES = {
|
|
1498
|
+
'model-training': {
|
|
1499
|
+
cycles: [0.98, 3.05, 5.45],
|
|
1500
|
+
amplitudes: [11.2, 11.0, 5.2],
|
|
1501
|
+
speeds: [0.31, -0.53, 0.78],
|
|
1502
|
+
bulgeAmplitude: 8.2,
|
|
1503
|
+
timeScale: 1.0,
|
|
1504
|
+
glowWidth: 5.8,
|
|
1505
|
+
haloWidth: 20,
|
|
1506
|
+
whiteAlpha: 0.72,
|
|
1507
|
+
whiteWidth: 1.15,
|
|
1508
|
+
cloudWidth: 0.17,
|
|
1509
|
+
autoRange: [25, 66]
|
|
1510
|
+
},
|
|
1511
|
+
'agent-migration': {
|
|
1512
|
+
cycles: [0.62, 1.55, 2.95],
|
|
1513
|
+
amplitudes: [16.0, 7.8, 2.3],
|
|
1514
|
+
speeds: [0.25, -0.4, 0.60],
|
|
1515
|
+
bulgeAmplitude: 8.4,
|
|
1516
|
+
timeScale: 0.82,
|
|
1517
|
+
glowWidth: 6.3,
|
|
1518
|
+
haloWidth: 21,
|
|
1519
|
+
whiteAlpha: 0.18,
|
|
1520
|
+
whiteWidth: 0.45,
|
|
1521
|
+
cloudWidth: 0.18,
|
|
1522
|
+
autoRange: [24, 62]
|
|
1523
|
+
},
|
|
1524
|
+
'visual-training': {
|
|
1525
|
+
cycles: [0.88, 2.45, 4.35],
|
|
1526
|
+
amplitudes: [12.8, 10.2, 4.3],
|
|
1527
|
+
speeds: [0.28, -0.47, 0.69],
|
|
1528
|
+
bulgeAmplitude: 7.3,
|
|
1529
|
+
timeScale: 0.91,
|
|
1530
|
+
glowWidth: 6.0,
|
|
1531
|
+
haloWidth: 21,
|
|
1532
|
+
whiteAlpha: 0.30,
|
|
1533
|
+
whiteWidth: 0.55,
|
|
1534
|
+
cloudWidth: 0.175,
|
|
1535
|
+
autoRange: [20, 75]
|
|
1536
|
+
},
|
|
1537
|
+
// ponytail: first-pass tide = asymmetric surge on the 2D fallback path.
|
|
1538
|
+
// Tune surge/amplitudes after visual QA against the WebGL overlay.
|
|
1539
|
+
'tide': {
|
|
1540
|
+
cycles: [0.72, 1.9, 4.2],
|
|
1541
|
+
amplitudes: [19.0, 6.5, 1.5],
|
|
1542
|
+
speeds: [0.42, -0.5, 0.66],
|
|
1543
|
+
bulgeAmplitude: 9.5,
|
|
1544
|
+
timeScale: 0.85,
|
|
1545
|
+
glowWidth: 6.2,
|
|
1546
|
+
haloWidth: 21,
|
|
1547
|
+
whiteAlpha: 0.5,
|
|
1548
|
+
whiteWidth: 1.0,
|
|
1549
|
+
cloudWidth: 0.18,
|
|
1550
|
+
autoRange: [18, 70],
|
|
1551
|
+
surge: 0.55
|
|
1552
|
+
}
|
|
1553
|
+
};
|
|
1554
|
+
var ProgressCapsuleController = /*#__PURE__*/function () {
|
|
1555
|
+
function ProgressCapsuleController(_ref) {
|
|
1556
|
+
var _options$min,
|
|
1557
|
+
_options$max,
|
|
1558
|
+
_options$value,
|
|
1559
|
+
_this = this;
|
|
1560
|
+
var root = _ref.root,
|
|
1561
|
+
canvas = _ref.canvas,
|
|
1562
|
+
valueElement = _ref.valueElement,
|
|
1563
|
+
preset = _ref.preset,
|
|
1564
|
+
emitter = _ref.emitter,
|
|
1565
|
+
options = _ref.options,
|
|
1566
|
+
copy = _ref.copy;
|
|
1567
|
+
_classCallCheck(this, ProgressCapsuleController);
|
|
1568
|
+
this.root = root;
|
|
1569
|
+
this.canvas = canvas;
|
|
1570
|
+
this.valueElement = valueElement;
|
|
1571
|
+
this.preset = preset;
|
|
1572
|
+
this.emitter = emitter;
|
|
1573
|
+
this.options = options;
|
|
1574
|
+
this.copy = copy;
|
|
1575
|
+
this.profile = preset.edgeStyle === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[preset.id] || FLOW_PROFILES['visual-training'];
|
|
1576
|
+
this.min = (_options$min = options.min) !== null && _options$min !== void 0 ? _options$min : 0;
|
|
1577
|
+
this.max = (_options$max = options.max) !== null && _options$max !== void 0 ? _options$max : 100;
|
|
1578
|
+
this.dprCap = dprCapFor(options.quality);
|
|
1579
|
+
this.ctx = canvas.getContext('2d');
|
|
1580
|
+
this.value = clamp((_options$value = options.value) !== null && _options$value !== void 0 ? _options$value : preset.initialProgress, this.min, this.max);
|
|
1581
|
+
this.dragging = false;
|
|
1582
|
+
this.webglActive = false;
|
|
1583
|
+
this.flowTime = stringSeed(preset.id) * 31;
|
|
1584
|
+
this.seed = stringSeed("".concat(preset.id, "-reference")) * Math.PI * 2;
|
|
1585
|
+
this.randomState = Math.floor(stringSeed("".concat(preset.id, "-auto")) * 0x7fffffff) || 1;
|
|
1586
|
+
this.dpr = 1;
|
|
1587
|
+
this.width = 0;
|
|
1588
|
+
this.height = 0;
|
|
1589
|
+
this.handlers = {};
|
|
1590
|
+
this.resizeObserver = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(function () {
|
|
1591
|
+
return _this.resizeCanvas();
|
|
1592
|
+
}) : null;
|
|
1593
|
+
if (this.resizeObserver) this.resizeObserver.observe(this.root);else window.addEventListener('resize', this.resizeCanvas);
|
|
1594
|
+
this.suppressEvents = true;
|
|
1595
|
+
this.setProgress(this.value, 'init');
|
|
1596
|
+
this.suppressEvents = false;
|
|
1597
|
+
this.bindEvents();
|
|
1598
|
+
this.resizeCanvas();
|
|
1599
|
+
}
|
|
1600
|
+
return _createClass(ProgressCapsuleController, [{
|
|
1601
|
+
key: "random",
|
|
1602
|
+
value: function random() {
|
|
1603
|
+
this.randomState = Math.imul(this.randomState, 1664525) + 1013904223 >>> 0;
|
|
1604
|
+
return this.randomState / 4294967296;
|
|
1605
|
+
}
|
|
1606
|
+
}, {
|
|
1607
|
+
key: "setProgress",
|
|
1608
|
+
value: function setProgress(nextValue) {
|
|
1609
|
+
var source = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'auto';
|
|
1610
|
+
this.value = clamp(nextValue, this.min, this.max);
|
|
1611
|
+
var rounded = Math.round(this.value);
|
|
1612
|
+
this.root.style.setProperty('--progress', this.value.toFixed(2));
|
|
1613
|
+
this.root.setAttribute('aria-valuenow', String(rounded));
|
|
1614
|
+
this.root.setAttribute('aria-valuetext', "".concat(rounded).concat(this.copy.valueSuffix));
|
|
1615
|
+
this.valueElement.textContent = "".concat(rounded).concat(this.copy.valueSuffix);
|
|
1616
|
+
if (!this.suppressEvents) this.emitter.emit('change', {
|
|
1617
|
+
value: this.value,
|
|
1618
|
+
source: source
|
|
1619
|
+
});
|
|
1620
|
+
}
|
|
1621
|
+
}, {
|
|
1622
|
+
key: "resizeCanvas",
|
|
1623
|
+
value: function resizeCanvas() {
|
|
1624
|
+
var bounds = this.root.getBoundingClientRect();
|
|
1625
|
+
this.dpr = Math.min(window.devicePixelRatio || 1, this.dprCap);
|
|
1626
|
+
this.width = Math.max(1, bounds.width);
|
|
1627
|
+
this.height = Math.max(1, bounds.height);
|
|
1628
|
+
this.canvas.width = Math.round(this.width * this.dpr);
|
|
1629
|
+
this.canvas.height = Math.round(this.height * this.dpr);
|
|
1630
|
+
this.canvas.style.width = "".concat(this.width, "px");
|
|
1631
|
+
this.canvas.style.height = "".concat(this.height, "px");
|
|
1632
|
+
this.ctx.setTransform(this.dpr, 0, 0, this.dpr, 0, 0);
|
|
1633
|
+
}
|
|
1634
|
+
}, {
|
|
1635
|
+
key: "edgeEnvelope",
|
|
1636
|
+
value: function edgeEnvelope(yRatio) {
|
|
1637
|
+
var edge = Math.sin(Math.PI * clamp(yRatio, 0, 1));
|
|
1638
|
+
return Math.pow(Math.max(edge, 0), 0.48);
|
|
1639
|
+
}
|
|
1640
|
+
}, {
|
|
1641
|
+
key: "localBulge",
|
|
1642
|
+
value: function localBulge(yRatio, time, index) {
|
|
1643
|
+
var direction = index === 0 ? 1 : -1;
|
|
1644
|
+
var center = 0.28 + index * 0.40 + Math.sin(time * (0.19 + index * 0.035) + this.seed * (1.1 + index)) * 0.13;
|
|
1645
|
+
var width = 0.075 + index * 0.016 + Math.sin(time * 0.13 + this.seed * 2.1) * 0.012;
|
|
1646
|
+
var distance = (yRatio - center) / Math.max(width, 0.035);
|
|
1647
|
+
var gaussian = Math.exp(-0.5 * distance * distance);
|
|
1648
|
+
return gaussian * Math.sin(time * (0.71 + index * 0.09) + this.seed * (2.7 + index)) * this.profile.bulgeAmplitude * direction;
|
|
1649
|
+
}
|
|
1650
|
+
}, {
|
|
1651
|
+
key: "edgeOffset",
|
|
1652
|
+
value: function edgeOffset(y, time) {
|
|
1653
|
+
var phase = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
1654
|
+
var amplitudeScale = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
|
|
1655
|
+
var yRatio = this.height > 0 ? y / this.height : 0;
|
|
1656
|
+
var envelope = this.edgeEnvelope(yRatio);
|
|
1657
|
+
var scaledTime = time * this.profile.timeScale;
|
|
1658
|
+
var phaseTime = this.profile.surge ? scaledTime + this.profile.surge * Math.sin(scaledTime * 2) : scaledTime;
|
|
1659
|
+
var offset = 0;
|
|
1660
|
+
for (var index = 0; index < this.profile.cycles.length; index += 1) {
|
|
1661
|
+
var cycle = this.profile.cycles[index];
|
|
1662
|
+
var amplitude = this.profile.amplitudes[index];
|
|
1663
|
+
var speed = this.profile.speeds[index];
|
|
1664
|
+
var amplitudeMotion = 0.74 + 0.26 * Math.sin(phaseTime * (0.17 + index * 0.045) + this.seed * (index + 2.4));
|
|
1665
|
+
offset += Math.sin(yRatio * Math.PI * 2 * cycle + phaseTime * speed * Math.PI * 2 + this.seed * (index + 1) + phase) * amplitude * amplitudeMotion;
|
|
1666
|
+
}
|
|
1667
|
+
offset += this.localBulge(yRatio, phaseTime + phase, 0);
|
|
1668
|
+
offset += this.localBulge(yRatio, phaseTime - phase * 0.7, 1);
|
|
1669
|
+
return offset * envelope * amplitudeScale;
|
|
1670
|
+
}
|
|
1671
|
+
}, {
|
|
1672
|
+
key: "createEdgePath",
|
|
1673
|
+
value: function createEdgePath(ctx, baseX, time) {
|
|
1674
|
+
var phase = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
|
|
1675
|
+
var amplitudeScale = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
|
|
1676
|
+
var step = Math.max(1.8, this.height / 92);
|
|
1677
|
+
ctx.beginPath();
|
|
1678
|
+
for (var y = 0; y <= this.height + step; y += step) {
|
|
1679
|
+
var x = baseX + this.edgeOffset(y, time, phase, amplitudeScale);
|
|
1680
|
+
if (y === 0) ctx.moveTo(x, y);else ctx.lineTo(x, y);
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
}, {
|
|
1684
|
+
key: "createFillPath",
|
|
1685
|
+
value: function createFillPath(ctx, baseX, time) {
|
|
1686
|
+
var phase = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
|
|
1687
|
+
var amplitudeScale = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
|
|
1688
|
+
var step = Math.max(1.8, this.height / 92);
|
|
1689
|
+
ctx.beginPath();
|
|
1690
|
+
ctx.moveTo(0, 0);
|
|
1691
|
+
ctx.lineTo(baseX + this.edgeOffset(0, time, phase, amplitudeScale), 0);
|
|
1692
|
+
for (var y = step; y <= this.height + step; y += step) {
|
|
1693
|
+
ctx.lineTo(baseX + this.edgeOffset(y, time, phase, amplitudeScale), y);
|
|
1694
|
+
}
|
|
1695
|
+
ctx.lineTo(0, this.height);
|
|
1696
|
+
ctx.closePath();
|
|
1697
|
+
}
|
|
1698
|
+
}, {
|
|
1699
|
+
key: "drawEllipticalGlow",
|
|
1700
|
+
value: function drawEllipticalGlow(x, y, radiusX, radiusY, color, alpha) {
|
|
1701
|
+
var ctx = this.ctx;
|
|
1702
|
+
ctx.save();
|
|
1703
|
+
ctx.translate(x, y);
|
|
1704
|
+
ctx.scale(1, radiusY / radiusX);
|
|
1705
|
+
var gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, radiusX);
|
|
1706
|
+
gradient.addColorStop(0, hexToRgba(color, alpha));
|
|
1707
|
+
gradient.addColorStop(0.42, hexToRgba(color, alpha * 0.48));
|
|
1708
|
+
gradient.addColorStop(1, hexToRgba(color, 0));
|
|
1709
|
+
ctx.globalCompositeOperation = 'screen';
|
|
1710
|
+
ctx.fillStyle = gradient;
|
|
1711
|
+
ctx.fillRect(-radiusX, -radiusX, radiusX * 2, radiusX * 2);
|
|
1712
|
+
ctx.restore();
|
|
1713
|
+
}
|
|
1714
|
+
}, {
|
|
1715
|
+
key: "drawDarkEllipticalShadow",
|
|
1716
|
+
value: function drawDarkEllipticalShadow(x, y, radiusX, radiusY, alpha) {
|
|
1717
|
+
var ctx = this.ctx;
|
|
1718
|
+
ctx.save();
|
|
1719
|
+
ctx.translate(x, y);
|
|
1720
|
+
ctx.scale(1, radiusY / radiusX);
|
|
1721
|
+
var gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, radiusX);
|
|
1722
|
+
gradient.addColorStop(0, "rgba(6, 6, 11, ".concat(alpha, ")"));
|
|
1723
|
+
gradient.addColorStop(0.54, "rgba(8, 8, 14, ".concat(alpha * 0.62, ")"));
|
|
1724
|
+
gradient.addColorStop(1, 'rgba(8, 8, 14, 0)');
|
|
1725
|
+
ctx.globalCompositeOperation = 'source-over';
|
|
1726
|
+
ctx.fillStyle = gradient;
|
|
1727
|
+
ctx.fillRect(-radiusX, -radiusX, radiusX * 2, radiusX * 2);
|
|
1728
|
+
ctx.restore();
|
|
1729
|
+
}
|
|
1730
|
+
}, {
|
|
1731
|
+
key: "drawColorClouds",
|
|
1732
|
+
value: function drawColorClouds(shoreline, time, accentA, accentB, glow) {
|
|
1733
|
+
this.ctx;
|
|
1734
|
+
var width = this.width;
|
|
1735
|
+
var height = this.height;
|
|
1736
|
+
var scale = this.profile.cloudWidth;
|
|
1737
|
+
var t = time * this.profile.timeScale;
|
|
1738
|
+
var upperY = height * (0.28 + Math.sin(t * 0.24 + this.seed) * 0.13);
|
|
1739
|
+
var lowerY = height * (0.70 + Math.cos(t * 0.21 + this.seed * 1.7) * 0.12);
|
|
1740
|
+
var middleY = height * (0.49 + Math.sin(t * 0.31 + this.seed * 2.3) * 0.15);
|
|
1741
|
+
var farX = shoreline - width * 0.095;
|
|
1742
|
+
var farRx = Math.max(52, width * scale);
|
|
1743
|
+
var farRy = height * 0.42;
|
|
1744
|
+
this.drawEllipticalGlow(farX, upperY, farRx, farRy, accentA, 0.38);
|
|
1745
|
+
this.drawDarkEllipticalShadow(farX + farRx * 0.16, upperY, farRx * 0.58, farRy * 0.66, 0.74);
|
|
1746
|
+
var lowerX = shoreline - width * 0.072;
|
|
1747
|
+
var lowerRx = Math.max(44, width * scale * 0.82);
|
|
1748
|
+
var lowerRy = height * 0.36;
|
|
1749
|
+
this.drawEllipticalGlow(lowerX, lowerY, lowerRx, lowerRy, accentB, 0.31);
|
|
1750
|
+
this.drawDarkEllipticalShadow(lowerX + lowerRx * 0.14, lowerY, lowerRx * 0.54, lowerRy * 0.62, 0.64);
|
|
1751
|
+
this.drawEllipticalGlow(shoreline - width * 0.034, middleY, Math.max(30, width * scale * 0.48), height * 0.27, glow, 0.20);
|
|
1752
|
+
}
|
|
1753
|
+
}, {
|
|
1754
|
+
key: "drawPathBand",
|
|
1755
|
+
value: function drawPathBand(_ref2) {
|
|
1756
|
+
var baseX = _ref2.baseX,
|
|
1757
|
+
time = _ref2.time,
|
|
1758
|
+
phase = _ref2.phase,
|
|
1759
|
+
amplitudeScale = _ref2.amplitudeScale,
|
|
1760
|
+
color = _ref2.color,
|
|
1761
|
+
alpha = _ref2.alpha,
|
|
1762
|
+
blur = _ref2.blur,
|
|
1763
|
+
width = _ref2.width,
|
|
1764
|
+
_ref2$composite = _ref2.composite,
|
|
1765
|
+
composite = _ref2$composite === void 0 ? 'screen' : _ref2$composite;
|
|
1766
|
+
var ctx = this.ctx;
|
|
1767
|
+
this.createEdgePath(ctx, baseX, time, phase, amplitudeScale);
|
|
1768
|
+
ctx.save();
|
|
1769
|
+
ctx.globalCompositeOperation = composite;
|
|
1770
|
+
ctx.globalAlpha = alpha;
|
|
1771
|
+
// Safari < 18 and some old WebViews ignore ctx.filter; setting it is a
|
|
1772
|
+
// no-op there, so only assign when supported to keep intent explicit.
|
|
1773
|
+
if (SUPPORTS_CTX_FILTER) ctx.filter = "blur(".concat(blur, "px)");
|
|
1774
|
+
ctx.strokeStyle = color;
|
|
1775
|
+
ctx.lineWidth = width;
|
|
1776
|
+
ctx.stroke();
|
|
1777
|
+
ctx.restore();
|
|
1778
|
+
}
|
|
1779
|
+
}, {
|
|
1780
|
+
key: "setRange",
|
|
1781
|
+
value: function setRange(min, max) {
|
|
1782
|
+
this.min = min;
|
|
1783
|
+
this.max = max;
|
|
1784
|
+
var clamped = clamp(this.value, this.min, this.max);
|
|
1785
|
+
if (clamped !== this.value) this.setProgress(clamped, 'prop');
|
|
1786
|
+
}
|
|
1787
|
+
}, {
|
|
1788
|
+
key: "drawReferenceFlow",
|
|
1789
|
+
value: function drawReferenceFlow() {
|
|
1790
|
+
var ctx = this.ctx;
|
|
1791
|
+
var width = this.width;
|
|
1792
|
+
var height = this.height;
|
|
1793
|
+
if (!ctx || width <= 0 || height <= 0) return;
|
|
1794
|
+
var shoreline = width * (this.value / 100);
|
|
1795
|
+
var time = this.flowTime;
|
|
1796
|
+
var _this$preset$colors = _slicedToArray(this.preset.colors, 4),
|
|
1797
|
+
dark = _this$preset$colors[0],
|
|
1798
|
+
accentA = _this$preset$colors[1],
|
|
1799
|
+
accentB = _this$preset$colors[2],
|
|
1800
|
+
glow = _this$preset$colors[3];
|
|
1801
|
+
ctx.clearRect(0, 0, width, height);
|
|
1802
|
+
ctx.fillStyle = '#202126';
|
|
1803
|
+
ctx.fillRect(0, 0, width, height);
|
|
1804
|
+
this.createFillPath(ctx, shoreline, time, 0, 1);
|
|
1805
|
+
var bodyGradient = ctx.createLinearGradient(0, 0, Math.max(shoreline, 1), 0);
|
|
1806
|
+
bodyGradient.addColorStop(0, dark);
|
|
1807
|
+
bodyGradient.addColorStop(0.74, dark);
|
|
1808
|
+
bodyGradient.addColorStop(0.89, hexToRgba(dark, 0.99));
|
|
1809
|
+
bodyGradient.addColorStop(0.955, hexToRgba(accentA, 0.09));
|
|
1810
|
+
bodyGradient.addColorStop(0.992, hexToRgba(accentB, 0.54));
|
|
1811
|
+
bodyGradient.addColorStop(1, hexToRgba(glow, 0.78));
|
|
1812
|
+
ctx.fillStyle = bodyGradient;
|
|
1813
|
+
ctx.fill();
|
|
1814
|
+
this.drawColorClouds(shoreline, time, accentA, accentB, glow);
|
|
1815
|
+
this.drawPathBand({
|
|
1816
|
+
baseX: shoreline - width * 0.105,
|
|
1817
|
+
time: time,
|
|
1818
|
+
phase: 1.42,
|
|
1819
|
+
amplitudeScale: 1.18,
|
|
1820
|
+
color: accentA,
|
|
1821
|
+
alpha: 0.22,
|
|
1822
|
+
blur: 21,
|
|
1823
|
+
width: 54
|
|
1824
|
+
});
|
|
1825
|
+
this.drawPathBand({
|
|
1826
|
+
baseX: shoreline - width * 0.073,
|
|
1827
|
+
time: time,
|
|
1828
|
+
phase: -0.92,
|
|
1829
|
+
amplitudeScale: 1.06,
|
|
1830
|
+
color: accentB,
|
|
1831
|
+
alpha: 0.30,
|
|
1832
|
+
blur: 15,
|
|
1833
|
+
width: 42
|
|
1834
|
+
});
|
|
1835
|
+
this.drawPathBand({
|
|
1836
|
+
baseX: shoreline - width * 0.047,
|
|
1837
|
+
time: time,
|
|
1838
|
+
phase: 0.42,
|
|
1839
|
+
amplitudeScale: 0.94,
|
|
1840
|
+
color: 'rgba(5, 5, 10, 0.92)',
|
|
1841
|
+
alpha: 0.72,
|
|
1842
|
+
blur: 12,
|
|
1843
|
+
width: 34,
|
|
1844
|
+
composite: 'source-over'
|
|
1845
|
+
});
|
|
1846
|
+
this.drawPathBand({
|
|
1847
|
+
baseX: shoreline - width * 0.025,
|
|
1848
|
+
time: time,
|
|
1849
|
+
phase: -0.28,
|
|
1850
|
+
amplitudeScale: 0.96,
|
|
1851
|
+
color: accentB,
|
|
1852
|
+
alpha: 0.66,
|
|
1853
|
+
blur: 8,
|
|
1854
|
+
width: 28
|
|
1855
|
+
});
|
|
1856
|
+
ctx.save();
|
|
1857
|
+
this.createFillPath(ctx, shoreline, time, 0, 1);
|
|
1858
|
+
ctx.clip();
|
|
1859
|
+
this.createEdgePath(ctx, shoreline, time, 0, 1);
|
|
1860
|
+
ctx.save();
|
|
1861
|
+
ctx.globalCompositeOperation = 'screen';
|
|
1862
|
+
ctx.strokeStyle = hexToRgba(accentA, 0.20);
|
|
1863
|
+
ctx.lineWidth = this.profile.haloWidth;
|
|
1864
|
+
ctx.shadowColor = accentA;
|
|
1865
|
+
ctx.shadowBlur = this.profile.haloWidth * 0.72;
|
|
1866
|
+
ctx.stroke();
|
|
1867
|
+
ctx.restore();
|
|
1868
|
+
ctx.save();
|
|
1869
|
+
ctx.globalCompositeOperation = 'screen';
|
|
1870
|
+
ctx.strokeStyle = hexToRgba(accentB, 0.78);
|
|
1871
|
+
ctx.lineWidth = this.profile.glowWidth + 4.2;
|
|
1872
|
+
ctx.shadowColor = accentB;
|
|
1873
|
+
ctx.shadowBlur = 8;
|
|
1874
|
+
ctx.stroke();
|
|
1875
|
+
ctx.restore();
|
|
1876
|
+
ctx.save();
|
|
1877
|
+
ctx.globalCompositeOperation = 'screen';
|
|
1878
|
+
ctx.strokeStyle = hexToRgba(glow, 0.88);
|
|
1879
|
+
ctx.lineWidth = this.profile.glowWidth;
|
|
1880
|
+
ctx.shadowColor = glow;
|
|
1881
|
+
ctx.shadowBlur = 5;
|
|
1882
|
+
ctx.stroke();
|
|
1883
|
+
ctx.restore();
|
|
1884
|
+
ctx.restore();
|
|
1885
|
+
ctx.save();
|
|
1886
|
+
ctx.globalCompositeOperation = 'screen';
|
|
1887
|
+
ctx.strokeStyle = hexToRgba(glow, 0.84);
|
|
1888
|
+
ctx.lineWidth = 2.15;
|
|
1889
|
+
ctx.shadowColor = glow;
|
|
1890
|
+
ctx.shadowBlur = 2.5;
|
|
1891
|
+
this.createEdgePath(ctx, shoreline, time, 0, 1);
|
|
1892
|
+
ctx.stroke();
|
|
1893
|
+
ctx.restore();
|
|
1894
|
+
if (this.profile.whiteAlpha > 0.05) {
|
|
1895
|
+
ctx.save();
|
|
1896
|
+
ctx.globalCompositeOperation = 'screen';
|
|
1897
|
+
ctx.strokeStyle = "rgba(255,255,245,".concat(this.profile.whiteAlpha, ")");
|
|
1898
|
+
ctx.lineWidth = this.profile.whiteWidth;
|
|
1899
|
+
this.createEdgePath(ctx, shoreline, time, 0, 1);
|
|
1900
|
+
ctx.stroke();
|
|
1901
|
+
ctx.restore();
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
}, {
|
|
1905
|
+
key: "updateFromPointer",
|
|
1906
|
+
value: function updateFromPointer(event) {
|
|
1907
|
+
var bounds = this.root.getBoundingClientRect();
|
|
1908
|
+
var ratio = bounds.width > 0 ? (event.clientX - bounds.left) / bounds.width : 0;
|
|
1909
|
+
this.setProgress(ratio * 100, 'drag');
|
|
1910
|
+
}
|
|
1911
|
+
}, {
|
|
1912
|
+
key: "beginDrag",
|
|
1913
|
+
value: function beginDrag(event) {
|
|
1914
|
+
if (event.button !== undefined && event.button !== 0) return;
|
|
1915
|
+
event.preventDefault();
|
|
1916
|
+
this.dragging = true;
|
|
1917
|
+
this.root.classList.add('is-dragging');
|
|
1918
|
+
try {
|
|
1919
|
+
var _this$root$setPointer, _this$root;
|
|
1920
|
+
(_this$root$setPointer = (_this$root = this.root).setPointerCapture) === null || _this$root$setPointer === void 0 || _this$root$setPointer.call(_this$root, event.pointerId);
|
|
1921
|
+
} catch (_unused) {}
|
|
1922
|
+
this.emitter.emit('dragstart', {
|
|
1923
|
+
value: this.value
|
|
1924
|
+
});
|
|
1925
|
+
this.updateFromPointer(event);
|
|
1926
|
+
}
|
|
1927
|
+
}, {
|
|
1928
|
+
key: "moveDrag",
|
|
1929
|
+
value: function moveDrag(event) {
|
|
1930
|
+
if (!this.dragging) return;
|
|
1931
|
+
event.preventDefault();
|
|
1932
|
+
this.updateFromPointer(event);
|
|
1933
|
+
}
|
|
1934
|
+
}, {
|
|
1935
|
+
key: "endDrag",
|
|
1936
|
+
value: function endDrag(event) {
|
|
1937
|
+
if (!this.dragging) return;
|
|
1938
|
+
this.dragging = false;
|
|
1939
|
+
this.root.classList.remove('is-dragging');
|
|
1940
|
+
try {
|
|
1941
|
+
var _this$root$hasPointer, _this$root2;
|
|
1942
|
+
if ((event === null || event === void 0 ? void 0 : event.pointerId) !== undefined && (_this$root$hasPointer = (_this$root2 = this.root).hasPointerCapture) !== null && _this$root$hasPointer !== void 0 && _this$root$hasPointer.call(_this$root2, event.pointerId)) {
|
|
1943
|
+
this.root.releasePointerCapture(event.pointerId);
|
|
1944
|
+
}
|
|
1945
|
+
} catch (_unused2) {}
|
|
1946
|
+
this.emitter.emit('dragend', {
|
|
1947
|
+
value: this.value
|
|
1948
|
+
});
|
|
1949
|
+
}
|
|
1950
|
+
}, {
|
|
1951
|
+
key: "bindEvents",
|
|
1952
|
+
value: function bindEvents() {
|
|
1953
|
+
var _this2 = this;
|
|
1954
|
+
if (this.options.draggable !== false) {
|
|
1955
|
+
this.handlers.pointerdown = function (event) {
|
|
1956
|
+
return _this2.beginDrag(event);
|
|
1957
|
+
};
|
|
1958
|
+
this.handlers.pointermove = function (event) {
|
|
1959
|
+
return _this2.moveDrag(event);
|
|
1960
|
+
};
|
|
1961
|
+
this.handlers.pointerup = function (event) {
|
|
1962
|
+
return _this2.endDrag(event);
|
|
1963
|
+
};
|
|
1964
|
+
this.handlers.pointercancel = function (event) {
|
|
1965
|
+
return _this2.endDrag(event);
|
|
1966
|
+
};
|
|
1967
|
+
this.root.addEventListener('pointerdown', this.handlers.pointerdown);
|
|
1968
|
+
this.root.addEventListener('pointermove', this.handlers.pointermove);
|
|
1969
|
+
this.root.addEventListener('pointerup', this.handlers.pointerup);
|
|
1970
|
+
this.root.addEventListener('pointercancel', this.handlers.pointercancel);
|
|
1971
|
+
}
|
|
1972
|
+
if (this.options.keyboard !== false) {
|
|
1973
|
+
this.handlers.keydown = function (event) {
|
|
1974
|
+
var actions = {
|
|
1975
|
+
ArrowLeft: -2,
|
|
1976
|
+
ArrowDown: -2,
|
|
1977
|
+
ArrowRight: 2,
|
|
1978
|
+
ArrowUp: 2,
|
|
1979
|
+
PageDown: -10,
|
|
1980
|
+
PageUp: 10
|
|
1981
|
+
};
|
|
1982
|
+
if (event.key === 'Home') {
|
|
1983
|
+
event.preventDefault();
|
|
1984
|
+
_this2.setProgress(_this2.min, 'keyboard');
|
|
1985
|
+
} else if (event.key === 'End') {
|
|
1986
|
+
event.preventDefault();
|
|
1987
|
+
_this2.setProgress(_this2.max, 'keyboard');
|
|
1988
|
+
} else if (actions[event.key]) {
|
|
1989
|
+
event.preventDefault();
|
|
1990
|
+
_this2.setProgress(_this2.value + actions[event.key], 'keyboard');
|
|
1991
|
+
} else {
|
|
1992
|
+
return;
|
|
1993
|
+
}
|
|
1994
|
+
};
|
|
1995
|
+
this.root.addEventListener('keydown', this.handlers.keydown);
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
}, {
|
|
1999
|
+
key: "update",
|
|
2000
|
+
value: function update(delta, paused) {
|
|
2001
|
+
if (!paused) this.flowTime += delta;
|
|
2002
|
+
}
|
|
2003
|
+
}, {
|
|
2004
|
+
key: "draw",
|
|
2005
|
+
value: function draw() {
|
|
2006
|
+
// Performance fix: when the WebGL overlay is active the 2D layer is
|
|
2007
|
+
// hidden behind it, so drawing it every frame would be wasted CPU.
|
|
2008
|
+
if (this.webglActive) return;
|
|
2009
|
+
this.drawReferenceFlow();
|
|
2010
|
+
}
|
|
2011
|
+
}, {
|
|
2012
|
+
key: "randomize",
|
|
2013
|
+
value: function randomize() {
|
|
2014
|
+
this.flowTime = this.random() * 40;
|
|
2015
|
+
}
|
|
2016
|
+
}, {
|
|
2017
|
+
key: "setColors",
|
|
2018
|
+
value: function setColors(colors) {
|
|
2019
|
+
if (!Array.isArray(colors) || colors.length !== 4) return;
|
|
2020
|
+
this.preset = _objectSpread2(_objectSpread2({}, this.preset), {}, {
|
|
2021
|
+
colors: colors
|
|
2022
|
+
});
|
|
2023
|
+
}
|
|
2024
|
+
}, {
|
|
2025
|
+
key: "dispose",
|
|
2026
|
+
value: function dispose() {
|
|
2027
|
+
if (this.resizeObserver) this.resizeObserver.disconnect();else window.removeEventListener('resize', this.resizeCanvas);
|
|
2028
|
+
for (var _i = 0, _Object$keys = Object.keys(this.handlers); _i < _Object$keys.length; _i++) {
|
|
2029
|
+
var name = _Object$keys[_i];
|
|
2030
|
+
var handler = this.handlers[name];
|
|
2031
|
+
this.root.removeEventListener(name, handler);
|
|
2032
|
+
}
|
|
2033
|
+
this.handlers = {};
|
|
2034
|
+
}
|
|
2035
|
+
}]);
|
|
2036
|
+
}();
|
|
2037
|
+
|
|
2038
|
+
/**
|
|
2039
|
+
* Mount a fluid progress capsule into `container`.
|
|
2040
|
+
*
|
|
2041
|
+
* Options: preset (id/code/name or object), width, height, value, min, max,
|
|
2042
|
+
* draggable, keyboard, colors, edgeStyle, quality,
|
|
2043
|
+
* respectReducedMotion, copy, cssVars.
|
|
2044
|
+
*/
|
|
2045
|
+
function createProgressCapsule(container) {
|
|
2046
|
+
var _options$preset, _merged$min, _merged$max;
|
|
2047
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
2048
|
+
if (!container || typeof container.appendChild !== 'function') {
|
|
2049
|
+
throw new Error('createProgressCapsule: container element is required');
|
|
2050
|
+
}
|
|
2051
|
+
var preset = _objectSpread2({}, getPreset('progress', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : 'NC-10'));
|
|
2052
|
+
var merged = normalizeOptions(DEFAULTS.progress, preset, options);
|
|
2053
|
+
var copy = _objectSpread2(_objectSpread2({}, COPY), merged.copy || {});
|
|
2054
|
+
var root = document.createElement('div');
|
|
2055
|
+
root.className = 'hj-capsule-root hj-progress-root';
|
|
2056
|
+
root.setAttribute('role', 'slider');
|
|
2057
|
+
root.setAttribute('tabindex', '0');
|
|
2058
|
+
root.setAttribute('data-draggable', String(merged.draggable !== false));
|
|
2059
|
+
root.setAttribute('aria-valuemin', String((_merged$min = merged.min) !== null && _merged$min !== void 0 ? _merged$min : 0));
|
|
2060
|
+
root.setAttribute('aria-valuemax', String((_merged$max = merged.max) !== null && _merged$max !== void 0 ? _merged$max : 100));
|
|
2061
|
+
root.setAttribute('aria-valuenow', String(preset.initialProgress));
|
|
2062
|
+
root.setAttribute('aria-label', interpolate(copy.progressAria, {
|
|
2063
|
+
brand: copy.brandName,
|
|
2064
|
+
code: preset.code,
|
|
2065
|
+
name: preset.name
|
|
2066
|
+
}));
|
|
2067
|
+
if (merged.keyboard === false) root.setAttribute('tabindex', '-1');
|
|
2068
|
+
var canvas = document.createElement('canvas');
|
|
2069
|
+
canvas.className = 'hj-progress-canvas';
|
|
2070
|
+
canvas.setAttribute('aria-hidden', 'true');
|
|
2071
|
+
var copyEnabled = copy.enabled !== false && merged.showCopy !== false;
|
|
2072
|
+
var copyText = function copyText(key, fallback) {
|
|
2073
|
+
var value = copy[key];
|
|
2074
|
+
return value === undefined ? fallback : value;
|
|
2075
|
+
};
|
|
2076
|
+
function buildCopyHtml() {
|
|
2077
|
+
var html = '';
|
|
2078
|
+
var brandText = copy.brandName || '';
|
|
2079
|
+
var subtitleText = copyText('subtitle', preset.subtitle);
|
|
2080
|
+
if (brandText) html += "<span class=\"hj-progress-name\">".concat(brandText, "</span>");
|
|
2081
|
+
if (subtitleText) html += "<span class=\"hj-progress-subtitle\">".concat(subtitleText, "</span>");
|
|
2082
|
+
return html;
|
|
2083
|
+
}
|
|
2084
|
+
var copyLayer = document.createElement('div');
|
|
2085
|
+
copyLayer.className = 'hj-progress-copy';
|
|
2086
|
+
var renderCopy = function renderCopy() {
|
|
2087
|
+
if (copyEnabled) copyLayer.innerHTML = buildCopyHtml();
|
|
2088
|
+
};
|
|
2089
|
+
renderCopy();
|
|
2090
|
+
if (copy.background) {
|
|
2091
|
+
root.style.setProperty('--hj-progress-copy-bg', copy.background);
|
|
2092
|
+
root.style.setProperty('--hj-progress-copy-pad', '6px 12px');
|
|
2093
|
+
}
|
|
2094
|
+
if (copy.color) root.style.setProperty('--hj-progress-copy-color', copy.color);
|
|
2095
|
+
var valueElement = document.createElement('div');
|
|
2096
|
+
valueElement.className = 'hj-progress-value';
|
|
2097
|
+
valueElement.setAttribute('aria-hidden', 'true');
|
|
2098
|
+
var dragLabel = document.createElement('span');
|
|
2099
|
+
dragLabel.className = 'hj-progress-drag-label';
|
|
2100
|
+
dragLabel.setAttribute('aria-hidden', 'true');
|
|
2101
|
+
dragLabel.textContent = copy.dragLabel;
|
|
2102
|
+
root.appendChild(canvas);
|
|
2103
|
+
if (copyEnabled) root.appendChild(copyLayer);
|
|
2104
|
+
root.appendChild(valueElement);
|
|
2105
|
+
root.appendChild(dragLabel);
|
|
2106
|
+
container.appendChild(root);
|
|
2107
|
+
var emitter = createEmitter();
|
|
2108
|
+
var paused = merged.respectReducedMotion && prefersReducedMotion();
|
|
2109
|
+
var applySize = function applySize() {
|
|
2110
|
+
root.style.width = parseSize(merged.width);
|
|
2111
|
+
root.style.height = parseSize(merged.height);
|
|
2112
|
+
var vars = merged.cssVars || {};
|
|
2113
|
+
for (var _i2 = 0, _Object$keys2 = Object.keys(vars); _i2 < _Object$keys2.length; _i2++) {
|
|
2114
|
+
var name = _Object$keys2[_i2];
|
|
2115
|
+
root.style.setProperty(name, vars[name]);
|
|
2116
|
+
}
|
|
2117
|
+
};
|
|
2118
|
+
applySize();
|
|
2119
|
+
var controller = new ProgressCapsuleController({
|
|
2120
|
+
root: root,
|
|
2121
|
+
canvas: canvas,
|
|
2122
|
+
valueElement: valueElement,
|
|
2123
|
+
preset: preset,
|
|
2124
|
+
emitter: emitter,
|
|
2125
|
+
options: merged,
|
|
2126
|
+
copy: copy
|
|
2127
|
+
});
|
|
2128
|
+
var overlay = null;
|
|
2129
|
+
if (merged.renderer !== 'canvas2d') {
|
|
2130
|
+
overlay = attachProgressFlowOverlay({
|
|
2131
|
+
root: root,
|
|
2132
|
+
canvas: canvas,
|
|
2133
|
+
preset: preset,
|
|
2134
|
+
getProgress: function getProgress() {
|
|
2135
|
+
return controller.value;
|
|
2136
|
+
}
|
|
2137
|
+
});
|
|
2138
|
+
}
|
|
2139
|
+
if (overlay) controller.webglActive = true;
|
|
2140
|
+
var visibility = createVisibilityGuard(root);
|
|
2141
|
+
var flowTime = 0;
|
|
2142
|
+
var unsubscribe = subscribeScheduler(function (delta, now) {
|
|
2143
|
+
flowTime += delta;
|
|
2144
|
+
controller.update(delta, false);
|
|
2145
|
+
if (visibility.isVisible()) {
|
|
2146
|
+
controller.draw();
|
|
2147
|
+
if (overlay) overlay.update(flowTime);
|
|
2148
|
+
}
|
|
2149
|
+
}, function () {
|
|
2150
|
+
return paused;
|
|
2151
|
+
});
|
|
2152
|
+
emitter.emit('ready', {
|
|
2153
|
+
preset: _objectSpread2({}, preset)
|
|
2154
|
+
});
|
|
2155
|
+
var syncDom = function syncDom() {
|
|
2156
|
+
root.setAttribute('aria-label', interpolate(copy.progressAria, {
|
|
2157
|
+
brand: copy.brandName,
|
|
2158
|
+
code: preset.code,
|
|
2159
|
+
name: preset.name
|
|
2160
|
+
}));
|
|
2161
|
+
renderCopy();
|
|
2162
|
+
};
|
|
2163
|
+
return {
|
|
2164
|
+
element: root,
|
|
2165
|
+
canvas: canvas,
|
|
2166
|
+
preset: preset,
|
|
2167
|
+
on: emitter.on,
|
|
2168
|
+
off: emitter.off,
|
|
2169
|
+
setValue: function setValue(value) {
|
|
2170
|
+
var source = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'prop';
|
|
2171
|
+
controller.setProgress(value, source);
|
|
2172
|
+
return this;
|
|
2173
|
+
},
|
|
2174
|
+
getValue: function getValue() {
|
|
2175
|
+
return controller.value;
|
|
2176
|
+
},
|
|
2177
|
+
setRange: function setRange(min, max) {
|
|
2178
|
+
controller.setRange(min, max);
|
|
2179
|
+
return this;
|
|
2180
|
+
},
|
|
2181
|
+
setPreset: function setPreset(ref) {
|
|
2182
|
+
var next = getPreset('progress', ref);
|
|
2183
|
+
Object.assign(preset, next);
|
|
2184
|
+
controller.preset = next;
|
|
2185
|
+
controller.profile = next.edgeStyle === 'tide' ? FLOW_PROFILES.tide : FLOW_PROFILES[next.id] || FLOW_PROFILES['visual-training'];
|
|
2186
|
+
controller.flowTime = stringSeed(next.id) * 31;
|
|
2187
|
+
controller.seed = stringSeed("".concat(next.id, "-reference")) * Math.PI * 2;
|
|
2188
|
+
syncDom();
|
|
2189
|
+
if (overlay) {
|
|
2190
|
+
overlay.dispose();
|
|
2191
|
+
overlay = attachProgressFlowOverlay({
|
|
2192
|
+
root: root,
|
|
2193
|
+
canvas: canvas,
|
|
2194
|
+
preset: next,
|
|
2195
|
+
getProgress: function getProgress() {
|
|
2196
|
+
return controller.value;
|
|
2197
|
+
}
|
|
2198
|
+
});
|
|
2199
|
+
}
|
|
2200
|
+
controller.webglActive = Boolean(overlay);
|
|
2201
|
+
controller.resizeCanvas();
|
|
2202
|
+
emitter.emit('presetchange', {
|
|
2203
|
+
preset: _objectSpread2({}, next)
|
|
2204
|
+
});
|
|
2205
|
+
return this;
|
|
2206
|
+
},
|
|
2207
|
+
setColors: function setColors(colors) {
|
|
2208
|
+
if (!Array.isArray(colors) || colors.length !== 4) return this;
|
|
2209
|
+
controller.setColors(colors);
|
|
2210
|
+
if (overlay) overlay.setColors(colors);
|
|
2211
|
+
controller.resizeCanvas();
|
|
2212
|
+
return this;
|
|
2213
|
+
},
|
|
2214
|
+
setSize: function setSize(width, height) {
|
|
2215
|
+
if (width !== undefined) merged.width = width;
|
|
2216
|
+
if (height !== undefined) merged.height = height;
|
|
2217
|
+
applySize();
|
|
2218
|
+
controller.resizeCanvas();
|
|
2219
|
+
return this;
|
|
2220
|
+
},
|
|
2221
|
+
randomize: function randomize() {
|
|
2222
|
+
controller.randomize();
|
|
2223
|
+
return this;
|
|
2224
|
+
},
|
|
2225
|
+
pause: function pause() {
|
|
2226
|
+
paused = true;
|
|
2227
|
+
return this;
|
|
2228
|
+
},
|
|
2229
|
+
resume: function resume() {
|
|
2230
|
+
paused = false;
|
|
2231
|
+
return this;
|
|
2232
|
+
},
|
|
2233
|
+
setQuality: function setQuality(quality) {
|
|
2234
|
+
merged.quality = quality;
|
|
2235
|
+
controller.dprCap = dprCapFor(quality);
|
|
2236
|
+
controller.resizeCanvas();
|
|
2237
|
+
return this;
|
|
2238
|
+
},
|
|
2239
|
+
dispose: function dispose() {
|
|
2240
|
+
unsubscribe();
|
|
2241
|
+
visibility.dispose();
|
|
2242
|
+
if (overlay) overlay.dispose();
|
|
2243
|
+
controller.dispose();
|
|
2244
|
+
root.remove();
|
|
2245
|
+
}
|
|
2246
|
+
};
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
/**
|
|
2250
|
+
* Shared Options-API wrapper factory. The only framework difference is the
|
|
2251
|
+
* render function: Vue2 passes `h` as an argument, Vue3 needs the imported
|
|
2252
|
+
* `h` (see vue2.js / vue3.js). Lifecycle options cover both.
|
|
2253
|
+
*/
|
|
2254
|
+
|
|
2255
|
+
var CAPSULE_EVENTS = ['ready', 'error', 'click', 'pointerdown', 'pointerup', 'dblclick', 'pointerenter', 'pointerleave', 'presetchange'];
|
|
2256
|
+
var PROGRESS_EVENTS = ['ready', 'error', 'change', 'dragstart', 'dragend', 'presetchange'];
|
|
2257
|
+
function hookEvents(controller, events, emit) {
|
|
2258
|
+
var _iterator = _createForOfIteratorHelper(events),
|
|
2259
|
+
_step;
|
|
2260
|
+
try {
|
|
2261
|
+
var _loop = function _loop() {
|
|
2262
|
+
var event = _step.value;
|
|
2263
|
+
controller.on(event, function (payload) {
|
|
2264
|
+
return emit(event, payload);
|
|
2265
|
+
});
|
|
2266
|
+
};
|
|
2267
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
2268
|
+
_loop();
|
|
2269
|
+
}
|
|
2270
|
+
} catch (err) {
|
|
2271
|
+
_iterator.e(err);
|
|
2272
|
+
} finally {
|
|
2273
|
+
_iterator.f();
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
function makeWrapper(_ref) {
|
|
2277
|
+
var name = _ref.name,
|
|
2278
|
+
props = _ref.props,
|
|
2279
|
+
events = _ref.events,
|
|
2280
|
+
create = _ref.create,
|
|
2281
|
+
render = _ref.render,
|
|
2282
|
+
methods = _ref.methods,
|
|
2283
|
+
watch = _ref.watch;
|
|
2284
|
+
var internalMethods = {
|
|
2285
|
+
mountController: function mountController() {
|
|
2286
|
+
var _this = this;
|
|
2287
|
+
this.controller = create(this.$el, this.$props);
|
|
2288
|
+
hookEvents(this.controller, events, function (event, payload) {
|
|
2289
|
+
return _this.$emit(event, payload);
|
|
2290
|
+
});
|
|
2291
|
+
},
|
|
2292
|
+
recreate: function recreate() {
|
|
2293
|
+
if (this.controller) this.controller.dispose();
|
|
2294
|
+
if (this.$el) this.$el.innerHTML = '';
|
|
2295
|
+
this.mountController();
|
|
2296
|
+
},
|
|
2297
|
+
scheduleRecreate: function scheduleRecreate() {
|
|
2298
|
+
var _this2 = this;
|
|
2299
|
+
if (this._recreateQueued) return;
|
|
2300
|
+
this._recreateQueued = true;
|
|
2301
|
+
this.$nextTick(function () {
|
|
2302
|
+
_this2._recreateQueued = false;
|
|
2303
|
+
_this2.recreate();
|
|
2304
|
+
});
|
|
2305
|
+
}
|
|
2306
|
+
};
|
|
2307
|
+
return {
|
|
2308
|
+
name: name,
|
|
2309
|
+
props: props,
|
|
2310
|
+
emits: events,
|
|
2311
|
+
render: render,
|
|
2312
|
+
mounted: function mounted() {
|
|
2313
|
+
this.mountController();
|
|
2314
|
+
},
|
|
2315
|
+
beforeUnmount: function beforeUnmount() {
|
|
2316
|
+
if (this.controller) this.controller.dispose();
|
|
2317
|
+
},
|
|
2318
|
+
beforeDestroy: function beforeDestroy() {
|
|
2319
|
+
if (this.controller) this.controller.dispose();
|
|
2320
|
+
},
|
|
2321
|
+
watch: _objectSpread2({
|
|
2322
|
+
preset: function preset(value) {
|
|
2323
|
+
if (value && this.controller) this.controller.setPreset(value);
|
|
2324
|
+
},
|
|
2325
|
+
colors: function colors(value) {
|
|
2326
|
+
if (value && this.controller) this.controller.setColors(value);
|
|
2327
|
+
},
|
|
2328
|
+
width: function width(value) {
|
|
2329
|
+
if (value !== undefined && this.controller) this.controller.setSize(value);
|
|
2330
|
+
},
|
|
2331
|
+
height: function height(value) {
|
|
2332
|
+
if (value !== undefined && this.controller) this.controller.setSize(undefined, value);
|
|
2333
|
+
},
|
|
2334
|
+
quality: function quality(value) {
|
|
2335
|
+
if (value && this.controller) this.controller.setQuality(value);
|
|
2336
|
+
}
|
|
2337
|
+
}, watch || {}),
|
|
2338
|
+
methods: _objectSpread2(_objectSpread2({}, internalMethods), methods || {})
|
|
2339
|
+
};
|
|
2340
|
+
}
|
|
2341
|
+
function makeCapsuleWrapper(createCapsule, render) {
|
|
2342
|
+
return makeWrapper({
|
|
2343
|
+
name: 'CosmicCapsule',
|
|
2344
|
+
props: ['preset', 'width', 'height', 'colors', 'seed', 'speed', 'interactive', 'mouseColor', 'renderer', 'quality', 'respectReducedMotion', 'copy', 'cssVars'],
|
|
2345
|
+
events: CAPSULE_EVENTS,
|
|
2346
|
+
create: createCapsule,
|
|
2347
|
+
render: render,
|
|
2348
|
+
watch: {
|
|
2349
|
+
seed: function seed(value) {
|
|
2350
|
+
var seed = Number(value);
|
|
2351
|
+
if (this.controller && Number.isFinite(seed)) {
|
|
2352
|
+
this.controller.setPreset(_objectSpread2(_objectSpread2({}, this.controller.preset), {}, {
|
|
2353
|
+
seed: seed
|
|
2354
|
+
}));
|
|
2355
|
+
}
|
|
2356
|
+
},
|
|
2357
|
+
speed: function speed(value) {
|
|
2358
|
+
var speed = Number(value);
|
|
2359
|
+
if (this.controller && Number.isFinite(speed)) {
|
|
2360
|
+
this.controller.setPreset(_objectSpread2(_objectSpread2({}, this.controller.preset), {}, {
|
|
2361
|
+
speed: speed
|
|
2362
|
+
}));
|
|
2363
|
+
}
|
|
2364
|
+
},
|
|
2365
|
+
interactive: function interactive() {
|
|
2366
|
+
this.scheduleRecreate();
|
|
2367
|
+
},
|
|
2368
|
+
mouseColor: function mouseColor() {
|
|
2369
|
+
this.scheduleRecreate();
|
|
2370
|
+
},
|
|
2371
|
+
renderer: function renderer() {
|
|
2372
|
+
this.scheduleRecreate();
|
|
2373
|
+
}
|
|
2374
|
+
},
|
|
2375
|
+
methods: {
|
|
2376
|
+
randomize: function randomize() {
|
|
2377
|
+
return this.controller && this.controller.randomize();
|
|
2378
|
+
},
|
|
2379
|
+
pause: function pause() {
|
|
2380
|
+
return this.controller && this.controller.pause();
|
|
2381
|
+
},
|
|
2382
|
+
resume: function resume() {
|
|
2383
|
+
return this.controller && this.controller.resume();
|
|
2384
|
+
},
|
|
2385
|
+
setPreset: function setPreset(preset) {
|
|
2386
|
+
return this.controller && this.controller.setPreset(preset);
|
|
2387
|
+
},
|
|
2388
|
+
setSize: function setSize(width, height) {
|
|
2389
|
+
return this.controller && this.controller.setSize(width, height);
|
|
2390
|
+
},
|
|
2391
|
+
setColors: function setColors(colors) {
|
|
2392
|
+
return this.controller && this.controller.setColors(colors);
|
|
2393
|
+
},
|
|
2394
|
+
setQuality: function setQuality(quality) {
|
|
2395
|
+
return this.controller && this.controller.setQuality(quality);
|
|
2396
|
+
},
|
|
2397
|
+
getController: function getController() {
|
|
2398
|
+
return this.controller;
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
});
|
|
2402
|
+
}
|
|
2403
|
+
function makeProgressWrapper(createProgressCapsule, render) {
|
|
2404
|
+
return makeWrapper({
|
|
2405
|
+
name: 'ProgressCapsule',
|
|
2406
|
+
props: ['preset', 'width', 'height', 'value', 'min', 'max', 'draggable', 'keyboard', 'edgeStyle', 'colors', 'quality', 'renderer', 'respectReducedMotion', 'copy', 'cssVars'],
|
|
2407
|
+
events: PROGRESS_EVENTS,
|
|
2408
|
+
create: createProgressCapsule,
|
|
2409
|
+
render: render,
|
|
2410
|
+
watch: {
|
|
2411
|
+
value: function value(_value) {
|
|
2412
|
+
if (_value !== undefined && this.controller) this.controller.setValue(_value);
|
|
2413
|
+
},
|
|
2414
|
+
min: function min(value) {
|
|
2415
|
+
if (value !== undefined && this.controller) this.controller.setRange(value, this.controller.max);
|
|
2416
|
+
},
|
|
2417
|
+
max: function max(value) {
|
|
2418
|
+
if (value !== undefined && this.controller) this.controller.setRange(this.controller.min, value);
|
|
2419
|
+
},
|
|
2420
|
+
edgeStyle: function edgeStyle(value) {
|
|
2421
|
+
if (value && this.controller) this.controller.setPreset(_objectSpread2(_objectSpread2({}, this.controller.preset), {}, {
|
|
2422
|
+
edgeStyle: value
|
|
2423
|
+
}));
|
|
2424
|
+
},
|
|
2425
|
+
draggable: function draggable() {
|
|
2426
|
+
this.scheduleRecreate();
|
|
2427
|
+
},
|
|
2428
|
+
keyboard: function keyboard() {
|
|
2429
|
+
this.scheduleRecreate();
|
|
2430
|
+
},
|
|
2431
|
+
renderer: function renderer() {
|
|
2432
|
+
this.scheduleRecreate();
|
|
2433
|
+
}
|
|
2434
|
+
},
|
|
2435
|
+
methods: {
|
|
2436
|
+
setValue: function setValue(value) {
|
|
2437
|
+
return this.controller && this.controller.setValue(value);
|
|
2438
|
+
},
|
|
2439
|
+
getValue: function getValue() {
|
|
2440
|
+
return this.controller ? this.controller.getValue() : undefined;
|
|
2441
|
+
},
|
|
2442
|
+
setRange: function setRange(min, max) {
|
|
2443
|
+
return this.controller && this.controller.setRange(min, max);
|
|
2444
|
+
},
|
|
2445
|
+
randomize: function randomize() {
|
|
2446
|
+
return this.controller && this.controller.randomize();
|
|
2447
|
+
},
|
|
2448
|
+
pause: function pause() {
|
|
2449
|
+
return this.controller && this.controller.pause();
|
|
2450
|
+
},
|
|
2451
|
+
resume: function resume() {
|
|
2452
|
+
return this.controller && this.controller.resume();
|
|
2453
|
+
},
|
|
2454
|
+
setPreset: function setPreset(preset) {
|
|
2455
|
+
return this.controller && this.controller.setPreset(preset);
|
|
2456
|
+
},
|
|
2457
|
+
setSize: function setSize(width, height) {
|
|
2458
|
+
return this.controller && this.controller.setSize(width, height);
|
|
2459
|
+
},
|
|
2460
|
+
setColors: function setColors(colors) {
|
|
2461
|
+
return this.controller && this.controller.setColors(colors);
|
|
2462
|
+
},
|
|
2463
|
+
setQuality: function setQuality(quality) {
|
|
2464
|
+
return this.controller && this.controller.setQuality(quality);
|
|
2465
|
+
},
|
|
2466
|
+
getController: function getController() {
|
|
2467
|
+
return this.controller;
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
});
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
// Vue2 passes `h` (createElement) as the first argument to render.
|
|
2474
|
+
var render = function render(h) {
|
|
2475
|
+
return h('div', {
|
|
2476
|
+
class: 'hj-vue-host'
|
|
2477
|
+
});
|
|
2478
|
+
};
|
|
2479
|
+
var CosmicCapsule = makeCapsuleWrapper(createCapsule, render);
|
|
2480
|
+
var ProgressCapsule = makeProgressWrapper(createProgressCapsule, render);
|
|
2481
|
+
|
|
2482
|
+
exports.CosmicCapsule = CosmicCapsule;
|
|
2483
|
+
exports.ProgressCapsule = ProgressCapsule;
|