@5even7/dlc-ui 0.2.11 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -42
- package/LICENSE +21 -21
- package/README.md +258 -255
- package/dist/capsule.cjs +307 -71
- package/dist/capsule.mjs +828 -604
- package/dist/color.cjs +338 -82
- package/dist/color.mjs +879 -631
- package/dist/index.cjs +997 -253
- package/dist/index.mjs +2704 -1976
- package/dist/index.umd.js +997 -253
- package/dist/index.umd.min.js +1 -1
- package/dist/progress.cjs +632 -172
- package/dist/progress.mjs +1827 -1379
- package/dist/vue2.cjs +1141 -266
- package/dist/vue2.mjs +2893 -2056
- package/dist/vue3.cjs +1141 -266
- package/dist/vue3.mjs +2893 -2056
- package/package.json +118 -118
- package/styles/base.css +32 -32
- package/styles/color.css +18 -18
- package/styles/progress.css +53 -50
- package/types/capsule.d.ts +15 -13
- package/types/color.d.ts +15 -13
- package/types/index.d.ts +204 -116
- package/types/progress.d.ts +16 -14
- package/types/vue3.d.ts +38 -22
package/dist/capsule.cjs
CHANGED
|
@@ -182,9 +182,9 @@ function _unsupportedIterableToArray(r, a) {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
/**
|
|
186
|
-
* Tiny event emitter. Accepts any event name so the API stays open for
|
|
187
|
-
* future events (hover, click, custom) without breaking changes.
|
|
185
|
+
/**
|
|
186
|
+
* Tiny event emitter. Accepts any event name so the API stays open for
|
|
187
|
+
* future events (hover, click, custom) without breaking changes.
|
|
188
188
|
*/
|
|
189
189
|
function createEmitter() {
|
|
190
190
|
// Plain object storage (no Map/Set) so the legacy build has no API
|
|
@@ -234,9 +234,9 @@ function createEmitter() {
|
|
|
234
234
|
|
|
235
235
|
var UNIT_PATTERN = /^[\d.]+(?:px|%|vw|vh|vmin|vmax|em|rem)$/;
|
|
236
236
|
|
|
237
|
-
/**
|
|
238
|
-
* Normalize a size option to a CSS length string.
|
|
239
|
-
* Accepts numbers (treated as px) or strings with px/%, vw/vh/vmin/vmax, em/rem.
|
|
237
|
+
/**
|
|
238
|
+
* Normalize a size option to a CSS length string.
|
|
239
|
+
* Accepts numbers (treated as px) or strings with px/%, vw/vh/vmin/vmax, em/rem.
|
|
240
240
|
*/
|
|
241
241
|
function parseSize(value) {
|
|
242
242
|
if (typeof value === 'number') {
|
|
@@ -275,11 +275,17 @@ function dprCapFor(quality) {
|
|
|
275
275
|
var tier = QUALITY_TIERS[quality] || QUALITY_TIERS.medium;
|
|
276
276
|
return tier.dpr;
|
|
277
277
|
}
|
|
278
|
+
function effectiveDprCap(quality) {
|
|
279
|
+
var renderScale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
280
|
+
var scale = Number(renderScale);
|
|
281
|
+
var normalizedScale = Number.isFinite(scale) ? Math.min(1, Math.max(0.25, scale)) : 1;
|
|
282
|
+
return Math.max(0.5, dprCapFor(quality) * normalizedScale);
|
|
283
|
+
}
|
|
278
284
|
|
|
279
|
-
/**
|
|
280
|
-
* Merge defaults < preset < user. Unknown user keys are preserved so the
|
|
281
|
-
* component API can grow (new props, cssVars, callbacks) without a breaking
|
|
282
|
-
* change.
|
|
285
|
+
/**
|
|
286
|
+
* Merge defaults < preset < user. Unknown user keys are preserved so the
|
|
287
|
+
* component API can grow (new props, cssVars, callbacks) without a breaking
|
|
288
|
+
* change.
|
|
283
289
|
*/
|
|
284
290
|
function normalizeOptions(defaults, preset, user) {
|
|
285
291
|
// undefined means "not provided" (e.g. Vue $props with unset props):
|
|
@@ -297,9 +303,9 @@ function normalizeOptions(defaults, preset, user) {
|
|
|
297
303
|
return _objectSpread2(_objectSpread2(_objectSpread2({}, defaults), presetOptions), userOptions);
|
|
298
304
|
}
|
|
299
305
|
|
|
300
|
-
/**
|
|
301
|
-
* 公共色板:NC-01~NC-06 的四色组(底色 / 主色 / 辅色 / 高光色)。
|
|
302
|
-
* Capsule 预置与 dlc-color 等组件共用,新增色板只改这里。
|
|
306
|
+
/**
|
|
307
|
+
* 公共色板:NC-01~NC-06 的四色组(底色 / 主色 / 辅色 / 高光色)。
|
|
308
|
+
* Capsule 预置与 dlc-color 等组件共用,新增色板只改这里。
|
|
303
309
|
*/
|
|
304
310
|
var PALETTES = {
|
|
305
311
|
original: ['#FFF3EA', '#F5B27A', '#F67BC6', '#A978E8'],
|
|
@@ -310,9 +316,9 @@ var PALETTES = {
|
|
|
310
316
|
plus: ['#FFF0E6', '#F6C26B', '#F98A64', '#E86D74']
|
|
311
317
|
};
|
|
312
318
|
|
|
313
|
-
/**
|
|
314
|
-
* Capsule 预置:仅星云材质 NC-01~NC-06(NC-07~09 aurora 已移除)。
|
|
315
|
-
* 颜色引用公共色板,seed/speed 决定形态与流速。
|
|
319
|
+
/**
|
|
320
|
+
* Capsule 预置:仅星云材质 NC-01~NC-06(NC-07~09 aurora 已移除)。
|
|
321
|
+
* 颜色引用公共色板,seed/speed 决定形态与流速。
|
|
316
322
|
*/
|
|
317
323
|
var CAPSULE_PRESETS = [{
|
|
318
324
|
id: 'original',
|
|
@@ -400,6 +406,15 @@ var PROGRESS_PRESETS = [{
|
|
|
400
406
|
initialProgress: 30,
|
|
401
407
|
edgeStyle: 'tide',
|
|
402
408
|
colors: ['#0A2239', '#2E9BFF', '#7FE3FF', '#EAF9FF']
|
|
409
|
+
}, {
|
|
410
|
+
id: 'botanic-lab',
|
|
411
|
+
code: 'NC-14',
|
|
412
|
+
name: '森息',
|
|
413
|
+
subtitle: 'MOSS CULTURE / ROOTING',
|
|
414
|
+
group: 'progress',
|
|
415
|
+
initialProgress: 46,
|
|
416
|
+
edgeStyle: 'flow',
|
|
417
|
+
colors: ['#102A23', '#287A58', '#9BD65B', '#F2FFC4']
|
|
403
418
|
}];
|
|
404
419
|
|
|
405
420
|
[].concat(_toConsumableArray(CAPSULE_PRESETS), _toConsumableArray(PROGRESS_PRESETS));
|
|
@@ -430,6 +445,11 @@ var DEFAULTS = {
|
|
|
430
445
|
height: 160,
|
|
431
446
|
quality: 'auto',
|
|
432
447
|
renderer: 'auto',
|
|
448
|
+
renderScale: 1,
|
|
449
|
+
powerPreference: 'high-performance',
|
|
450
|
+
fps: 60,
|
|
451
|
+
paused: false,
|
|
452
|
+
static: false,
|
|
433
453
|
respectReducedMotion: true,
|
|
434
454
|
mouseColor: true,
|
|
435
455
|
textRatio: 39
|
|
@@ -700,7 +720,7 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
700
720
|
alpha: false,
|
|
701
721
|
antialias: false,
|
|
702
722
|
depth: false,
|
|
703
|
-
powerPreference: 'high-performance',
|
|
723
|
+
powerPreference: this.options.powerPreference || 'high-performance',
|
|
704
724
|
preserveDrawingBuffer: false
|
|
705
725
|
});
|
|
706
726
|
if (!this.gl) throw new Error('WebGL2 is not available');
|
|
@@ -711,16 +731,19 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
711
731
|
this.motion = 0;
|
|
712
732
|
this.motionTarget = 0;
|
|
713
733
|
this.timeOffset = preset.seed * 0.73;
|
|
734
|
+
this.colors = preset.colors.map(hexToRgb01);
|
|
714
735
|
this.visible = true;
|
|
715
736
|
this.disposed = false;
|
|
716
737
|
_assertClassBrand(_CosmicRenderer_brand, this, _setupGeometry).call(this);
|
|
717
738
|
_assertClassBrand(_CosmicRenderer_brand, this, _bindEvents).call(this);
|
|
739
|
+
_assertClassBrand(_CosmicRenderer_brand, this, _bindContextEvents).call(this);
|
|
718
740
|
this.resize();
|
|
719
741
|
}
|
|
720
742
|
return _createClass(CosmicRenderer, [{
|
|
721
743
|
key: "setPreset",
|
|
722
744
|
value: function setPreset(preset) {
|
|
723
745
|
this.preset = _objectSpread2({}, preset);
|
|
746
|
+
this.colors = preset.colors.map(hexToRgb01);
|
|
724
747
|
this.timeOffset = preset.seed * 0.73;
|
|
725
748
|
}
|
|
726
749
|
}, {
|
|
@@ -765,15 +788,14 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
765
788
|
if (this.canvas.width !== width || this.canvas.height !== height) {
|
|
766
789
|
this.canvas.width = width;
|
|
767
790
|
this.canvas.height = height;
|
|
768
|
-
this.gl.viewport(0, 0, width, height);
|
|
769
791
|
}
|
|
792
|
+
this.gl.viewport(0, 0, width, height);
|
|
770
793
|
}
|
|
771
794
|
}, {
|
|
772
795
|
key: "draw",
|
|
773
796
|
value: function draw(elapsedSeconds) {
|
|
774
797
|
var paused = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
775
798
|
if (this.disposed || !this.visible) return;
|
|
776
|
-
this.resize();
|
|
777
799
|
var gl = this.gl;
|
|
778
800
|
this.pointer[0] += (this.pointerTarget[0] - this.pointer[0]) * 0.08;
|
|
779
801
|
this.pointer[1] += (this.pointerTarget[1] - this.pointer[1]) * 0.08;
|
|
@@ -782,16 +804,15 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
782
804
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
|
|
783
805
|
gl.enableVertexAttribArray(this.locations.position);
|
|
784
806
|
gl.vertexAttribPointer(this.locations.position, 2, gl.FLOAT, false, 0, 0);
|
|
785
|
-
var colors = this.preset.colors.map(hexToRgb01);
|
|
786
807
|
gl.uniform2f(this.locations.resolution, this.canvas.width, this.canvas.height);
|
|
787
808
|
gl.uniform1f(this.locations.time, this.timeOffset + (paused ? 0 : elapsedSeconds * this.preset.speed));
|
|
788
809
|
gl.uniform1f(this.locations.seed, this.preset.seed);
|
|
789
810
|
gl.uniform1f(this.locations.motion, this.motion);
|
|
790
811
|
gl.uniform2f(this.locations.pointer, this.pointer[0], this.pointer[1]);
|
|
791
|
-
gl.uniform3fv(this.locations.colorA, colors[0]);
|
|
792
|
-
gl.uniform3fv(this.locations.colorB, colors[1]);
|
|
793
|
-
gl.uniform3fv(this.locations.colorC, colors[2]);
|
|
794
|
-
gl.uniform3fv(this.locations.colorD, colors[3]);
|
|
812
|
+
gl.uniform3fv(this.locations.colorA, this.colors[0]);
|
|
813
|
+
gl.uniform3fv(this.locations.colorB, this.colors[1]);
|
|
814
|
+
gl.uniform3fv(this.locations.colorC, this.colors[2]);
|
|
815
|
+
gl.uniform3fv(this.locations.colorD, this.colors[3]);
|
|
795
816
|
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
796
817
|
}
|
|
797
818
|
}, {
|
|
@@ -802,6 +823,8 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
802
823
|
target.removeEventListener('pointermove', this.onPointerMove);
|
|
803
824
|
target.removeEventListener('pointerdown', this.onPointerMove);
|
|
804
825
|
target.removeEventListener('pointerleave', this.onPointerLeave);
|
|
826
|
+
this.canvas.removeEventListener('webglcontextlost', this.onContextLost, false);
|
|
827
|
+
this.canvas.removeEventListener('webglcontextrestored', this.onContextRestored, false);
|
|
805
828
|
this.gl.deleteBuffer(this.buffer);
|
|
806
829
|
this.gl.deleteProgram(this.program);
|
|
807
830
|
var lose = this.gl.getExtension('WEBGL_lose_context');
|
|
@@ -858,6 +881,26 @@ function _bindEvents() {
|
|
|
858
881
|
passive: true
|
|
859
882
|
});
|
|
860
883
|
}
|
|
884
|
+
function _bindContextEvents() {
|
|
885
|
+
var _this3 = this;
|
|
886
|
+
this.onContextLost = function (event) {
|
|
887
|
+
event.preventDefault();
|
|
888
|
+
if (_this3.disposed) return;
|
|
889
|
+
_this3.visible = false;
|
|
890
|
+
if (typeof _this3.options.onContextLost === 'function') _this3.options.onContextLost(event);
|
|
891
|
+
};
|
|
892
|
+
this.onContextRestored = function () {
|
|
893
|
+
if (_this3.disposed) return;
|
|
894
|
+
_this3.program = createProgram(_this3.gl);
|
|
895
|
+
_this3.locations = _assertClassBrand(_CosmicRenderer_brand, _this3, _getLocations).call(_this3);
|
|
896
|
+
_assertClassBrand(_CosmicRenderer_brand, _this3, _setupGeometry).call(_this3);
|
|
897
|
+
_this3.visible = true;
|
|
898
|
+
_this3.resize();
|
|
899
|
+
if (typeof _this3.options.onContextRestored === 'function') _this3.options.onContextRestored();
|
|
900
|
+
};
|
|
901
|
+
this.canvas.addEventListener('webglcontextlost', this.onContextLost, false);
|
|
902
|
+
this.canvas.addEventListener('webglcontextrestored', this.onContextRestored, false);
|
|
903
|
+
}
|
|
861
904
|
|
|
862
905
|
function rgb(color) {
|
|
863
906
|
var alpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
@@ -872,18 +915,20 @@ function rgb(color) {
|
|
|
872
915
|
}
|
|
873
916
|
var FallbackRenderer = /*#__PURE__*/function () {
|
|
874
917
|
function FallbackRenderer(canvas, preset) {
|
|
918
|
+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
875
919
|
_classCallCheck(this, FallbackRenderer);
|
|
876
920
|
this.canvas = canvas;
|
|
877
921
|
this.preset = preset;
|
|
878
922
|
this.context = canvas.getContext('2d');
|
|
879
923
|
this.visible = true;
|
|
880
924
|
this.timePhase = 0;
|
|
925
|
+
this.dprCap = options.dprCap || 1.5;
|
|
881
926
|
}
|
|
882
927
|
return _createClass(FallbackRenderer, [{
|
|
883
928
|
key: "resize",
|
|
884
929
|
value: function resize() {
|
|
885
930
|
var rect = this.canvas.getBoundingClientRect();
|
|
886
|
-
var dpr = Math.min(window.devicePixelRatio || 1,
|
|
931
|
+
var dpr = Math.min(window.devicePixelRatio || 1, this.dprCap);
|
|
887
932
|
var width = Math.max(2, Math.round(rect.width * dpr));
|
|
888
933
|
var height = Math.max(2, Math.round(rect.height * dpr));
|
|
889
934
|
if (this.canvas.width !== width || this.canvas.height !== height) {
|
|
@@ -924,7 +969,6 @@ var FallbackRenderer = /*#__PURE__*/function () {
|
|
|
924
969
|
key: "draw",
|
|
925
970
|
value: function draw(time) {
|
|
926
971
|
if (!this.visible) return;
|
|
927
|
-
this.resize();
|
|
928
972
|
this.drawNebula(time);
|
|
929
973
|
}
|
|
930
974
|
}, {
|
|
@@ -932,6 +976,12 @@ var FallbackRenderer = /*#__PURE__*/function () {
|
|
|
932
976
|
value: function setPreset(preset) {
|
|
933
977
|
this.preset = preset;
|
|
934
978
|
}
|
|
979
|
+
}, {
|
|
980
|
+
key: "setDprCap",
|
|
981
|
+
value: function setDprCap(cap) {
|
|
982
|
+
this.dprCap = cap;
|
|
983
|
+
this.resize();
|
|
984
|
+
}
|
|
935
985
|
}, {
|
|
936
986
|
key: "randomize",
|
|
937
987
|
value: function randomize() {
|
|
@@ -949,10 +999,10 @@ var FallbackRenderer = /*#__PURE__*/function () {
|
|
|
949
999
|
}]);
|
|
950
1000
|
}();
|
|
951
1001
|
|
|
952
|
-
/**
|
|
953
|
-
* Document-level shared rAF scheduler. Every component instance subscribes
|
|
954
|
-
* its own frame callback; the whole page runs ONE animation loop (like the
|
|
955
|
-
* original demo), which avoids jank from many competing rAF loops.
|
|
1002
|
+
/**
|
|
1003
|
+
* Document-level shared rAF scheduler. Every component instance subscribes
|
|
1004
|
+
* its own frame callback; the whole page runs ONE animation loop (like the
|
|
1005
|
+
* original demo), which avoids jank from many competing rAF loops.
|
|
956
1006
|
*/
|
|
957
1007
|
var subscribers = [];
|
|
958
1008
|
var running = false;
|
|
@@ -960,11 +1010,7 @@ var rafId = 0;
|
|
|
960
1010
|
var last = 0;
|
|
961
1011
|
function tick(now) {
|
|
962
1012
|
if (!running) return;
|
|
963
|
-
var
|
|
964
|
-
last = now;
|
|
965
|
-
// Schedule the next frame BEFORE running callbacks so one throwing
|
|
966
|
-
// subscriber can never kill the whole animation loop.
|
|
967
|
-
rafId = requestAnimationFrame(tick);
|
|
1013
|
+
var activeItems = [];
|
|
968
1014
|
{
|
|
969
1015
|
var _iterator = _createForOfIteratorHelper(subscribers.slice()),
|
|
970
1016
|
_step;
|
|
@@ -972,10 +1018,8 @@ function tick(now) {
|
|
|
972
1018
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
973
1019
|
var item = _step.value;
|
|
974
1020
|
try {
|
|
975
|
-
if (!item.isPaused())
|
|
976
|
-
} catch (
|
|
977
|
-
console.warn('[dlc-ui] frame error:', error);
|
|
978
|
-
}
|
|
1021
|
+
if (!item.isPaused()) activeItems.push(item);
|
|
1022
|
+
} catch (_unused) {}
|
|
979
1023
|
}
|
|
980
1024
|
} catch (err) {
|
|
981
1025
|
_iterator.e(err);
|
|
@@ -983,6 +1027,25 @@ function tick(now) {
|
|
|
983
1027
|
_iterator.f();
|
|
984
1028
|
}
|
|
985
1029
|
}
|
|
1030
|
+
if (activeItems.length === 0) {
|
|
1031
|
+
running = false;
|
|
1032
|
+
rafId = 0;
|
|
1033
|
+
last = 0;
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
var delta = last ? Math.min((now - last) / 1000, 0.05) : 0;
|
|
1037
|
+
last = now;
|
|
1038
|
+
// Schedule the next frame BEFORE running callbacks so one throwing
|
|
1039
|
+
// subscriber can never kill the whole animation loop.
|
|
1040
|
+
rafId = requestAnimationFrame(tick);
|
|
1041
|
+
for (var _i = 0, _activeItems = activeItems; _i < _activeItems.length; _i++) {
|
|
1042
|
+
var _item = _activeItems[_i];
|
|
1043
|
+
try {
|
|
1044
|
+
_item.onFrame(delta, now);
|
|
1045
|
+
} catch (error) {
|
|
1046
|
+
console.warn('[dlc-ui] frame error:', error);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
986
1049
|
if (subscribers.length === 0) {
|
|
987
1050
|
cancelAnimationFrame(rafId);
|
|
988
1051
|
running = false;
|
|
@@ -995,6 +1058,9 @@ function start() {
|
|
|
995
1058
|
last = 0;
|
|
996
1059
|
rafId = requestAnimationFrame(tick);
|
|
997
1060
|
}
|
|
1061
|
+
function wakeScheduler() {
|
|
1062
|
+
start();
|
|
1063
|
+
}
|
|
998
1064
|
function subscribeScheduler(onFrame, isPaused) {
|
|
999
1065
|
var item = {
|
|
1000
1066
|
onFrame: onFrame,
|
|
@@ -1013,11 +1079,12 @@ function subscribeScheduler(onFrame, isPaused) {
|
|
|
1013
1079
|
};
|
|
1014
1080
|
}
|
|
1015
1081
|
|
|
1016
|
-
/**
|
|
1017
|
-
* Gates drawing on "element intersects viewport AND the page tab is visible".
|
|
1018
|
-
* Falls back to always-visible when IntersectionObserver is unavailable.
|
|
1082
|
+
/**
|
|
1083
|
+
* Gates drawing on "element intersects viewport AND the page tab is visible".
|
|
1084
|
+
* Falls back to always-visible when IntersectionObserver is unavailable.
|
|
1019
1085
|
*/
|
|
1020
1086
|
function createVisibilityGuard(element) {
|
|
1087
|
+
var onChange = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
1021
1088
|
var intersecting = true;
|
|
1022
1089
|
var pageVisible = typeof document === 'undefined' || !document.hidden;
|
|
1023
1090
|
var disposed = false;
|
|
@@ -1027,6 +1094,7 @@ function createVisibilityGuard(element) {
|
|
|
1027
1094
|
intersecting = entries.some(function (entry) {
|
|
1028
1095
|
return entry.isIntersecting;
|
|
1029
1096
|
});
|
|
1097
|
+
if (typeof onChange === 'function') onChange();
|
|
1030
1098
|
}, {
|
|
1031
1099
|
rootMargin: '180px'
|
|
1032
1100
|
});
|
|
@@ -1034,6 +1102,7 @@ function createVisibilityGuard(element) {
|
|
|
1034
1102
|
}
|
|
1035
1103
|
var onVisibilityChange = function onVisibilityChange() {
|
|
1036
1104
|
pageVisible = typeof document !== 'undefined' && !document.hidden;
|
|
1105
|
+
if (typeof onChange === 'function') onChange();
|
|
1037
1106
|
};
|
|
1038
1107
|
if (typeof document !== 'undefined') {
|
|
1039
1108
|
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
@@ -1069,18 +1138,69 @@ function nextTick(fn) {
|
|
|
1069
1138
|
}
|
|
1070
1139
|
}
|
|
1071
1140
|
|
|
1072
|
-
function
|
|
1073
|
-
|
|
1141
|
+
function normalizeFps(value) {
|
|
1142
|
+
var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 60;
|
|
1143
|
+
var fps = Number(value);
|
|
1144
|
+
if (!Number.isFinite(fps)) return fallback;
|
|
1145
|
+
return Math.min(60, Math.max(1, fps));
|
|
1146
|
+
}
|
|
1147
|
+
function createFrameGate() {
|
|
1148
|
+
var initialFps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 60;
|
|
1149
|
+
var fps = normalizeFps(initialFps);
|
|
1150
|
+
var elapsed = 0;
|
|
1151
|
+
return {
|
|
1152
|
+
shouldDraw: function shouldDraw(delta) {
|
|
1153
|
+
elapsed += delta;
|
|
1154
|
+
var interval = 1 / fps;
|
|
1155
|
+
if (elapsed + 0.0001 < interval) return false;
|
|
1156
|
+
elapsed %= interval;
|
|
1157
|
+
return true;
|
|
1158
|
+
},
|
|
1159
|
+
setFps: function setFps(value) {
|
|
1160
|
+
fps = normalizeFps(value, fps);
|
|
1161
|
+
elapsed = 0;
|
|
1162
|
+
return fps;
|
|
1163
|
+
},
|
|
1164
|
+
getFps: function getFps() {
|
|
1165
|
+
return fps;
|
|
1166
|
+
}
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
function createReducedMotionPreference(enabled, onChange) {
|
|
1170
|
+
var query = enabled && typeof matchMedia !== 'undefined' ? matchMedia('(prefers-reduced-motion: reduce)') : null;
|
|
1171
|
+
var notify = function notify() {
|
|
1172
|
+
if (typeof onChange === 'function') onChange(Boolean(query && query.matches));
|
|
1173
|
+
};
|
|
1174
|
+
if (query) {
|
|
1175
|
+
if (typeof query.addEventListener === 'function') query.addEventListener('change', notify);else if (typeof query.addListener === 'function') query.addListener(notify);
|
|
1176
|
+
}
|
|
1177
|
+
return {
|
|
1178
|
+
matches: function matches() {
|
|
1179
|
+
return Boolean(query && query.matches);
|
|
1180
|
+
},
|
|
1181
|
+
dispose: function dispose() {
|
|
1182
|
+
if (!query) return;
|
|
1183
|
+
if (typeof query.removeEventListener === 'function') query.removeEventListener('change', notify);else if (typeof query.removeListener === 'function') query.removeListener(notify);
|
|
1184
|
+
}
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
function toFiniteNumber(value) {
|
|
1189
|
+
if (value == null || typeof value === 'boolean') return null;
|
|
1190
|
+
if (typeof value === 'string' && value.trim() === '') return null;
|
|
1191
|
+
var number = Number(value);
|
|
1192
|
+
return Number.isFinite(number) ? number : null;
|
|
1074
1193
|
}
|
|
1075
1194
|
|
|
1076
|
-
/**
|
|
1195
|
+
/**
|
|
1077
1196
|
* Mount a cosmic (nebula) capsule into `container`.
|
|
1078
1197
|
*
|
|
1079
1198
|
* Options: preset (literary name), width, height (number=px or string with
|
|
1080
1199
|
* px/%/vw/vh/em/rem), colors, seed, speed, textRatio (0-100, text region
|
|
1081
1200
|
* width in percent), text (HTML string or DOM nodes for the text slot),
|
|
1082
1201
|
* colorContent (HTML string or DOM nodes for the color slot), quality,
|
|
1083
|
-
* renderer,
|
|
1202
|
+
* renderer, quality, renderScale, powerPreference, fps, paused/static,
|
|
1203
|
+
* respectReducedMotion, mouseColor, cssVars.
|
|
1084
1204
|
*/
|
|
1085
1205
|
function createCapsule(container) {
|
|
1086
1206
|
var _options$preset;
|
|
@@ -1090,10 +1210,19 @@ function createCapsule(container) {
|
|
|
1090
1210
|
}
|
|
1091
1211
|
var preset = _objectSpread2({}, getPreset('capsule', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : '初光'));
|
|
1092
1212
|
var merged = normalizeOptions(DEFAULTS.capsule, preset, options);
|
|
1093
|
-
var normalizedColors = merged.colors.map(normalizeColor);
|
|
1094
|
-
if (normalizedColors.every(Boolean)) preset.colors = normalizedColors;
|
|
1095
|
-
|
|
1096
|
-
|
|
1213
|
+
var normalizedColors = Array.isArray(merged.colors) ? merged.colors.map(normalizeColor) : [];
|
|
1214
|
+
if (normalizedColors.length === 4 && normalizedColors.every(Boolean)) preset.colors = normalizedColors;
|
|
1215
|
+
var initialSeed = toFiniteNumber(merged.seed);
|
|
1216
|
+
var initialSpeed = toFiniteNumber(merged.speed);
|
|
1217
|
+
if (initialSeed !== null) preset.seed = initialSeed;
|
|
1218
|
+
if (initialSpeed !== null) preset.speed = initialSpeed;
|
|
1219
|
+
merged.colors = _toConsumableArray(preset.colors);
|
|
1220
|
+
merged.seed = preset.seed;
|
|
1221
|
+
merged.speed = preset.speed;
|
|
1222
|
+
var optionColors = Array.isArray(options.colors) ? options.colors.map(normalizeColor) : [];
|
|
1223
|
+
var colorOverride = optionColors.length === 4 && optionColors.every(Boolean) ? _toConsumableArray(optionColors) : null;
|
|
1224
|
+
var seedOverride = options.seed !== undefined ? toFiniteNumber(options.seed) : null;
|
|
1225
|
+
var speedOverride = options.speed !== undefined ? toFiniteNumber(options.speed) : null;
|
|
1097
1226
|
var customLabel = typeof options.label === 'string' && options.label ? options.label : null;
|
|
1098
1227
|
var root = document.createElement('div');
|
|
1099
1228
|
root.className = 'hj-capsule-root hj-capsule-cosmic';
|
|
@@ -1145,25 +1274,49 @@ function createCapsule(container) {
|
|
|
1145
1274
|
root.appendChild(canvas);
|
|
1146
1275
|
container.appendChild(root);
|
|
1147
1276
|
var emitter = createEmitter();
|
|
1148
|
-
var
|
|
1277
|
+
var manuallyPaused = merged.paused === true;
|
|
1278
|
+
var reducedPaused = false;
|
|
1279
|
+
var staticMode = merged.static === true;
|
|
1280
|
+
var contextLost = false;
|
|
1149
1281
|
var disposed = false;
|
|
1282
|
+
var renderOnce = function renderOnce() {};
|
|
1150
1283
|
var dirty = {
|
|
1151
1284
|
preset: false,
|
|
1152
1285
|
seed: false,
|
|
1153
1286
|
speed: false,
|
|
1154
1287
|
colors: false,
|
|
1155
1288
|
textRatio: false,
|
|
1156
|
-
cssVars: false
|
|
1289
|
+
cssVars: false,
|
|
1290
|
+
mouseColor: false,
|
|
1291
|
+
quality: false,
|
|
1292
|
+
renderScale: false,
|
|
1293
|
+
paused: false,
|
|
1294
|
+
static: false,
|
|
1295
|
+
fps: false
|
|
1157
1296
|
};
|
|
1158
1297
|
var renderer;
|
|
1159
1298
|
var useWebgl = merged.renderer !== 'canvas2d';
|
|
1160
1299
|
if (useWebgl) {
|
|
1161
1300
|
try {
|
|
1162
1301
|
renderer = new CosmicRenderer(canvas, merged, {
|
|
1163
|
-
dprCap:
|
|
1302
|
+
dprCap: effectiveDprCap(merged.quality, merged.renderScale),
|
|
1303
|
+
mouseColor: merged.mouseColor !== false,
|
|
1304
|
+
powerPreference: merged.powerPreference,
|
|
1305
|
+
onContextLost: function onContextLost() {
|
|
1306
|
+
contextLost = true;
|
|
1307
|
+
emitter.emit('contextlost', {});
|
|
1308
|
+
},
|
|
1309
|
+
onContextRestored: function onContextRestored() {
|
|
1310
|
+
contextLost = false;
|
|
1311
|
+
emitter.emit('contextrestored', {});
|
|
1312
|
+
renderOnce();
|
|
1313
|
+
wakeScheduler();
|
|
1314
|
+
}
|
|
1164
1315
|
});
|
|
1165
1316
|
} catch (error) {
|
|
1166
|
-
renderer = new FallbackRenderer(canvas, merged
|
|
1317
|
+
renderer = new FallbackRenderer(canvas, merged, {
|
|
1318
|
+
dprCap: effectiveDprCap(merged.quality, merged.renderScale)
|
|
1319
|
+
});
|
|
1167
1320
|
nextTick(function () {
|
|
1168
1321
|
if (disposed) return;
|
|
1169
1322
|
emitter.emit('error', {
|
|
@@ -1172,8 +1325,15 @@ function createCapsule(container) {
|
|
|
1172
1325
|
});
|
|
1173
1326
|
}
|
|
1174
1327
|
} else {
|
|
1175
|
-
renderer = new FallbackRenderer(canvas, merged
|
|
1328
|
+
renderer = new FallbackRenderer(canvas, merged, {
|
|
1329
|
+
dprCap: effectiveDprCap(merged.quality, merged.renderScale)
|
|
1330
|
+
});
|
|
1176
1331
|
}
|
|
1332
|
+
var animationTime = 0;
|
|
1333
|
+
var frameGate = createFrameGate(merged.fps);
|
|
1334
|
+
renderOnce = function renderOnce() {
|
|
1335
|
+
return renderer.draw(animationTime);
|
|
1336
|
+
};
|
|
1177
1337
|
var applySize = function applySize() {
|
|
1178
1338
|
root.style.width = parseSize(merged.width);
|
|
1179
1339
|
root.style.height = parseSize(merged.height);
|
|
@@ -1191,11 +1351,21 @@ function createCapsule(container) {
|
|
|
1191
1351
|
renderer.resize();
|
|
1192
1352
|
};
|
|
1193
1353
|
applySize();
|
|
1194
|
-
var
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
var
|
|
1354
|
+
var resize = function resize() {
|
|
1355
|
+
renderer.resize();
|
|
1356
|
+
if (manuallyPaused || reducedPaused || staticMode) renderOnce();
|
|
1357
|
+
};
|
|
1358
|
+
var resizeObserver = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(resize) : null;
|
|
1359
|
+
if (resizeObserver) resizeObserver.observe(root);else window.addEventListener('resize', resize);
|
|
1360
|
+
var visibility = createVisibilityGuard(root, wakeScheduler);
|
|
1361
|
+
var motionPreference = createReducedMotionPreference(merged.respectReducedMotion, function (matches) {
|
|
1362
|
+
reducedPaused = matches;
|
|
1363
|
+
if (matches) renderOnce();else wakeScheduler();
|
|
1364
|
+
});
|
|
1365
|
+
reducedPaused = motionPreference.matches();
|
|
1366
|
+
var isMotionPaused = function isMotionPaused() {
|
|
1367
|
+
return manuallyPaused || reducedPaused || staticMode || contextLost;
|
|
1368
|
+
};
|
|
1199
1369
|
root.addEventListener('pointerenter', function () {
|
|
1200
1370
|
return emitter.emit('pointerenter', {
|
|
1201
1371
|
preset: _objectSpread2({}, preset)
|
|
@@ -1230,12 +1400,12 @@ function createCapsule(container) {
|
|
|
1230
1400
|
preset: _objectSpread2({}, preset)
|
|
1231
1401
|
});
|
|
1232
1402
|
});
|
|
1233
|
-
|
|
1403
|
+
renderOnce();
|
|
1234
1404
|
var unsubscribe = subscribeScheduler(function (delta) {
|
|
1235
1405
|
animationTime += delta;
|
|
1236
|
-
if (
|
|
1406
|
+
if (frameGate.shouldDraw(delta)) renderer.draw(animationTime);
|
|
1237
1407
|
}, function () {
|
|
1238
|
-
return
|
|
1408
|
+
return isMotionPaused() || !visibility.isVisible();
|
|
1239
1409
|
});
|
|
1240
1410
|
nextTick(function () {
|
|
1241
1411
|
if (disposed) return;
|
|
@@ -1258,11 +1428,15 @@ function createCapsule(container) {
|
|
|
1258
1428
|
var next = getPreset('capsule', ref);
|
|
1259
1429
|
dirty.preset = true;
|
|
1260
1430
|
Object.assign(preset, next);
|
|
1431
|
+
if (colorOverride) preset.colors = _toConsumableArray(colorOverride);
|
|
1432
|
+
if (seedOverride !== null) preset.seed = seedOverride;
|
|
1433
|
+
if (speedOverride !== null) preset.speed = speedOverride;
|
|
1261
1434
|
var nextColors = preset.colors.map(normalizeColor);
|
|
1262
1435
|
if (nextColors.every(Boolean)) preset.colors = nextColors;
|
|
1263
1436
|
renderer.setPreset(_objectSpread2({}, preset));
|
|
1264
1437
|
syncTheme();
|
|
1265
1438
|
renderer.resize();
|
|
1439
|
+
if (isMotionPaused()) renderOnce();
|
|
1266
1440
|
emitter.emit('presetchange', {
|
|
1267
1441
|
preset: _objectSpread2({}, next)
|
|
1268
1442
|
});
|
|
@@ -1274,26 +1448,32 @@ function createCapsule(container) {
|
|
|
1274
1448
|
return !color;
|
|
1275
1449
|
})) return this;
|
|
1276
1450
|
dirty.colors = true;
|
|
1451
|
+
colorOverride = _toConsumableArray(next);
|
|
1277
1452
|
preset.colors = next;
|
|
1278
1453
|
renderer.setPreset(_objectSpread2(_objectSpread2({}, preset), {}, {
|
|
1279
1454
|
colors: next
|
|
1280
1455
|
}));
|
|
1456
|
+
if (isMotionPaused()) renderOnce();
|
|
1281
1457
|
return this;
|
|
1282
1458
|
},
|
|
1283
1459
|
setSeed: function setSeed(seed) {
|
|
1284
|
-
var value =
|
|
1285
|
-
if (
|
|
1460
|
+
var value = toFiniteNumber(seed);
|
|
1461
|
+
if (value === null) return this;
|
|
1286
1462
|
dirty.seed = true;
|
|
1463
|
+
seedOverride = value;
|
|
1287
1464
|
preset.seed = value;
|
|
1288
1465
|
renderer.setPreset(_objectSpread2({}, preset));
|
|
1466
|
+
if (isMotionPaused()) renderOnce();
|
|
1289
1467
|
return this;
|
|
1290
1468
|
},
|
|
1291
1469
|
setSpeed: function setSpeed(speed) {
|
|
1292
|
-
var value =
|
|
1293
|
-
if (
|
|
1470
|
+
var value = toFiniteNumber(speed);
|
|
1471
|
+
if (value === null) return this;
|
|
1294
1472
|
dirty.speed = true;
|
|
1473
|
+
speedOverride = value;
|
|
1295
1474
|
preset.speed = value;
|
|
1296
1475
|
renderer.setPreset(_objectSpread2({}, preset));
|
|
1476
|
+
if (isMotionPaused()) renderOnce();
|
|
1297
1477
|
return this;
|
|
1298
1478
|
},
|
|
1299
1479
|
setText: function setText(content) {
|
|
@@ -1329,6 +1509,7 @@ function createCapsule(container) {
|
|
|
1329
1509
|
return this;
|
|
1330
1510
|
},
|
|
1331
1511
|
setMouseColor: function setMouseColor(value) {
|
|
1512
|
+
dirty.mouseColor = true;
|
|
1332
1513
|
merged.mouseColor = value !== false;
|
|
1333
1514
|
if (typeof renderer.setMouseColor === 'function') renderer.setMouseColor(merged.mouseColor);
|
|
1334
1515
|
return this;
|
|
@@ -1343,6 +1524,7 @@ function createCapsule(container) {
|
|
|
1343
1524
|
merged.height = height;
|
|
1344
1525
|
}
|
|
1345
1526
|
applySize();
|
|
1527
|
+
if (isMotionPaused()) renderOnce();
|
|
1346
1528
|
return this;
|
|
1347
1529
|
},
|
|
1348
1530
|
randomize: function randomize() {
|
|
@@ -1350,23 +1532,59 @@ function createCapsule(container) {
|
|
|
1350
1532
|
return this;
|
|
1351
1533
|
},
|
|
1352
1534
|
pause: function pause() {
|
|
1353
|
-
paused = true;
|
|
1535
|
+
dirty.paused = true;
|
|
1536
|
+
manuallyPaused = true;
|
|
1537
|
+
renderOnce();
|
|
1354
1538
|
return this;
|
|
1355
1539
|
},
|
|
1356
1540
|
resume: function resume() {
|
|
1357
|
-
paused =
|
|
1541
|
+
dirty.paused = true;
|
|
1542
|
+
manuallyPaused = false;
|
|
1543
|
+
wakeScheduler();
|
|
1544
|
+
return this;
|
|
1545
|
+
},
|
|
1546
|
+
setPaused: function setPaused(value) {
|
|
1547
|
+
return value ? this.pause() : this.resume();
|
|
1548
|
+
},
|
|
1549
|
+
setStatic: function setStatic(value) {
|
|
1550
|
+
dirty.static = true;
|
|
1551
|
+
staticMode = value === true;
|
|
1552
|
+
merged.static = staticMode;
|
|
1553
|
+
if (staticMode) renderOnce();else wakeScheduler();
|
|
1554
|
+
return this;
|
|
1555
|
+
},
|
|
1556
|
+
setFps: function setFps(fps) {
|
|
1557
|
+
dirty.fps = true;
|
|
1558
|
+
merged.fps = frameGate.setFps(fps);
|
|
1559
|
+
wakeScheduler();
|
|
1358
1560
|
return this;
|
|
1359
1561
|
},
|
|
1360
1562
|
setQuality: function setQuality(quality) {
|
|
1563
|
+
dirty.quality = true;
|
|
1361
1564
|
merged.quality = quality;
|
|
1362
|
-
if (typeof renderer.setDprCap === 'function')
|
|
1565
|
+
if (typeof renderer.setDprCap === 'function') {
|
|
1566
|
+
renderer.setDprCap(effectiveDprCap(quality, merged.renderScale));
|
|
1567
|
+
}
|
|
1568
|
+
if (isMotionPaused()) renderOnce();
|
|
1569
|
+
return this;
|
|
1570
|
+
},
|
|
1571
|
+
setRenderScale: function setRenderScale(renderScale) {
|
|
1572
|
+
var value = Number(renderScale);
|
|
1573
|
+
if (!Number.isFinite(value)) return this;
|
|
1574
|
+
dirty.renderScale = true;
|
|
1575
|
+
merged.renderScale = Math.min(1, Math.max(0.25, value));
|
|
1576
|
+
if (typeof renderer.setDprCap === 'function') {
|
|
1577
|
+
renderer.setDprCap(effectiveDprCap(merged.quality, merged.renderScale));
|
|
1578
|
+
}
|
|
1579
|
+
if (isMotionPaused()) renderOnce();
|
|
1363
1580
|
return this;
|
|
1364
1581
|
},
|
|
1365
1582
|
dispose: function dispose() {
|
|
1366
1583
|
disposed = true;
|
|
1367
1584
|
unsubscribe();
|
|
1368
1585
|
visibility.dispose();
|
|
1369
|
-
|
|
1586
|
+
motionPreference.dispose();
|
|
1587
|
+
if (resizeObserver) resizeObserver.disconnect();else window.removeEventListener('resize', resize);
|
|
1370
1588
|
renderer.dispose();
|
|
1371
1589
|
root.remove();
|
|
1372
1590
|
},
|
|
@@ -1376,6 +1594,24 @@ function createCapsule(container) {
|
|
|
1376
1594
|
get cssVars() {
|
|
1377
1595
|
return merged.cssVars;
|
|
1378
1596
|
},
|
|
1597
|
+
get mouseColor() {
|
|
1598
|
+
return merged.mouseColor;
|
|
1599
|
+
},
|
|
1600
|
+
get quality() {
|
|
1601
|
+
return merged.quality;
|
|
1602
|
+
},
|
|
1603
|
+
get renderScale() {
|
|
1604
|
+
return merged.renderScale;
|
|
1605
|
+
},
|
|
1606
|
+
get paused() {
|
|
1607
|
+
return manuallyPaused;
|
|
1608
|
+
},
|
|
1609
|
+
get static() {
|
|
1610
|
+
return staticMode;
|
|
1611
|
+
},
|
|
1612
|
+
get fps() {
|
|
1613
|
+
return frameGate.getFps();
|
|
1614
|
+
},
|
|
1379
1615
|
dirty: dirty
|
|
1380
1616
|
};
|
|
1381
1617
|
}
|