@5even7/dlc-ui 0.2.11 → 0.2.12
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 +42 -42
- package/LICENSE +21 -21
- package/README.md +255 -255
- package/dist/capsule.cjs +298 -71
- package/dist/capsule.mjs +828 -604
- package/dist/color.cjs +329 -82
- package/dist/color.mjs +879 -631
- package/dist/index.cjs +979 -252
- package/dist/index.mjs +2695 -1979
- package/dist/index.umd.js +979 -252
- package/dist/index.umd.min.js +1 -1
- package/dist/progress.cjs +614 -171
- package/dist/progress.mjs +1815 -1379
- package/dist/vue2.cjs +1123 -265
- package/dist/vue2.mjs +2884 -2059
- package/dist/vue3.cjs +1123 -265
- package/dist/vue3.mjs +2884 -2059
- 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',
|
|
@@ -430,6 +436,11 @@ var DEFAULTS = {
|
|
|
430
436
|
height: 160,
|
|
431
437
|
quality: 'auto',
|
|
432
438
|
renderer: 'auto',
|
|
439
|
+
renderScale: 1,
|
|
440
|
+
powerPreference: 'high-performance',
|
|
441
|
+
fps: 60,
|
|
442
|
+
paused: false,
|
|
443
|
+
static: false,
|
|
433
444
|
respectReducedMotion: true,
|
|
434
445
|
mouseColor: true,
|
|
435
446
|
textRatio: 39
|
|
@@ -700,7 +711,7 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
700
711
|
alpha: false,
|
|
701
712
|
antialias: false,
|
|
702
713
|
depth: false,
|
|
703
|
-
powerPreference: 'high-performance',
|
|
714
|
+
powerPreference: this.options.powerPreference || 'high-performance',
|
|
704
715
|
preserveDrawingBuffer: false
|
|
705
716
|
});
|
|
706
717
|
if (!this.gl) throw new Error('WebGL2 is not available');
|
|
@@ -711,16 +722,19 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
711
722
|
this.motion = 0;
|
|
712
723
|
this.motionTarget = 0;
|
|
713
724
|
this.timeOffset = preset.seed * 0.73;
|
|
725
|
+
this.colors = preset.colors.map(hexToRgb01);
|
|
714
726
|
this.visible = true;
|
|
715
727
|
this.disposed = false;
|
|
716
728
|
_assertClassBrand(_CosmicRenderer_brand, this, _setupGeometry).call(this);
|
|
717
729
|
_assertClassBrand(_CosmicRenderer_brand, this, _bindEvents).call(this);
|
|
730
|
+
_assertClassBrand(_CosmicRenderer_brand, this, _bindContextEvents).call(this);
|
|
718
731
|
this.resize();
|
|
719
732
|
}
|
|
720
733
|
return _createClass(CosmicRenderer, [{
|
|
721
734
|
key: "setPreset",
|
|
722
735
|
value: function setPreset(preset) {
|
|
723
736
|
this.preset = _objectSpread2({}, preset);
|
|
737
|
+
this.colors = preset.colors.map(hexToRgb01);
|
|
724
738
|
this.timeOffset = preset.seed * 0.73;
|
|
725
739
|
}
|
|
726
740
|
}, {
|
|
@@ -765,15 +779,14 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
765
779
|
if (this.canvas.width !== width || this.canvas.height !== height) {
|
|
766
780
|
this.canvas.width = width;
|
|
767
781
|
this.canvas.height = height;
|
|
768
|
-
this.gl.viewport(0, 0, width, height);
|
|
769
782
|
}
|
|
783
|
+
this.gl.viewport(0, 0, width, height);
|
|
770
784
|
}
|
|
771
785
|
}, {
|
|
772
786
|
key: "draw",
|
|
773
787
|
value: function draw(elapsedSeconds) {
|
|
774
788
|
var paused = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
775
789
|
if (this.disposed || !this.visible) return;
|
|
776
|
-
this.resize();
|
|
777
790
|
var gl = this.gl;
|
|
778
791
|
this.pointer[0] += (this.pointerTarget[0] - this.pointer[0]) * 0.08;
|
|
779
792
|
this.pointer[1] += (this.pointerTarget[1] - this.pointer[1]) * 0.08;
|
|
@@ -782,16 +795,15 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
782
795
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
|
|
783
796
|
gl.enableVertexAttribArray(this.locations.position);
|
|
784
797
|
gl.vertexAttribPointer(this.locations.position, 2, gl.FLOAT, false, 0, 0);
|
|
785
|
-
var colors = this.preset.colors.map(hexToRgb01);
|
|
786
798
|
gl.uniform2f(this.locations.resolution, this.canvas.width, this.canvas.height);
|
|
787
799
|
gl.uniform1f(this.locations.time, this.timeOffset + (paused ? 0 : elapsedSeconds * this.preset.speed));
|
|
788
800
|
gl.uniform1f(this.locations.seed, this.preset.seed);
|
|
789
801
|
gl.uniform1f(this.locations.motion, this.motion);
|
|
790
802
|
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]);
|
|
803
|
+
gl.uniform3fv(this.locations.colorA, this.colors[0]);
|
|
804
|
+
gl.uniform3fv(this.locations.colorB, this.colors[1]);
|
|
805
|
+
gl.uniform3fv(this.locations.colorC, this.colors[2]);
|
|
806
|
+
gl.uniform3fv(this.locations.colorD, this.colors[3]);
|
|
795
807
|
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
796
808
|
}
|
|
797
809
|
}, {
|
|
@@ -802,6 +814,8 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
802
814
|
target.removeEventListener('pointermove', this.onPointerMove);
|
|
803
815
|
target.removeEventListener('pointerdown', this.onPointerMove);
|
|
804
816
|
target.removeEventListener('pointerleave', this.onPointerLeave);
|
|
817
|
+
this.canvas.removeEventListener('webglcontextlost', this.onContextLost, false);
|
|
818
|
+
this.canvas.removeEventListener('webglcontextrestored', this.onContextRestored, false);
|
|
805
819
|
this.gl.deleteBuffer(this.buffer);
|
|
806
820
|
this.gl.deleteProgram(this.program);
|
|
807
821
|
var lose = this.gl.getExtension('WEBGL_lose_context');
|
|
@@ -858,6 +872,26 @@ function _bindEvents() {
|
|
|
858
872
|
passive: true
|
|
859
873
|
});
|
|
860
874
|
}
|
|
875
|
+
function _bindContextEvents() {
|
|
876
|
+
var _this3 = this;
|
|
877
|
+
this.onContextLost = function (event) {
|
|
878
|
+
event.preventDefault();
|
|
879
|
+
if (_this3.disposed) return;
|
|
880
|
+
_this3.visible = false;
|
|
881
|
+
if (typeof _this3.options.onContextLost === 'function') _this3.options.onContextLost(event);
|
|
882
|
+
};
|
|
883
|
+
this.onContextRestored = function () {
|
|
884
|
+
if (_this3.disposed) return;
|
|
885
|
+
_this3.program = createProgram(_this3.gl);
|
|
886
|
+
_this3.locations = _assertClassBrand(_CosmicRenderer_brand, _this3, _getLocations).call(_this3);
|
|
887
|
+
_assertClassBrand(_CosmicRenderer_brand, _this3, _setupGeometry).call(_this3);
|
|
888
|
+
_this3.visible = true;
|
|
889
|
+
_this3.resize();
|
|
890
|
+
if (typeof _this3.options.onContextRestored === 'function') _this3.options.onContextRestored();
|
|
891
|
+
};
|
|
892
|
+
this.canvas.addEventListener('webglcontextlost', this.onContextLost, false);
|
|
893
|
+
this.canvas.addEventListener('webglcontextrestored', this.onContextRestored, false);
|
|
894
|
+
}
|
|
861
895
|
|
|
862
896
|
function rgb(color) {
|
|
863
897
|
var alpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
@@ -872,18 +906,20 @@ function rgb(color) {
|
|
|
872
906
|
}
|
|
873
907
|
var FallbackRenderer = /*#__PURE__*/function () {
|
|
874
908
|
function FallbackRenderer(canvas, preset) {
|
|
909
|
+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
875
910
|
_classCallCheck(this, FallbackRenderer);
|
|
876
911
|
this.canvas = canvas;
|
|
877
912
|
this.preset = preset;
|
|
878
913
|
this.context = canvas.getContext('2d');
|
|
879
914
|
this.visible = true;
|
|
880
915
|
this.timePhase = 0;
|
|
916
|
+
this.dprCap = options.dprCap || 1.5;
|
|
881
917
|
}
|
|
882
918
|
return _createClass(FallbackRenderer, [{
|
|
883
919
|
key: "resize",
|
|
884
920
|
value: function resize() {
|
|
885
921
|
var rect = this.canvas.getBoundingClientRect();
|
|
886
|
-
var dpr = Math.min(window.devicePixelRatio || 1,
|
|
922
|
+
var dpr = Math.min(window.devicePixelRatio || 1, this.dprCap);
|
|
887
923
|
var width = Math.max(2, Math.round(rect.width * dpr));
|
|
888
924
|
var height = Math.max(2, Math.round(rect.height * dpr));
|
|
889
925
|
if (this.canvas.width !== width || this.canvas.height !== height) {
|
|
@@ -924,7 +960,6 @@ var FallbackRenderer = /*#__PURE__*/function () {
|
|
|
924
960
|
key: "draw",
|
|
925
961
|
value: function draw(time) {
|
|
926
962
|
if (!this.visible) return;
|
|
927
|
-
this.resize();
|
|
928
963
|
this.drawNebula(time);
|
|
929
964
|
}
|
|
930
965
|
}, {
|
|
@@ -932,6 +967,12 @@ var FallbackRenderer = /*#__PURE__*/function () {
|
|
|
932
967
|
value: function setPreset(preset) {
|
|
933
968
|
this.preset = preset;
|
|
934
969
|
}
|
|
970
|
+
}, {
|
|
971
|
+
key: "setDprCap",
|
|
972
|
+
value: function setDprCap(cap) {
|
|
973
|
+
this.dprCap = cap;
|
|
974
|
+
this.resize();
|
|
975
|
+
}
|
|
935
976
|
}, {
|
|
936
977
|
key: "randomize",
|
|
937
978
|
value: function randomize() {
|
|
@@ -949,10 +990,10 @@ var FallbackRenderer = /*#__PURE__*/function () {
|
|
|
949
990
|
}]);
|
|
950
991
|
}();
|
|
951
992
|
|
|
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.
|
|
993
|
+
/**
|
|
994
|
+
* Document-level shared rAF scheduler. Every component instance subscribes
|
|
995
|
+
* its own frame callback; the whole page runs ONE animation loop (like the
|
|
996
|
+
* original demo), which avoids jank from many competing rAF loops.
|
|
956
997
|
*/
|
|
957
998
|
var subscribers = [];
|
|
958
999
|
var running = false;
|
|
@@ -960,11 +1001,7 @@ var rafId = 0;
|
|
|
960
1001
|
var last = 0;
|
|
961
1002
|
function tick(now) {
|
|
962
1003
|
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);
|
|
1004
|
+
var activeItems = [];
|
|
968
1005
|
{
|
|
969
1006
|
var _iterator = _createForOfIteratorHelper(subscribers.slice()),
|
|
970
1007
|
_step;
|
|
@@ -972,10 +1009,8 @@ function tick(now) {
|
|
|
972
1009
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
973
1010
|
var item = _step.value;
|
|
974
1011
|
try {
|
|
975
|
-
if (!item.isPaused())
|
|
976
|
-
} catch (
|
|
977
|
-
console.warn('[dlc-ui] frame error:', error);
|
|
978
|
-
}
|
|
1012
|
+
if (!item.isPaused()) activeItems.push(item);
|
|
1013
|
+
} catch (_unused) {}
|
|
979
1014
|
}
|
|
980
1015
|
} catch (err) {
|
|
981
1016
|
_iterator.e(err);
|
|
@@ -983,6 +1018,25 @@ function tick(now) {
|
|
|
983
1018
|
_iterator.f();
|
|
984
1019
|
}
|
|
985
1020
|
}
|
|
1021
|
+
if (activeItems.length === 0) {
|
|
1022
|
+
running = false;
|
|
1023
|
+
rafId = 0;
|
|
1024
|
+
last = 0;
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
var delta = last ? Math.min((now - last) / 1000, 0.05) : 0;
|
|
1028
|
+
last = now;
|
|
1029
|
+
// Schedule the next frame BEFORE running callbacks so one throwing
|
|
1030
|
+
// subscriber can never kill the whole animation loop.
|
|
1031
|
+
rafId = requestAnimationFrame(tick);
|
|
1032
|
+
for (var _i = 0, _activeItems = activeItems; _i < _activeItems.length; _i++) {
|
|
1033
|
+
var _item = _activeItems[_i];
|
|
1034
|
+
try {
|
|
1035
|
+
_item.onFrame(delta, now);
|
|
1036
|
+
} catch (error) {
|
|
1037
|
+
console.warn('[dlc-ui] frame error:', error);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
986
1040
|
if (subscribers.length === 0) {
|
|
987
1041
|
cancelAnimationFrame(rafId);
|
|
988
1042
|
running = false;
|
|
@@ -995,6 +1049,9 @@ function start() {
|
|
|
995
1049
|
last = 0;
|
|
996
1050
|
rafId = requestAnimationFrame(tick);
|
|
997
1051
|
}
|
|
1052
|
+
function wakeScheduler() {
|
|
1053
|
+
start();
|
|
1054
|
+
}
|
|
998
1055
|
function subscribeScheduler(onFrame, isPaused) {
|
|
999
1056
|
var item = {
|
|
1000
1057
|
onFrame: onFrame,
|
|
@@ -1013,11 +1070,12 @@ function subscribeScheduler(onFrame, isPaused) {
|
|
|
1013
1070
|
};
|
|
1014
1071
|
}
|
|
1015
1072
|
|
|
1016
|
-
/**
|
|
1017
|
-
* Gates drawing on "element intersects viewport AND the page tab is visible".
|
|
1018
|
-
* Falls back to always-visible when IntersectionObserver is unavailable.
|
|
1073
|
+
/**
|
|
1074
|
+
* Gates drawing on "element intersects viewport AND the page tab is visible".
|
|
1075
|
+
* Falls back to always-visible when IntersectionObserver is unavailable.
|
|
1019
1076
|
*/
|
|
1020
1077
|
function createVisibilityGuard(element) {
|
|
1078
|
+
var onChange = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
1021
1079
|
var intersecting = true;
|
|
1022
1080
|
var pageVisible = typeof document === 'undefined' || !document.hidden;
|
|
1023
1081
|
var disposed = false;
|
|
@@ -1027,6 +1085,7 @@ function createVisibilityGuard(element) {
|
|
|
1027
1085
|
intersecting = entries.some(function (entry) {
|
|
1028
1086
|
return entry.isIntersecting;
|
|
1029
1087
|
});
|
|
1088
|
+
if (typeof onChange === 'function') onChange();
|
|
1030
1089
|
}, {
|
|
1031
1090
|
rootMargin: '180px'
|
|
1032
1091
|
});
|
|
@@ -1034,6 +1093,7 @@ function createVisibilityGuard(element) {
|
|
|
1034
1093
|
}
|
|
1035
1094
|
var onVisibilityChange = function onVisibilityChange() {
|
|
1036
1095
|
pageVisible = typeof document !== 'undefined' && !document.hidden;
|
|
1096
|
+
if (typeof onChange === 'function') onChange();
|
|
1037
1097
|
};
|
|
1038
1098
|
if (typeof document !== 'undefined') {
|
|
1039
1099
|
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
@@ -1069,18 +1129,69 @@ function nextTick(fn) {
|
|
|
1069
1129
|
}
|
|
1070
1130
|
}
|
|
1071
1131
|
|
|
1072
|
-
function
|
|
1073
|
-
|
|
1132
|
+
function normalizeFps(value) {
|
|
1133
|
+
var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 60;
|
|
1134
|
+
var fps = Number(value);
|
|
1135
|
+
if (!Number.isFinite(fps)) return fallback;
|
|
1136
|
+
return Math.min(60, Math.max(1, fps));
|
|
1137
|
+
}
|
|
1138
|
+
function createFrameGate() {
|
|
1139
|
+
var initialFps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 60;
|
|
1140
|
+
var fps = normalizeFps(initialFps);
|
|
1141
|
+
var elapsed = 0;
|
|
1142
|
+
return {
|
|
1143
|
+
shouldDraw: function shouldDraw(delta) {
|
|
1144
|
+
elapsed += delta;
|
|
1145
|
+
var interval = 1 / fps;
|
|
1146
|
+
if (elapsed + 0.0001 < interval) return false;
|
|
1147
|
+
elapsed %= interval;
|
|
1148
|
+
return true;
|
|
1149
|
+
},
|
|
1150
|
+
setFps: function setFps(value) {
|
|
1151
|
+
fps = normalizeFps(value, fps);
|
|
1152
|
+
elapsed = 0;
|
|
1153
|
+
return fps;
|
|
1154
|
+
},
|
|
1155
|
+
getFps: function getFps() {
|
|
1156
|
+
return fps;
|
|
1157
|
+
}
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
function createReducedMotionPreference(enabled, onChange) {
|
|
1161
|
+
var query = enabled && typeof matchMedia !== 'undefined' ? matchMedia('(prefers-reduced-motion: reduce)') : null;
|
|
1162
|
+
var notify = function notify() {
|
|
1163
|
+
if (typeof onChange === 'function') onChange(Boolean(query && query.matches));
|
|
1164
|
+
};
|
|
1165
|
+
if (query) {
|
|
1166
|
+
if (typeof query.addEventListener === 'function') query.addEventListener('change', notify);else if (typeof query.addListener === 'function') query.addListener(notify);
|
|
1167
|
+
}
|
|
1168
|
+
return {
|
|
1169
|
+
matches: function matches() {
|
|
1170
|
+
return Boolean(query && query.matches);
|
|
1171
|
+
},
|
|
1172
|
+
dispose: function dispose() {
|
|
1173
|
+
if (!query) return;
|
|
1174
|
+
if (typeof query.removeEventListener === 'function') query.removeEventListener('change', notify);else if (typeof query.removeListener === 'function') query.removeListener(notify);
|
|
1175
|
+
}
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
function toFiniteNumber(value) {
|
|
1180
|
+
if (value == null || typeof value === 'boolean') return null;
|
|
1181
|
+
if (typeof value === 'string' && value.trim() === '') return null;
|
|
1182
|
+
var number = Number(value);
|
|
1183
|
+
return Number.isFinite(number) ? number : null;
|
|
1074
1184
|
}
|
|
1075
1185
|
|
|
1076
|
-
/**
|
|
1186
|
+
/**
|
|
1077
1187
|
* Mount a cosmic (nebula) capsule into `container`.
|
|
1078
1188
|
*
|
|
1079
1189
|
* Options: preset (literary name), width, height (number=px or string with
|
|
1080
1190
|
* px/%/vw/vh/em/rem), colors, seed, speed, textRatio (0-100, text region
|
|
1081
1191
|
* width in percent), text (HTML string or DOM nodes for the text slot),
|
|
1082
1192
|
* colorContent (HTML string or DOM nodes for the color slot), quality,
|
|
1083
|
-
* renderer,
|
|
1193
|
+
* renderer, quality, renderScale, powerPreference, fps, paused/static,
|
|
1194
|
+
* respectReducedMotion, mouseColor, cssVars.
|
|
1084
1195
|
*/
|
|
1085
1196
|
function createCapsule(container) {
|
|
1086
1197
|
var _options$preset;
|
|
@@ -1090,10 +1201,19 @@ function createCapsule(container) {
|
|
|
1090
1201
|
}
|
|
1091
1202
|
var preset = _objectSpread2({}, getPreset('capsule', (_options$preset = options.preset) !== null && _options$preset !== void 0 ? _options$preset : '初光'));
|
|
1092
1203
|
var merged = normalizeOptions(DEFAULTS.capsule, preset, options);
|
|
1093
|
-
var normalizedColors = merged.colors.map(normalizeColor);
|
|
1094
|
-
if (normalizedColors.every(Boolean)) preset.colors = normalizedColors;
|
|
1095
|
-
|
|
1096
|
-
|
|
1204
|
+
var normalizedColors = Array.isArray(merged.colors) ? merged.colors.map(normalizeColor) : [];
|
|
1205
|
+
if (normalizedColors.length === 4 && normalizedColors.every(Boolean)) preset.colors = normalizedColors;
|
|
1206
|
+
var initialSeed = toFiniteNumber(merged.seed);
|
|
1207
|
+
var initialSpeed = toFiniteNumber(merged.speed);
|
|
1208
|
+
if (initialSeed !== null) preset.seed = initialSeed;
|
|
1209
|
+
if (initialSpeed !== null) preset.speed = initialSpeed;
|
|
1210
|
+
merged.colors = _toConsumableArray(preset.colors);
|
|
1211
|
+
merged.seed = preset.seed;
|
|
1212
|
+
merged.speed = preset.speed;
|
|
1213
|
+
var optionColors = Array.isArray(options.colors) ? options.colors.map(normalizeColor) : [];
|
|
1214
|
+
var colorOverride = optionColors.length === 4 && optionColors.every(Boolean) ? _toConsumableArray(optionColors) : null;
|
|
1215
|
+
var seedOverride = options.seed !== undefined ? toFiniteNumber(options.seed) : null;
|
|
1216
|
+
var speedOverride = options.speed !== undefined ? toFiniteNumber(options.speed) : null;
|
|
1097
1217
|
var customLabel = typeof options.label === 'string' && options.label ? options.label : null;
|
|
1098
1218
|
var root = document.createElement('div');
|
|
1099
1219
|
root.className = 'hj-capsule-root hj-capsule-cosmic';
|
|
@@ -1145,25 +1265,49 @@ function createCapsule(container) {
|
|
|
1145
1265
|
root.appendChild(canvas);
|
|
1146
1266
|
container.appendChild(root);
|
|
1147
1267
|
var emitter = createEmitter();
|
|
1148
|
-
var
|
|
1268
|
+
var manuallyPaused = merged.paused === true;
|
|
1269
|
+
var reducedPaused = false;
|
|
1270
|
+
var staticMode = merged.static === true;
|
|
1271
|
+
var contextLost = false;
|
|
1149
1272
|
var disposed = false;
|
|
1273
|
+
var renderOnce = function renderOnce() {};
|
|
1150
1274
|
var dirty = {
|
|
1151
1275
|
preset: false,
|
|
1152
1276
|
seed: false,
|
|
1153
1277
|
speed: false,
|
|
1154
1278
|
colors: false,
|
|
1155
1279
|
textRatio: false,
|
|
1156
|
-
cssVars: false
|
|
1280
|
+
cssVars: false,
|
|
1281
|
+
mouseColor: false,
|
|
1282
|
+
quality: false,
|
|
1283
|
+
renderScale: false,
|
|
1284
|
+
paused: false,
|
|
1285
|
+
static: false,
|
|
1286
|
+
fps: false
|
|
1157
1287
|
};
|
|
1158
1288
|
var renderer;
|
|
1159
1289
|
var useWebgl = merged.renderer !== 'canvas2d';
|
|
1160
1290
|
if (useWebgl) {
|
|
1161
1291
|
try {
|
|
1162
1292
|
renderer = new CosmicRenderer(canvas, merged, {
|
|
1163
|
-
dprCap:
|
|
1293
|
+
dprCap: effectiveDprCap(merged.quality, merged.renderScale),
|
|
1294
|
+
mouseColor: merged.mouseColor !== false,
|
|
1295
|
+
powerPreference: merged.powerPreference,
|
|
1296
|
+
onContextLost: function onContextLost() {
|
|
1297
|
+
contextLost = true;
|
|
1298
|
+
emitter.emit('contextlost', {});
|
|
1299
|
+
},
|
|
1300
|
+
onContextRestored: function onContextRestored() {
|
|
1301
|
+
contextLost = false;
|
|
1302
|
+
emitter.emit('contextrestored', {});
|
|
1303
|
+
renderOnce();
|
|
1304
|
+
wakeScheduler();
|
|
1305
|
+
}
|
|
1164
1306
|
});
|
|
1165
1307
|
} catch (error) {
|
|
1166
|
-
renderer = new FallbackRenderer(canvas, merged
|
|
1308
|
+
renderer = new FallbackRenderer(canvas, merged, {
|
|
1309
|
+
dprCap: effectiveDprCap(merged.quality, merged.renderScale)
|
|
1310
|
+
});
|
|
1167
1311
|
nextTick(function () {
|
|
1168
1312
|
if (disposed) return;
|
|
1169
1313
|
emitter.emit('error', {
|
|
@@ -1172,8 +1316,15 @@ function createCapsule(container) {
|
|
|
1172
1316
|
});
|
|
1173
1317
|
}
|
|
1174
1318
|
} else {
|
|
1175
|
-
renderer = new FallbackRenderer(canvas, merged
|
|
1319
|
+
renderer = new FallbackRenderer(canvas, merged, {
|
|
1320
|
+
dprCap: effectiveDprCap(merged.quality, merged.renderScale)
|
|
1321
|
+
});
|
|
1176
1322
|
}
|
|
1323
|
+
var animationTime = 0;
|
|
1324
|
+
var frameGate = createFrameGate(merged.fps);
|
|
1325
|
+
renderOnce = function renderOnce() {
|
|
1326
|
+
return renderer.draw(animationTime);
|
|
1327
|
+
};
|
|
1177
1328
|
var applySize = function applySize() {
|
|
1178
1329
|
root.style.width = parseSize(merged.width);
|
|
1179
1330
|
root.style.height = parseSize(merged.height);
|
|
@@ -1191,11 +1342,21 @@ function createCapsule(container) {
|
|
|
1191
1342
|
renderer.resize();
|
|
1192
1343
|
};
|
|
1193
1344
|
applySize();
|
|
1194
|
-
var
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
var
|
|
1345
|
+
var resize = function resize() {
|
|
1346
|
+
renderer.resize();
|
|
1347
|
+
if (manuallyPaused || reducedPaused || staticMode) renderOnce();
|
|
1348
|
+
};
|
|
1349
|
+
var resizeObserver = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(resize) : null;
|
|
1350
|
+
if (resizeObserver) resizeObserver.observe(root);else window.addEventListener('resize', resize);
|
|
1351
|
+
var visibility = createVisibilityGuard(root, wakeScheduler);
|
|
1352
|
+
var motionPreference = createReducedMotionPreference(merged.respectReducedMotion, function (matches) {
|
|
1353
|
+
reducedPaused = matches;
|
|
1354
|
+
if (matches) renderOnce();else wakeScheduler();
|
|
1355
|
+
});
|
|
1356
|
+
reducedPaused = motionPreference.matches();
|
|
1357
|
+
var isMotionPaused = function isMotionPaused() {
|
|
1358
|
+
return manuallyPaused || reducedPaused || staticMode || contextLost;
|
|
1359
|
+
};
|
|
1199
1360
|
root.addEventListener('pointerenter', function () {
|
|
1200
1361
|
return emitter.emit('pointerenter', {
|
|
1201
1362
|
preset: _objectSpread2({}, preset)
|
|
@@ -1230,12 +1391,12 @@ function createCapsule(container) {
|
|
|
1230
1391
|
preset: _objectSpread2({}, preset)
|
|
1231
1392
|
});
|
|
1232
1393
|
});
|
|
1233
|
-
|
|
1394
|
+
renderOnce();
|
|
1234
1395
|
var unsubscribe = subscribeScheduler(function (delta) {
|
|
1235
1396
|
animationTime += delta;
|
|
1236
|
-
if (
|
|
1397
|
+
if (frameGate.shouldDraw(delta)) renderer.draw(animationTime);
|
|
1237
1398
|
}, function () {
|
|
1238
|
-
return
|
|
1399
|
+
return isMotionPaused() || !visibility.isVisible();
|
|
1239
1400
|
});
|
|
1240
1401
|
nextTick(function () {
|
|
1241
1402
|
if (disposed) return;
|
|
@@ -1258,11 +1419,15 @@ function createCapsule(container) {
|
|
|
1258
1419
|
var next = getPreset('capsule', ref);
|
|
1259
1420
|
dirty.preset = true;
|
|
1260
1421
|
Object.assign(preset, next);
|
|
1422
|
+
if (colorOverride) preset.colors = _toConsumableArray(colorOverride);
|
|
1423
|
+
if (seedOverride !== null) preset.seed = seedOverride;
|
|
1424
|
+
if (speedOverride !== null) preset.speed = speedOverride;
|
|
1261
1425
|
var nextColors = preset.colors.map(normalizeColor);
|
|
1262
1426
|
if (nextColors.every(Boolean)) preset.colors = nextColors;
|
|
1263
1427
|
renderer.setPreset(_objectSpread2({}, preset));
|
|
1264
1428
|
syncTheme();
|
|
1265
1429
|
renderer.resize();
|
|
1430
|
+
if (isMotionPaused()) renderOnce();
|
|
1266
1431
|
emitter.emit('presetchange', {
|
|
1267
1432
|
preset: _objectSpread2({}, next)
|
|
1268
1433
|
});
|
|
@@ -1274,26 +1439,32 @@ function createCapsule(container) {
|
|
|
1274
1439
|
return !color;
|
|
1275
1440
|
})) return this;
|
|
1276
1441
|
dirty.colors = true;
|
|
1442
|
+
colorOverride = _toConsumableArray(next);
|
|
1277
1443
|
preset.colors = next;
|
|
1278
1444
|
renderer.setPreset(_objectSpread2(_objectSpread2({}, preset), {}, {
|
|
1279
1445
|
colors: next
|
|
1280
1446
|
}));
|
|
1447
|
+
if (isMotionPaused()) renderOnce();
|
|
1281
1448
|
return this;
|
|
1282
1449
|
},
|
|
1283
1450
|
setSeed: function setSeed(seed) {
|
|
1284
|
-
var value =
|
|
1285
|
-
if (
|
|
1451
|
+
var value = toFiniteNumber(seed);
|
|
1452
|
+
if (value === null) return this;
|
|
1286
1453
|
dirty.seed = true;
|
|
1454
|
+
seedOverride = value;
|
|
1287
1455
|
preset.seed = value;
|
|
1288
1456
|
renderer.setPreset(_objectSpread2({}, preset));
|
|
1457
|
+
if (isMotionPaused()) renderOnce();
|
|
1289
1458
|
return this;
|
|
1290
1459
|
},
|
|
1291
1460
|
setSpeed: function setSpeed(speed) {
|
|
1292
|
-
var value =
|
|
1293
|
-
if (
|
|
1461
|
+
var value = toFiniteNumber(speed);
|
|
1462
|
+
if (value === null) return this;
|
|
1294
1463
|
dirty.speed = true;
|
|
1464
|
+
speedOverride = value;
|
|
1295
1465
|
preset.speed = value;
|
|
1296
1466
|
renderer.setPreset(_objectSpread2({}, preset));
|
|
1467
|
+
if (isMotionPaused()) renderOnce();
|
|
1297
1468
|
return this;
|
|
1298
1469
|
},
|
|
1299
1470
|
setText: function setText(content) {
|
|
@@ -1329,6 +1500,7 @@ function createCapsule(container) {
|
|
|
1329
1500
|
return this;
|
|
1330
1501
|
},
|
|
1331
1502
|
setMouseColor: function setMouseColor(value) {
|
|
1503
|
+
dirty.mouseColor = true;
|
|
1332
1504
|
merged.mouseColor = value !== false;
|
|
1333
1505
|
if (typeof renderer.setMouseColor === 'function') renderer.setMouseColor(merged.mouseColor);
|
|
1334
1506
|
return this;
|
|
@@ -1343,6 +1515,7 @@ function createCapsule(container) {
|
|
|
1343
1515
|
merged.height = height;
|
|
1344
1516
|
}
|
|
1345
1517
|
applySize();
|
|
1518
|
+
if (isMotionPaused()) renderOnce();
|
|
1346
1519
|
return this;
|
|
1347
1520
|
},
|
|
1348
1521
|
randomize: function randomize() {
|
|
@@ -1350,23 +1523,59 @@ function createCapsule(container) {
|
|
|
1350
1523
|
return this;
|
|
1351
1524
|
},
|
|
1352
1525
|
pause: function pause() {
|
|
1353
|
-
paused = true;
|
|
1526
|
+
dirty.paused = true;
|
|
1527
|
+
manuallyPaused = true;
|
|
1528
|
+
renderOnce();
|
|
1354
1529
|
return this;
|
|
1355
1530
|
},
|
|
1356
1531
|
resume: function resume() {
|
|
1357
|
-
paused =
|
|
1532
|
+
dirty.paused = true;
|
|
1533
|
+
manuallyPaused = false;
|
|
1534
|
+
wakeScheduler();
|
|
1535
|
+
return this;
|
|
1536
|
+
},
|
|
1537
|
+
setPaused: function setPaused(value) {
|
|
1538
|
+
return value ? this.pause() : this.resume();
|
|
1539
|
+
},
|
|
1540
|
+
setStatic: function setStatic(value) {
|
|
1541
|
+
dirty.static = true;
|
|
1542
|
+
staticMode = value === true;
|
|
1543
|
+
merged.static = staticMode;
|
|
1544
|
+
if (staticMode) renderOnce();else wakeScheduler();
|
|
1545
|
+
return this;
|
|
1546
|
+
},
|
|
1547
|
+
setFps: function setFps(fps) {
|
|
1548
|
+
dirty.fps = true;
|
|
1549
|
+
merged.fps = frameGate.setFps(fps);
|
|
1550
|
+
wakeScheduler();
|
|
1358
1551
|
return this;
|
|
1359
1552
|
},
|
|
1360
1553
|
setQuality: function setQuality(quality) {
|
|
1554
|
+
dirty.quality = true;
|
|
1361
1555
|
merged.quality = quality;
|
|
1362
|
-
if (typeof renderer.setDprCap === 'function')
|
|
1556
|
+
if (typeof renderer.setDprCap === 'function') {
|
|
1557
|
+
renderer.setDprCap(effectiveDprCap(quality, merged.renderScale));
|
|
1558
|
+
}
|
|
1559
|
+
if (isMotionPaused()) renderOnce();
|
|
1560
|
+
return this;
|
|
1561
|
+
},
|
|
1562
|
+
setRenderScale: function setRenderScale(renderScale) {
|
|
1563
|
+
var value = Number(renderScale);
|
|
1564
|
+
if (!Number.isFinite(value)) return this;
|
|
1565
|
+
dirty.renderScale = true;
|
|
1566
|
+
merged.renderScale = Math.min(1, Math.max(0.25, value));
|
|
1567
|
+
if (typeof renderer.setDprCap === 'function') {
|
|
1568
|
+
renderer.setDprCap(effectiveDprCap(merged.quality, merged.renderScale));
|
|
1569
|
+
}
|
|
1570
|
+
if (isMotionPaused()) renderOnce();
|
|
1363
1571
|
return this;
|
|
1364
1572
|
},
|
|
1365
1573
|
dispose: function dispose() {
|
|
1366
1574
|
disposed = true;
|
|
1367
1575
|
unsubscribe();
|
|
1368
1576
|
visibility.dispose();
|
|
1369
|
-
|
|
1577
|
+
motionPreference.dispose();
|
|
1578
|
+
if (resizeObserver) resizeObserver.disconnect();else window.removeEventListener('resize', resize);
|
|
1370
1579
|
renderer.dispose();
|
|
1371
1580
|
root.remove();
|
|
1372
1581
|
},
|
|
@@ -1376,6 +1585,24 @@ function createCapsule(container) {
|
|
|
1376
1585
|
get cssVars() {
|
|
1377
1586
|
return merged.cssVars;
|
|
1378
1587
|
},
|
|
1588
|
+
get mouseColor() {
|
|
1589
|
+
return merged.mouseColor;
|
|
1590
|
+
},
|
|
1591
|
+
get quality() {
|
|
1592
|
+
return merged.quality;
|
|
1593
|
+
},
|
|
1594
|
+
get renderScale() {
|
|
1595
|
+
return merged.renderScale;
|
|
1596
|
+
},
|
|
1597
|
+
get paused() {
|
|
1598
|
+
return manuallyPaused;
|
|
1599
|
+
},
|
|
1600
|
+
get static() {
|
|
1601
|
+
return staticMode;
|
|
1602
|
+
},
|
|
1603
|
+
get fps() {
|
|
1604
|
+
return frameGate.getFps();
|
|
1605
|
+
},
|
|
1379
1606
|
dirty: dirty
|
|
1380
1607
|
};
|
|
1381
1608
|
}
|