@5even7/dlc-ui 0.2.10 → 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 +50 -42
- package/LICENSE +21 -21
- package/README.md +257 -257
- package/dist/capsule.cjs +298 -71
- package/dist/capsule.mjs +828 -604
- package/dist/color.cjs +330 -83
- package/dist/color.mjs +880 -632
- package/dist/index.cjs +982 -255
- package/dist/index.mjs +2708 -1987
- package/dist/index.umd.js +982 -255
- package/dist/index.umd.min.js +1 -1
- package/dist/progress.cjs +616 -173
- package/dist/progress.mjs +1827 -1386
- package/dist/vue2.cjs +1126 -268
- package/dist/vue2.mjs +2897 -2067
- package/dist/vue3.cjs +1126 -268
- package/dist/vue3.mjs +2897 -2067
- package/package.json +122 -121
- package/styles/base.css +32 -32
- package/styles/capsule.css +2 -0
- package/styles/color.css +18 -18
- package/styles/progress.css +55 -50
- package/types/capsule.d.ts +15 -13
- package/types/color.d.ts +15 -13
- package/types/index.d.ts +216 -127
- package/types/progress.d.ts +16 -14
- package/types/vue3.d.ts +38 -22
package/dist/color.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
|
|
@@ -254,11 +254,17 @@ function dprCapFor(quality) {
|
|
|
254
254
|
var tier = QUALITY_TIERS[quality] || QUALITY_TIERS.medium;
|
|
255
255
|
return tier.dpr;
|
|
256
256
|
}
|
|
257
|
+
function effectiveDprCap(quality) {
|
|
258
|
+
var renderScale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
259
|
+
var scale = Number(renderScale);
|
|
260
|
+
var normalizedScale = Number.isFinite(scale) ? Math.min(1, Math.max(0.25, scale)) : 1;
|
|
261
|
+
return Math.max(0.5, dprCapFor(quality) * normalizedScale);
|
|
262
|
+
}
|
|
257
263
|
|
|
258
|
-
/**
|
|
259
|
-
* Merge defaults < preset < user. Unknown user keys are preserved so the
|
|
260
|
-
* component API can grow (new props, cssVars, callbacks) without a breaking
|
|
261
|
-
* change.
|
|
264
|
+
/**
|
|
265
|
+
* Merge defaults < preset < user. Unknown user keys are preserved so the
|
|
266
|
+
* component API can grow (new props, cssVars, callbacks) without a breaking
|
|
267
|
+
* change.
|
|
262
268
|
*/
|
|
263
269
|
function normalizeOptions(defaults, preset, user) {
|
|
264
270
|
// undefined means "not provided" (e.g. Vue $props with unset props):
|
|
@@ -276,9 +282,9 @@ function normalizeOptions(defaults, preset, user) {
|
|
|
276
282
|
return _objectSpread2(_objectSpread2(_objectSpread2({}, defaults), presetOptions), userOptions);
|
|
277
283
|
}
|
|
278
284
|
|
|
279
|
-
/**
|
|
280
|
-
* 公共色板:NC-01~NC-06 的四色组(底色 / 主色 / 辅色 / 高光色)。
|
|
281
|
-
* Capsule 预置与 dlc-color 等组件共用,新增色板只改这里。
|
|
285
|
+
/**
|
|
286
|
+
* 公共色板:NC-01~NC-06 的四色组(底色 / 主色 / 辅色 / 高光色)。
|
|
287
|
+
* Capsule 预置与 dlc-color 等组件共用,新增色板只改这里。
|
|
282
288
|
*/
|
|
283
289
|
var PALETTES = {
|
|
284
290
|
original: ['#FFF3EA', '#F5B27A', '#F67BC6', '#A978E8'],
|
|
@@ -289,9 +295,9 @@ var PALETTES = {
|
|
|
289
295
|
plus: ['#FFF0E6', '#F6C26B', '#F98A64', '#E86D74']
|
|
290
296
|
};
|
|
291
297
|
|
|
292
|
-
/**
|
|
293
|
-
* Capsule 预置:仅星云材质 NC-01~NC-06(NC-07~09 aurora 已移除)。
|
|
294
|
-
* 颜色引用公共色板,seed/speed 决定形态与流速。
|
|
298
|
+
/**
|
|
299
|
+
* Capsule 预置:仅星云材质 NC-01~NC-06(NC-07~09 aurora 已移除)。
|
|
300
|
+
* 颜色引用公共色板,seed/speed 决定形态与流速。
|
|
295
301
|
*/
|
|
296
302
|
var CAPSULE_PRESETS = [{
|
|
297
303
|
id: 'original',
|
|
@@ -407,6 +413,7 @@ var DEFAULTS = {
|
|
|
407
413
|
capsule: {
|
|
408
414
|
quality: 'auto',
|
|
409
415
|
renderer: 'auto',
|
|
416
|
+
fps: 60,
|
|
410
417
|
respectReducedMotion: true}};
|
|
411
418
|
|
|
412
419
|
/**
|
|
@@ -665,7 +672,7 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
665
672
|
alpha: false,
|
|
666
673
|
antialias: false,
|
|
667
674
|
depth: false,
|
|
668
|
-
powerPreference: 'high-performance',
|
|
675
|
+
powerPreference: this.options.powerPreference || 'high-performance',
|
|
669
676
|
preserveDrawingBuffer: false
|
|
670
677
|
});
|
|
671
678
|
if (!this.gl) throw new Error('WebGL2 is not available');
|
|
@@ -676,16 +683,19 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
676
683
|
this.motion = 0;
|
|
677
684
|
this.motionTarget = 0;
|
|
678
685
|
this.timeOffset = preset.seed * 0.73;
|
|
686
|
+
this.colors = preset.colors.map(hexToRgb01);
|
|
679
687
|
this.visible = true;
|
|
680
688
|
this.disposed = false;
|
|
681
689
|
_assertClassBrand(_CosmicRenderer_brand, this, _setupGeometry).call(this);
|
|
682
690
|
_assertClassBrand(_CosmicRenderer_brand, this, _bindEvents).call(this);
|
|
691
|
+
_assertClassBrand(_CosmicRenderer_brand, this, _bindContextEvents).call(this);
|
|
683
692
|
this.resize();
|
|
684
693
|
}
|
|
685
694
|
return _createClass(CosmicRenderer, [{
|
|
686
695
|
key: "setPreset",
|
|
687
696
|
value: function setPreset(preset) {
|
|
688
697
|
this.preset = _objectSpread2({}, preset);
|
|
698
|
+
this.colors = preset.colors.map(hexToRgb01);
|
|
689
699
|
this.timeOffset = preset.seed * 0.73;
|
|
690
700
|
}
|
|
691
701
|
}, {
|
|
@@ -730,15 +740,14 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
730
740
|
if (this.canvas.width !== width || this.canvas.height !== height) {
|
|
731
741
|
this.canvas.width = width;
|
|
732
742
|
this.canvas.height = height;
|
|
733
|
-
this.gl.viewport(0, 0, width, height);
|
|
734
743
|
}
|
|
744
|
+
this.gl.viewport(0, 0, width, height);
|
|
735
745
|
}
|
|
736
746
|
}, {
|
|
737
747
|
key: "draw",
|
|
738
748
|
value: function draw(elapsedSeconds) {
|
|
739
749
|
var paused = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
740
750
|
if (this.disposed || !this.visible) return;
|
|
741
|
-
this.resize();
|
|
742
751
|
var gl = this.gl;
|
|
743
752
|
this.pointer[0] += (this.pointerTarget[0] - this.pointer[0]) * 0.08;
|
|
744
753
|
this.pointer[1] += (this.pointerTarget[1] - this.pointer[1]) * 0.08;
|
|
@@ -747,16 +756,15 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
747
756
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
|
|
748
757
|
gl.enableVertexAttribArray(this.locations.position);
|
|
749
758
|
gl.vertexAttribPointer(this.locations.position, 2, gl.FLOAT, false, 0, 0);
|
|
750
|
-
var colors = this.preset.colors.map(hexToRgb01);
|
|
751
759
|
gl.uniform2f(this.locations.resolution, this.canvas.width, this.canvas.height);
|
|
752
760
|
gl.uniform1f(this.locations.time, this.timeOffset + (paused ? 0 : elapsedSeconds * this.preset.speed));
|
|
753
761
|
gl.uniform1f(this.locations.seed, this.preset.seed);
|
|
754
762
|
gl.uniform1f(this.locations.motion, this.motion);
|
|
755
763
|
gl.uniform2f(this.locations.pointer, this.pointer[0], this.pointer[1]);
|
|
756
|
-
gl.uniform3fv(this.locations.colorA, colors[0]);
|
|
757
|
-
gl.uniform3fv(this.locations.colorB, colors[1]);
|
|
758
|
-
gl.uniform3fv(this.locations.colorC, colors[2]);
|
|
759
|
-
gl.uniform3fv(this.locations.colorD, colors[3]);
|
|
764
|
+
gl.uniform3fv(this.locations.colorA, this.colors[0]);
|
|
765
|
+
gl.uniform3fv(this.locations.colorB, this.colors[1]);
|
|
766
|
+
gl.uniform3fv(this.locations.colorC, this.colors[2]);
|
|
767
|
+
gl.uniform3fv(this.locations.colorD, this.colors[3]);
|
|
760
768
|
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
761
769
|
}
|
|
762
770
|
}, {
|
|
@@ -767,6 +775,8 @@ var CosmicRenderer = /*#__PURE__*/function () {
|
|
|
767
775
|
target.removeEventListener('pointermove', this.onPointerMove);
|
|
768
776
|
target.removeEventListener('pointerdown', this.onPointerMove);
|
|
769
777
|
target.removeEventListener('pointerleave', this.onPointerLeave);
|
|
778
|
+
this.canvas.removeEventListener('webglcontextlost', this.onContextLost, false);
|
|
779
|
+
this.canvas.removeEventListener('webglcontextrestored', this.onContextRestored, false);
|
|
770
780
|
this.gl.deleteBuffer(this.buffer);
|
|
771
781
|
this.gl.deleteProgram(this.program);
|
|
772
782
|
var lose = this.gl.getExtension('WEBGL_lose_context');
|
|
@@ -823,6 +833,26 @@ function _bindEvents() {
|
|
|
823
833
|
passive: true
|
|
824
834
|
});
|
|
825
835
|
}
|
|
836
|
+
function _bindContextEvents() {
|
|
837
|
+
var _this3 = this;
|
|
838
|
+
this.onContextLost = function (event) {
|
|
839
|
+
event.preventDefault();
|
|
840
|
+
if (_this3.disposed) return;
|
|
841
|
+
_this3.visible = false;
|
|
842
|
+
if (typeof _this3.options.onContextLost === 'function') _this3.options.onContextLost(event);
|
|
843
|
+
};
|
|
844
|
+
this.onContextRestored = function () {
|
|
845
|
+
if (_this3.disposed) return;
|
|
846
|
+
_this3.program = createProgram(_this3.gl);
|
|
847
|
+
_this3.locations = _assertClassBrand(_CosmicRenderer_brand, _this3, _getLocations).call(_this3);
|
|
848
|
+
_assertClassBrand(_CosmicRenderer_brand, _this3, _setupGeometry).call(_this3);
|
|
849
|
+
_this3.visible = true;
|
|
850
|
+
_this3.resize();
|
|
851
|
+
if (typeof _this3.options.onContextRestored === 'function') _this3.options.onContextRestored();
|
|
852
|
+
};
|
|
853
|
+
this.canvas.addEventListener('webglcontextlost', this.onContextLost, false);
|
|
854
|
+
this.canvas.addEventListener('webglcontextrestored', this.onContextRestored, false);
|
|
855
|
+
}
|
|
826
856
|
|
|
827
857
|
function rgb(color) {
|
|
828
858
|
var alpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
@@ -837,18 +867,20 @@ function rgb(color) {
|
|
|
837
867
|
}
|
|
838
868
|
var FallbackRenderer = /*#__PURE__*/function () {
|
|
839
869
|
function FallbackRenderer(canvas, preset) {
|
|
870
|
+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
840
871
|
_classCallCheck(this, FallbackRenderer);
|
|
841
872
|
this.canvas = canvas;
|
|
842
873
|
this.preset = preset;
|
|
843
874
|
this.context = canvas.getContext('2d');
|
|
844
875
|
this.visible = true;
|
|
845
876
|
this.timePhase = 0;
|
|
877
|
+
this.dprCap = options.dprCap || 1.5;
|
|
846
878
|
}
|
|
847
879
|
return _createClass(FallbackRenderer, [{
|
|
848
880
|
key: "resize",
|
|
849
881
|
value: function resize() {
|
|
850
882
|
var rect = this.canvas.getBoundingClientRect();
|
|
851
|
-
var dpr = Math.min(window.devicePixelRatio || 1,
|
|
883
|
+
var dpr = Math.min(window.devicePixelRatio || 1, this.dprCap);
|
|
852
884
|
var width = Math.max(2, Math.round(rect.width * dpr));
|
|
853
885
|
var height = Math.max(2, Math.round(rect.height * dpr));
|
|
854
886
|
if (this.canvas.width !== width || this.canvas.height !== height) {
|
|
@@ -889,7 +921,6 @@ var FallbackRenderer = /*#__PURE__*/function () {
|
|
|
889
921
|
key: "draw",
|
|
890
922
|
value: function draw(time) {
|
|
891
923
|
if (!this.visible) return;
|
|
892
|
-
this.resize();
|
|
893
924
|
this.drawNebula(time);
|
|
894
925
|
}
|
|
895
926
|
}, {
|
|
@@ -897,6 +928,12 @@ var FallbackRenderer = /*#__PURE__*/function () {
|
|
|
897
928
|
value: function setPreset(preset) {
|
|
898
929
|
this.preset = preset;
|
|
899
930
|
}
|
|
931
|
+
}, {
|
|
932
|
+
key: "setDprCap",
|
|
933
|
+
value: function setDprCap(cap) {
|
|
934
|
+
this.dprCap = cap;
|
|
935
|
+
this.resize();
|
|
936
|
+
}
|
|
900
937
|
}, {
|
|
901
938
|
key: "randomize",
|
|
902
939
|
value: function randomize() {
|
|
@@ -914,10 +951,10 @@ var FallbackRenderer = /*#__PURE__*/function () {
|
|
|
914
951
|
}]);
|
|
915
952
|
}();
|
|
916
953
|
|
|
917
|
-
/**
|
|
918
|
-
* Document-level shared rAF scheduler. Every component instance subscribes
|
|
919
|
-
* its own frame callback; the whole page runs ONE animation loop (like the
|
|
920
|
-
* original demo), which avoids jank from many competing rAF loops.
|
|
954
|
+
/**
|
|
955
|
+
* Document-level shared rAF scheduler. Every component instance subscribes
|
|
956
|
+
* its own frame callback; the whole page runs ONE animation loop (like the
|
|
957
|
+
* original demo), which avoids jank from many competing rAF loops.
|
|
921
958
|
*/
|
|
922
959
|
var subscribers = [];
|
|
923
960
|
var running = false;
|
|
@@ -925,11 +962,7 @@ var rafId = 0;
|
|
|
925
962
|
var last = 0;
|
|
926
963
|
function tick(now) {
|
|
927
964
|
if (!running) return;
|
|
928
|
-
var
|
|
929
|
-
last = now;
|
|
930
|
-
// Schedule the next frame BEFORE running callbacks so one throwing
|
|
931
|
-
// subscriber can never kill the whole animation loop.
|
|
932
|
-
rafId = requestAnimationFrame(tick);
|
|
965
|
+
var activeItems = [];
|
|
933
966
|
{
|
|
934
967
|
var _iterator = _createForOfIteratorHelper(subscribers.slice()),
|
|
935
968
|
_step;
|
|
@@ -937,10 +970,8 @@ function tick(now) {
|
|
|
937
970
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
938
971
|
var item = _step.value;
|
|
939
972
|
try {
|
|
940
|
-
if (!item.isPaused())
|
|
941
|
-
} catch (
|
|
942
|
-
console.warn('[dlc-ui] frame error:', error);
|
|
943
|
-
}
|
|
973
|
+
if (!item.isPaused()) activeItems.push(item);
|
|
974
|
+
} catch (_unused) {}
|
|
944
975
|
}
|
|
945
976
|
} catch (err) {
|
|
946
977
|
_iterator.e(err);
|
|
@@ -948,6 +979,25 @@ function tick(now) {
|
|
|
948
979
|
_iterator.f();
|
|
949
980
|
}
|
|
950
981
|
}
|
|
982
|
+
if (activeItems.length === 0) {
|
|
983
|
+
running = false;
|
|
984
|
+
rafId = 0;
|
|
985
|
+
last = 0;
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
var delta = last ? Math.min((now - last) / 1000, 0.05) : 0;
|
|
989
|
+
last = now;
|
|
990
|
+
// Schedule the next frame BEFORE running callbacks so one throwing
|
|
991
|
+
// subscriber can never kill the whole animation loop.
|
|
992
|
+
rafId = requestAnimationFrame(tick);
|
|
993
|
+
for (var _i = 0, _activeItems = activeItems; _i < _activeItems.length; _i++) {
|
|
994
|
+
var _item = _activeItems[_i];
|
|
995
|
+
try {
|
|
996
|
+
_item.onFrame(delta, now);
|
|
997
|
+
} catch (error) {
|
|
998
|
+
console.warn('[dlc-ui] frame error:', error);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
951
1001
|
if (subscribers.length === 0) {
|
|
952
1002
|
cancelAnimationFrame(rafId);
|
|
953
1003
|
running = false;
|
|
@@ -960,6 +1010,9 @@ function start() {
|
|
|
960
1010
|
last = 0;
|
|
961
1011
|
rafId = requestAnimationFrame(tick);
|
|
962
1012
|
}
|
|
1013
|
+
function wakeScheduler() {
|
|
1014
|
+
start();
|
|
1015
|
+
}
|
|
963
1016
|
function subscribeScheduler(onFrame, isPaused) {
|
|
964
1017
|
var item = {
|
|
965
1018
|
onFrame: onFrame,
|
|
@@ -978,11 +1031,12 @@ function subscribeScheduler(onFrame, isPaused) {
|
|
|
978
1031
|
};
|
|
979
1032
|
}
|
|
980
1033
|
|
|
981
|
-
/**
|
|
982
|
-
* Gates drawing on "element intersects viewport AND the page tab is visible".
|
|
983
|
-
* Falls back to always-visible when IntersectionObserver is unavailable.
|
|
1034
|
+
/**
|
|
1035
|
+
* Gates drawing on "element intersects viewport AND the page tab is visible".
|
|
1036
|
+
* Falls back to always-visible when IntersectionObserver is unavailable.
|
|
984
1037
|
*/
|
|
985
1038
|
function createVisibilityGuard(element) {
|
|
1039
|
+
var onChange = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
986
1040
|
var intersecting = true;
|
|
987
1041
|
var pageVisible = typeof document === 'undefined' || !document.hidden;
|
|
988
1042
|
var disposed = false;
|
|
@@ -992,6 +1046,7 @@ function createVisibilityGuard(element) {
|
|
|
992
1046
|
intersecting = entries.some(function (entry) {
|
|
993
1047
|
return entry.isIntersecting;
|
|
994
1048
|
});
|
|
1049
|
+
if (typeof onChange === 'function') onChange();
|
|
995
1050
|
}, {
|
|
996
1051
|
rootMargin: '180px'
|
|
997
1052
|
});
|
|
@@ -999,6 +1054,7 @@ function createVisibilityGuard(element) {
|
|
|
999
1054
|
}
|
|
1000
1055
|
var onVisibilityChange = function onVisibilityChange() {
|
|
1001
1056
|
pageVisible = typeof document !== 'undefined' && !document.hidden;
|
|
1057
|
+
if (typeof onChange === 'function') onChange();
|
|
1002
1058
|
};
|
|
1003
1059
|
if (typeof document !== 'undefined') {
|
|
1004
1060
|
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
@@ -1034,22 +1090,100 @@ function nextTick(fn) {
|
|
|
1034
1090
|
}
|
|
1035
1091
|
}
|
|
1036
1092
|
|
|
1037
|
-
function
|
|
1038
|
-
|
|
1093
|
+
function normalizeFps(value) {
|
|
1094
|
+
var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 60;
|
|
1095
|
+
var fps = Number(value);
|
|
1096
|
+
if (!Number.isFinite(fps)) return fallback;
|
|
1097
|
+
return Math.min(60, Math.max(1, fps));
|
|
1098
|
+
}
|
|
1099
|
+
function createFrameGate() {
|
|
1100
|
+
var initialFps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 60;
|
|
1101
|
+
var fps = normalizeFps(initialFps);
|
|
1102
|
+
var elapsed = 0;
|
|
1103
|
+
return {
|
|
1104
|
+
shouldDraw: function shouldDraw(delta) {
|
|
1105
|
+
elapsed += delta;
|
|
1106
|
+
var interval = 1 / fps;
|
|
1107
|
+
if (elapsed + 0.0001 < interval) return false;
|
|
1108
|
+
elapsed %= interval;
|
|
1109
|
+
return true;
|
|
1110
|
+
},
|
|
1111
|
+
setFps: function setFps(value) {
|
|
1112
|
+
fps = normalizeFps(value, fps);
|
|
1113
|
+
elapsed = 0;
|
|
1114
|
+
return fps;
|
|
1115
|
+
},
|
|
1116
|
+
getFps: function getFps() {
|
|
1117
|
+
return fps;
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
function createReducedMotionPreference(enabled, onChange) {
|
|
1122
|
+
var query = enabled && typeof matchMedia !== 'undefined' ? matchMedia('(prefers-reduced-motion: reduce)') : null;
|
|
1123
|
+
var notify = function notify() {
|
|
1124
|
+
if (typeof onChange === 'function') onChange(Boolean(query && query.matches));
|
|
1125
|
+
};
|
|
1126
|
+
if (query) {
|
|
1127
|
+
if (typeof query.addEventListener === 'function') query.addEventListener('change', notify);else if (typeof query.addListener === 'function') query.addListener(notify);
|
|
1128
|
+
}
|
|
1129
|
+
return {
|
|
1130
|
+
matches: function matches() {
|
|
1131
|
+
return Boolean(query && query.matches);
|
|
1132
|
+
},
|
|
1133
|
+
dispose: function dispose() {
|
|
1134
|
+
if (!query) return;
|
|
1135
|
+
if (typeof query.removeEventListener === 'function') query.removeEventListener('change', notify);else if (typeof query.removeListener === 'function') query.removeListener(notify);
|
|
1136
|
+
}
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
function toFiniteNumber(value) {
|
|
1141
|
+
if (value == null || typeof value === 'boolean') return null;
|
|
1142
|
+
if (typeof value === 'string' && value.trim() === '') return null;
|
|
1143
|
+
var number = Number(value);
|
|
1144
|
+
return Number.isFinite(number) ? number : null;
|
|
1039
1145
|
}
|
|
1040
1146
|
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1147
|
+
var HOST_STYLES = new WeakMap();
|
|
1148
|
+
function acquireHostStyles(host) {
|
|
1149
|
+
var active = HOST_STYLES.get(host);
|
|
1150
|
+
if (active) {
|
|
1151
|
+
active.count += 1;
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
var state = {
|
|
1155
|
+
count: 1,
|
|
1156
|
+
position: host.style.position,
|
|
1157
|
+
isolation: host.style.isolation
|
|
1158
|
+
};
|
|
1159
|
+
var computed = getComputedStyle(host);
|
|
1160
|
+
if (computed.position === 'static' || computed.position === '') host.style.position = 'relative';
|
|
1161
|
+
host.style.isolation = 'isolate';
|
|
1162
|
+
HOST_STYLES.set(host, state);
|
|
1163
|
+
}
|
|
1164
|
+
function releaseHostStyles(host) {
|
|
1165
|
+
var state = HOST_STYLES.get(host);
|
|
1166
|
+
if (!state) return;
|
|
1167
|
+
state.count -= 1;
|
|
1168
|
+
if (state.count > 0) return;
|
|
1169
|
+
host.style.position = state.position;
|
|
1170
|
+
host.style.isolation = state.isolation;
|
|
1171
|
+
HOST_STYLES.delete(host);
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* Mount the cosmic (nebula) material as a background layer inside `host`.
|
|
1176
|
+
*
|
|
1177
|
+
* The layer is absolutely positioned and defaults to `z-index: -1`, so it
|
|
1178
|
+
* paints behind the host's in-flow content: text/buttons/images inside the
|
|
1179
|
+
* host sit on top with zero extra CSS. Host gets `position: relative;
|
|
1180
|
+
* isolation: isolate` automatically so the layer can never escape its box
|
|
1181
|
+
* (or break stacking outside it).
|
|
1182
|
+
*
|
|
1183
|
+
* Options: preset (literary name), colors, seed, speed, quality,
|
|
1184
|
+
* renderer, renderScale, powerPreference, fps, paused/static, mouseColor,
|
|
1185
|
+
* respectReducedMotion, opacity (0-1), fallbackColor (true=preset base
|
|
1186
|
+
* color, a hex string, or false to disable).
|
|
1053
1187
|
*/
|
|
1054
1188
|
function createColorBackground(host) {
|
|
1055
1189
|
var _options$preset;
|
|
@@ -1063,18 +1197,29 @@ function createColorBackground(host) {
|
|
|
1063
1197
|
renderer: DEFAULTS.capsule.renderer,
|
|
1064
1198
|
respectReducedMotion: DEFAULTS.capsule.respectReducedMotion,
|
|
1065
1199
|
mouseColor: true,
|
|
1200
|
+
renderScale: 1,
|
|
1201
|
+
powerPreference: 'high-performance',
|
|
1202
|
+
fps: DEFAULTS.capsule.fps,
|
|
1203
|
+
paused: false,
|
|
1204
|
+
static: false,
|
|
1066
1205
|
opacity: 1,
|
|
1067
1206
|
fallbackColor: true
|
|
1068
1207
|
}, preset, options);
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
preset.
|
|
1072
|
-
|
|
1073
|
-
var
|
|
1074
|
-
if (
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1208
|
+
merged.opacity = Number.isFinite(Number(merged.opacity)) ? Math.min(1, Math.max(0, Number(merged.opacity))) : 1;
|
|
1209
|
+
var normalizedColors = Array.isArray(merged.colors) ? merged.colors.map(normalizeColor) : [];
|
|
1210
|
+
if (normalizedColors.length === 4 && normalizedColors.every(Boolean)) preset.colors = normalizedColors;
|
|
1211
|
+
var initialSeed = toFiniteNumber(merged.seed);
|
|
1212
|
+
var initialSpeed = toFiniteNumber(merged.speed);
|
|
1213
|
+
if (initialSeed !== null) preset.seed = initialSeed;
|
|
1214
|
+
if (initialSpeed !== null) preset.speed = initialSpeed;
|
|
1215
|
+
merged.colors = _toConsumableArray(preset.colors);
|
|
1216
|
+
merged.seed = preset.seed;
|
|
1217
|
+
merged.speed = preset.speed;
|
|
1218
|
+
var optionColors = Array.isArray(options.colors) ? options.colors.map(normalizeColor) : [];
|
|
1219
|
+
var colorOverride = optionColors.length === 4 && optionColors.every(Boolean) ? _toConsumableArray(optionColors) : null;
|
|
1220
|
+
var seedOverride = options.seed !== undefined ? toFiniteNumber(options.seed) : null;
|
|
1221
|
+
var speedOverride = options.speed !== undefined ? toFiniteNumber(options.speed) : null;
|
|
1222
|
+
acquireHostStyles(host);
|
|
1078
1223
|
var layer = document.createElement('div');
|
|
1079
1224
|
layer.className = 'dlc-color-layer';
|
|
1080
1225
|
var syncLayerVars = function syncLayerVars() {
|
|
@@ -1089,8 +1234,12 @@ function createColorBackground(host) {
|
|
|
1089
1234
|
layer.appendChild(canvas);
|
|
1090
1235
|
host.appendChild(layer);
|
|
1091
1236
|
var emitter = createEmitter();
|
|
1092
|
-
var
|
|
1237
|
+
var manuallyPaused = merged.paused === true;
|
|
1238
|
+
var reducedPaused = false;
|
|
1239
|
+
var staticMode = merged.static === true;
|
|
1240
|
+
var contextLost = false;
|
|
1093
1241
|
var disposed = false;
|
|
1242
|
+
var renderOnce = function renderOnce() {};
|
|
1094
1243
|
var dirty = {
|
|
1095
1244
|
preset: false,
|
|
1096
1245
|
seed: false,
|
|
@@ -1098,19 +1247,37 @@ function createColorBackground(host) {
|
|
|
1098
1247
|
colors: false,
|
|
1099
1248
|
opacity: false,
|
|
1100
1249
|
fallbackColor: false,
|
|
1101
|
-
mouseColor: false
|
|
1250
|
+
mouseColor: false,
|
|
1251
|
+
quality: false,
|
|
1252
|
+
renderScale: false,
|
|
1253
|
+
paused: false,
|
|
1254
|
+
static: false,
|
|
1255
|
+
fps: false
|
|
1102
1256
|
};
|
|
1103
1257
|
var renderer;
|
|
1104
1258
|
var useWebgl = merged.renderer !== 'canvas2d';
|
|
1105
1259
|
if (useWebgl) {
|
|
1106
1260
|
try {
|
|
1107
1261
|
renderer = new CosmicRenderer(canvas, merged, {
|
|
1108
|
-
dprCap:
|
|
1262
|
+
dprCap: effectiveDprCap(merged.quality, merged.renderScale),
|
|
1109
1263
|
mouseColor: merged.mouseColor !== false,
|
|
1110
|
-
eventTarget: host
|
|
1264
|
+
eventTarget: host,
|
|
1265
|
+
powerPreference: merged.powerPreference,
|
|
1266
|
+
onContextLost: function onContextLost() {
|
|
1267
|
+
contextLost = true;
|
|
1268
|
+
emitter.emit('contextlost', {});
|
|
1269
|
+
},
|
|
1270
|
+
onContextRestored: function onContextRestored() {
|
|
1271
|
+
contextLost = false;
|
|
1272
|
+
emitter.emit('contextrestored', {});
|
|
1273
|
+
renderOnce();
|
|
1274
|
+
wakeScheduler();
|
|
1275
|
+
}
|
|
1111
1276
|
});
|
|
1112
1277
|
} catch (error) {
|
|
1113
|
-
renderer = new FallbackRenderer(canvas, merged
|
|
1278
|
+
renderer = new FallbackRenderer(canvas, merged, {
|
|
1279
|
+
dprCap: effectiveDprCap(merged.quality, merged.renderScale)
|
|
1280
|
+
});
|
|
1114
1281
|
nextTick(function () {
|
|
1115
1282
|
if (disposed) return;
|
|
1116
1283
|
emitter.emit('error', {
|
|
@@ -1119,19 +1286,37 @@ function createColorBackground(host) {
|
|
|
1119
1286
|
});
|
|
1120
1287
|
}
|
|
1121
1288
|
} else {
|
|
1122
|
-
renderer = new FallbackRenderer(canvas, merged
|
|
1289
|
+
renderer = new FallbackRenderer(canvas, merged, {
|
|
1290
|
+
dprCap: effectiveDprCap(merged.quality, merged.renderScale)
|
|
1291
|
+
});
|
|
1123
1292
|
}
|
|
1124
|
-
|
|
1125
|
-
return renderer.resize();
|
|
1126
|
-
}) : null;
|
|
1127
|
-
if (resizeObserver) resizeObserver.observe(host);else window.addEventListener('resize', renderer.resize);
|
|
1128
|
-
var visibility = createVisibilityGuard(layer);
|
|
1293
|
+
renderer.resize();
|
|
1129
1294
|
var animationTime = 0;
|
|
1295
|
+
var frameGate = createFrameGate(merged.fps);
|
|
1296
|
+
renderOnce = function renderOnce() {
|
|
1297
|
+
return renderer.draw(animationTime);
|
|
1298
|
+
};
|
|
1299
|
+
var resize = function resize() {
|
|
1300
|
+
renderer.resize();
|
|
1301
|
+
if (manuallyPaused || reducedPaused || staticMode) renderOnce();
|
|
1302
|
+
};
|
|
1303
|
+
var resizeObserver = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(resize) : null;
|
|
1304
|
+
if (resizeObserver) resizeObserver.observe(host);else window.addEventListener('resize', resize);
|
|
1305
|
+
var visibility = createVisibilityGuard(layer, wakeScheduler);
|
|
1306
|
+
var motionPreference = createReducedMotionPreference(merged.respectReducedMotion, function (matches) {
|
|
1307
|
+
reducedPaused = matches;
|
|
1308
|
+
if (matches) renderOnce();else wakeScheduler();
|
|
1309
|
+
});
|
|
1310
|
+
reducedPaused = motionPreference.matches();
|
|
1311
|
+
var isMotionPaused = function isMotionPaused() {
|
|
1312
|
+
return manuallyPaused || reducedPaused || staticMode || contextLost;
|
|
1313
|
+
};
|
|
1314
|
+
renderOnce();
|
|
1130
1315
|
var unsubscribe = subscribeScheduler(function (delta) {
|
|
1131
1316
|
animationTime += delta;
|
|
1132
|
-
if (
|
|
1317
|
+
if (frameGate.shouldDraw(delta)) renderer.draw(animationTime);
|
|
1133
1318
|
}, function () {
|
|
1134
|
-
return
|
|
1319
|
+
return isMotionPaused() || !visibility.isVisible();
|
|
1135
1320
|
});
|
|
1136
1321
|
nextTick(function () {
|
|
1137
1322
|
if (disposed) return;
|
|
@@ -1150,11 +1335,15 @@ function createColorBackground(host) {
|
|
|
1150
1335
|
var next = getPreset('capsule', ref);
|
|
1151
1336
|
dirty.preset = true;
|
|
1152
1337
|
Object.assign(preset, next);
|
|
1338
|
+
if (colorOverride) preset.colors = _toConsumableArray(colorOverride);
|
|
1339
|
+
if (seedOverride !== null) preset.seed = seedOverride;
|
|
1340
|
+
if (speedOverride !== null) preset.speed = speedOverride;
|
|
1153
1341
|
var nextColors = preset.colors.map(normalizeColor);
|
|
1154
1342
|
if (nextColors.every(Boolean)) preset.colors = nextColors;
|
|
1155
1343
|
renderer.setPreset(_objectSpread2({}, preset));
|
|
1156
1344
|
renderer.resize();
|
|
1157
1345
|
syncLayerVars();
|
|
1346
|
+
if (isMotionPaused()) renderOnce();
|
|
1158
1347
|
emitter.emit('presetchange', {
|
|
1159
1348
|
preset: _objectSpread2({}, preset)
|
|
1160
1349
|
});
|
|
@@ -1166,27 +1355,33 @@ function createColorBackground(host) {
|
|
|
1166
1355
|
return !color;
|
|
1167
1356
|
})) return this;
|
|
1168
1357
|
dirty.colors = true;
|
|
1358
|
+
colorOverride = _toConsumableArray(next);
|
|
1169
1359
|
preset.colors = next;
|
|
1170
1360
|
renderer.setPreset(_objectSpread2(_objectSpread2({}, preset), {}, {
|
|
1171
1361
|
colors: next
|
|
1172
1362
|
}));
|
|
1173
1363
|
syncLayerVars();
|
|
1364
|
+
if (isMotionPaused()) renderOnce();
|
|
1174
1365
|
return this;
|
|
1175
1366
|
},
|
|
1176
1367
|
setSeed: function setSeed(seed) {
|
|
1177
|
-
var value =
|
|
1178
|
-
if (
|
|
1368
|
+
var value = toFiniteNumber(seed);
|
|
1369
|
+
if (value === null) return this;
|
|
1179
1370
|
dirty.seed = true;
|
|
1371
|
+
seedOverride = value;
|
|
1180
1372
|
preset.seed = value;
|
|
1181
1373
|
renderer.setPreset(_objectSpread2({}, preset));
|
|
1374
|
+
if (isMotionPaused()) renderOnce();
|
|
1182
1375
|
return this;
|
|
1183
1376
|
},
|
|
1184
1377
|
setSpeed: function setSpeed(speed) {
|
|
1185
|
-
var value =
|
|
1186
|
-
if (
|
|
1378
|
+
var value = toFiniteNumber(speed);
|
|
1379
|
+
if (value === null) return this;
|
|
1187
1380
|
dirty.speed = true;
|
|
1381
|
+
speedOverride = value;
|
|
1188
1382
|
preset.speed = value;
|
|
1189
1383
|
renderer.setPreset(_objectSpread2({}, preset));
|
|
1384
|
+
if (isMotionPaused()) renderOnce();
|
|
1190
1385
|
return this;
|
|
1191
1386
|
},
|
|
1192
1387
|
setFallbackColor: function setFallbackColor(value) {
|
|
@@ -1202,8 +1397,23 @@ function createColorBackground(host) {
|
|
|
1202
1397
|
return this;
|
|
1203
1398
|
},
|
|
1204
1399
|
setQuality: function setQuality(quality) {
|
|
1400
|
+
dirty.quality = true;
|
|
1205
1401
|
merged.quality = quality;
|
|
1206
|
-
if (typeof renderer.setDprCap === 'function')
|
|
1402
|
+
if (typeof renderer.setDprCap === 'function') {
|
|
1403
|
+
renderer.setDprCap(effectiveDprCap(quality, merged.renderScale));
|
|
1404
|
+
}
|
|
1405
|
+
if (isMotionPaused()) renderOnce();
|
|
1406
|
+
return this;
|
|
1407
|
+
},
|
|
1408
|
+
setRenderScale: function setRenderScale(renderScale) {
|
|
1409
|
+
var value = Number(renderScale);
|
|
1410
|
+
if (!Number.isFinite(value)) return this;
|
|
1411
|
+
dirty.renderScale = true;
|
|
1412
|
+
merged.renderScale = Math.min(1, Math.max(0.25, value));
|
|
1413
|
+
if (typeof renderer.setDprCap === 'function') {
|
|
1414
|
+
renderer.setDprCap(effectiveDprCap(merged.quality, merged.renderScale));
|
|
1415
|
+
}
|
|
1416
|
+
if (isMotionPaused()) renderOnce();
|
|
1207
1417
|
return this;
|
|
1208
1418
|
},
|
|
1209
1419
|
setOpacity: function setOpacity(value) {
|
|
@@ -1219,20 +1429,42 @@ function createColorBackground(host) {
|
|
|
1219
1429
|
return this;
|
|
1220
1430
|
},
|
|
1221
1431
|
pause: function pause() {
|
|
1222
|
-
paused = true;
|
|
1432
|
+
dirty.paused = true;
|
|
1433
|
+
manuallyPaused = true;
|
|
1434
|
+
renderOnce();
|
|
1223
1435
|
return this;
|
|
1224
1436
|
},
|
|
1225
1437
|
resume: function resume() {
|
|
1226
|
-
paused =
|
|
1438
|
+
dirty.paused = true;
|
|
1439
|
+
manuallyPaused = false;
|
|
1440
|
+
wakeScheduler();
|
|
1441
|
+
return this;
|
|
1442
|
+
},
|
|
1443
|
+
setPaused: function setPaused(value) {
|
|
1444
|
+
return value ? this.pause() : this.resume();
|
|
1445
|
+
},
|
|
1446
|
+
setStatic: function setStatic(value) {
|
|
1447
|
+
dirty.static = true;
|
|
1448
|
+
staticMode = value === true;
|
|
1449
|
+
merged.static = staticMode;
|
|
1450
|
+
if (staticMode) renderOnce();else wakeScheduler();
|
|
1451
|
+
return this;
|
|
1452
|
+
},
|
|
1453
|
+
setFps: function setFps(fps) {
|
|
1454
|
+
dirty.fps = true;
|
|
1455
|
+
merged.fps = frameGate.setFps(fps);
|
|
1456
|
+
wakeScheduler();
|
|
1227
1457
|
return this;
|
|
1228
1458
|
},
|
|
1229
1459
|
dispose: function dispose() {
|
|
1230
1460
|
disposed = true;
|
|
1231
1461
|
unsubscribe();
|
|
1232
1462
|
visibility.dispose();
|
|
1233
|
-
|
|
1463
|
+
motionPreference.dispose();
|
|
1464
|
+
if (resizeObserver) resizeObserver.disconnect();else window.removeEventListener('resize', resize);
|
|
1234
1465
|
renderer.dispose();
|
|
1235
1466
|
layer.remove();
|
|
1467
|
+
releaseHostStyles(host);
|
|
1236
1468
|
},
|
|
1237
1469
|
get opacity() {
|
|
1238
1470
|
return merged.opacity;
|
|
@@ -1243,6 +1475,21 @@ function createColorBackground(host) {
|
|
|
1243
1475
|
get mouseColor() {
|
|
1244
1476
|
return merged.mouseColor;
|
|
1245
1477
|
},
|
|
1478
|
+
get quality() {
|
|
1479
|
+
return merged.quality;
|
|
1480
|
+
},
|
|
1481
|
+
get renderScale() {
|
|
1482
|
+
return merged.renderScale;
|
|
1483
|
+
},
|
|
1484
|
+
get paused() {
|
|
1485
|
+
return manuallyPaused;
|
|
1486
|
+
},
|
|
1487
|
+
get static() {
|
|
1488
|
+
return staticMode;
|
|
1489
|
+
},
|
|
1490
|
+
get fps() {
|
|
1491
|
+
return frameGate.getFps();
|
|
1492
|
+
},
|
|
1246
1493
|
dirty: dirty
|
|
1247
1494
|
};
|
|
1248
1495
|
}
|