@tsparticles/all 4.2.1 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/browser/index.js +3 -1
- package/browser/index.lazy.js +1 -1
- package/cjs/index.js +3 -1
- package/cjs/index.lazy.js +1 -1
- package/esm/index.js +3 -1
- package/esm/index.lazy.js +1 -1
- package/package.json +80 -79
- package/report.html +1 -1
- package/tsparticles.all.bundle.js +2049 -1755
- package/tsparticles.all.bundle.min.js +1 -1
- package/tsparticles.all.js +7 -6
- package/tsparticles.all.min.js +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
(function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
|
|
2
|
-
/* tsParticles v4.
|
|
2
|
+
/* tsParticles v4.3.0 */
|
|
3
3
|
(function (global, factory) {
|
|
4
4
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
5
5
|
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
@@ -398,29 +398,27 @@
|
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
400
|
else if (!isObject(destination) || Array.isArray(destination)) {
|
|
401
|
-
destination =
|
|
401
|
+
destination = Object.create(null);
|
|
402
402
|
}
|
|
403
|
-
const sourceKeys = Object.keys(source),
|
|
403
|
+
const sourceKeys = Object.keys(source), hasNested = sourceKeys.some(k => {
|
|
404
404
|
const v = source[k];
|
|
405
405
|
return isObject(v) || Array.isArray(v);
|
|
406
406
|
});
|
|
407
407
|
if (!hasNested) {
|
|
408
408
|
const sourceDict = source, destDict = destination;
|
|
409
409
|
for (const key of sourceKeys) {
|
|
410
|
-
if (
|
|
410
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
|
411
411
|
continue;
|
|
412
412
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
destDict[key] = v;
|
|
417
|
-
}
|
|
413
|
+
const v = sourceDict[key];
|
|
414
|
+
if (v !== undefined) {
|
|
415
|
+
destDict[key] = v;
|
|
418
416
|
}
|
|
419
417
|
}
|
|
420
418
|
continue;
|
|
421
419
|
}
|
|
422
420
|
for (const key of sourceKeys) {
|
|
423
|
-
if (
|
|
421
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
|
424
422
|
continue;
|
|
425
423
|
}
|
|
426
424
|
const sourceDict = source, destDict = destination, value = sourceDict[key];
|
|
@@ -1112,6 +1110,18 @@
|
|
|
1112
1110
|
AnimationStatus["decreasing"] = "decreasing";
|
|
1113
1111
|
})(exports.AnimationStatus || (exports.AnimationStatus = {}));
|
|
1114
1112
|
|
|
1113
|
+
exports.DrawLayer = void 0;
|
|
1114
|
+
(function (DrawLayer) {
|
|
1115
|
+
DrawLayer[DrawLayer["BackgroundElement"] = 0] = "BackgroundElement";
|
|
1116
|
+
DrawLayer[DrawLayer["BackgroundDraw"] = 1] = "BackgroundDraw";
|
|
1117
|
+
DrawLayer[DrawLayer["BackgroundMask"] = 2] = "BackgroundMask";
|
|
1118
|
+
DrawLayer[DrawLayer["CanvasSetup"] = 3] = "CanvasSetup";
|
|
1119
|
+
DrawLayer[DrawLayer["PluginContent"] = 4] = "PluginContent";
|
|
1120
|
+
DrawLayer[DrawLayer["Particles"] = 5] = "Particles";
|
|
1121
|
+
DrawLayer[DrawLayer["CanvasCleanup"] = 6] = "CanvasCleanup";
|
|
1122
|
+
DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
|
|
1123
|
+
})(exports.DrawLayer || (exports.DrawLayer = {}));
|
|
1124
|
+
|
|
1115
1125
|
class OptionLoader {
|
|
1116
1126
|
load(data) {
|
|
1117
1127
|
if (isNull(data)) {
|
|
@@ -1270,6 +1280,8 @@
|
|
|
1270
1280
|
|
|
1271
1281
|
class Background extends OptionLoader {
|
|
1272
1282
|
color;
|
|
1283
|
+
draw;
|
|
1284
|
+
element;
|
|
1273
1285
|
image = "";
|
|
1274
1286
|
opacity = 1;
|
|
1275
1287
|
position = "";
|
|
@@ -1284,6 +1296,8 @@
|
|
|
1284
1296
|
if (data.color !== undefined) {
|
|
1285
1297
|
this.color = OptionsColor.create(this.color, data.color);
|
|
1286
1298
|
}
|
|
1299
|
+
loadProperty(this, "element", data.element);
|
|
1300
|
+
loadProperty(this, "draw", data.draw);
|
|
1287
1301
|
loadProperty(this, "image", data.image);
|
|
1288
1302
|
loadProperty(this, "position", data.position);
|
|
1289
1303
|
loadProperty(this, "repeat", data.repeat);
|
|
@@ -1829,7 +1843,7 @@
|
|
|
1829
1843
|
}
|
|
1830
1844
|
}
|
|
1831
1845
|
|
|
1832
|
-
const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, sdrReferenceWhiteNits = 203;
|
|
1846
|
+
const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
|
|
1833
1847
|
function getCachedStyle(key, generator) {
|
|
1834
1848
|
let cached = styleCache.get(key);
|
|
1835
1849
|
if (!cached) {
|
|
@@ -1972,6 +1986,17 @@
|
|
|
1972
1986
|
: lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
|
|
1973
1987
|
return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
|
|
1974
1988
|
}
|
|
1989
|
+
function hslToRgbFloat(hsl) {
|
|
1990
|
+
const h = ((hsl.h % hMax) + hMax) % hMax, s = Math.max(sMin, Math.min(sMax, hsl.s)), l = Math.max(lMin, Math.min(lMax, hsl.l)), hNormalized = h / hMax, sNormalized = s / sMax, lNormalized = l / lMax;
|
|
1991
|
+
if (s === sMin) {
|
|
1992
|
+
const grayscaleValue = lNormalized * rgbMax;
|
|
1993
|
+
return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
|
|
1994
|
+
}
|
|
1995
|
+
const temp1 = lNormalized < half$2
|
|
1996
|
+
? lNormalized * (sNormalizedOffset + sNormalized)
|
|
1997
|
+
: lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
|
|
1998
|
+
return { r: red, g: green, b: blue };
|
|
1999
|
+
}
|
|
1975
2000
|
function hslaToRgba(hsla) {
|
|
1976
2001
|
const rgbResult = hslToRgb(hsla);
|
|
1977
2002
|
return {
|
|
@@ -1981,8 +2006,16 @@
|
|
|
1981
2006
|
r: rgbResult.r,
|
|
1982
2007
|
};
|
|
1983
2008
|
}
|
|
1984
|
-
function getRandomRgbColor(min) {
|
|
1985
|
-
const fixedMin = min ?? defaultRgbMin
|
|
2009
|
+
function getRandomRgbColor(min, hdr) {
|
|
2010
|
+
const fixedMin = min ?? defaultRgbMin;
|
|
2011
|
+
if (hdr) {
|
|
2012
|
+
return {
|
|
2013
|
+
r: getRandomInRange(fixedMin, rgbMax),
|
|
2014
|
+
g: getRandomInRange(fixedMin, rgbMax),
|
|
2015
|
+
b: getRandomInRange(fixedMin, rgbMax),
|
|
2016
|
+
};
|
|
2017
|
+
}
|
|
2018
|
+
const fixedMax = rgbMax + identity$3, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
|
|
1986
2019
|
return {
|
|
1987
2020
|
b: getRgbInRangeValue(),
|
|
1988
2021
|
g: getRgbInRangeValue(),
|
|
@@ -1990,7 +2023,7 @@
|
|
|
1990
2023
|
};
|
|
1991
2024
|
}
|
|
1992
2025
|
function getStyleFromRgb(color, hdr, opacity) {
|
|
1993
|
-
const op = opacity ?? defaultOpacity$3, key = `rgb-${color.r.toFixed(
|
|
2026
|
+
const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$3, key = `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
|
|
1994
2027
|
return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
|
|
1995
2028
|
}
|
|
1996
2029
|
function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
|
|
@@ -2001,9 +2034,9 @@
|
|
|
2001
2034
|
return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$3).toString()})`;
|
|
2002
2035
|
}
|
|
2003
2036
|
function getStyleFromHsl(color, hdr, opacity) {
|
|
2004
|
-
const op = opacity ?? defaultOpacity$3, key = `hsl-${color.h.toFixed(
|
|
2037
|
+
const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$3, key = `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
|
|
2005
2038
|
return getCachedStyle(key, () => hdr
|
|
2006
|
-
? getStyleFromRgb(
|
|
2039
|
+
? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
|
|
2007
2040
|
: `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
|
|
2008
2041
|
}
|
|
2009
2042
|
function colorMix(color1, color2, size1, size2) {
|
|
@@ -2123,7 +2156,7 @@
|
|
|
2123
2156
|
colorValue.velocity = defaultVelocity;
|
|
2124
2157
|
}
|
|
2125
2158
|
}
|
|
2126
|
-
function updateColorValue(data, decrease, delta) {
|
|
2159
|
+
function updateColorValue(data, decrease, delta, hdr) {
|
|
2127
2160
|
const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
|
|
2128
2161
|
if (!data.enable ||
|
|
2129
2162
|
((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
|
|
@@ -2136,7 +2169,7 @@
|
|
|
2136
2169
|
if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
|
|
2137
2170
|
return;
|
|
2138
2171
|
}
|
|
2139
|
-
const offset = data.offset ? randomInRangeValue(data.offset) : minOffset, velocity = (data.velocity ?? minVelocity) * delta.factor + offset * velocityFactor, decay = data.decay ?? identity, max = data.max, min = data.min;
|
|
2172
|
+
const offset = data.offset ? randomInRangeValue(data.offset) : minOffset, velocity = ((data.velocity ?? minVelocity) * delta.factor + offset * velocityFactor) * (hdr ? hdrAnimationScale : identity), decay = data.decay ?? identity, max = data.max, min = data.min;
|
|
2140
2173
|
if (!decrease || data.status === exports.AnimationStatus.increasing) {
|
|
2141
2174
|
data.value += velocity;
|
|
2142
2175
|
if (data.value > max) {
|
|
@@ -2163,14 +2196,14 @@
|
|
|
2163
2196
|
}
|
|
2164
2197
|
data.value = clamp(data.value, min, max);
|
|
2165
2198
|
}
|
|
2166
|
-
function updateColor(color, delta) {
|
|
2199
|
+
function updateColor(color, delta, hdr) {
|
|
2167
2200
|
if (!color) {
|
|
2168
2201
|
return;
|
|
2169
2202
|
}
|
|
2170
2203
|
const { h, s, l } = color;
|
|
2171
|
-
updateColorValue(h, false, delta);
|
|
2172
|
-
updateColorValue(s, true, delta);
|
|
2173
|
-
updateColorValue(l, true, delta);
|
|
2204
|
+
updateColorValue(h, false, delta, hdr);
|
|
2205
|
+
updateColorValue(s, true, delta, hdr);
|
|
2206
|
+
updateColorValue(l, true, delta, hdr);
|
|
2174
2207
|
}
|
|
2175
2208
|
function alterHsl(color, type, value) {
|
|
2176
2209
|
return {
|
|
@@ -2218,6 +2251,8 @@
|
|
|
2218
2251
|
|
|
2219
2252
|
class BackgroundMaskCover {
|
|
2220
2253
|
color;
|
|
2254
|
+
draw;
|
|
2255
|
+
element;
|
|
2221
2256
|
image;
|
|
2222
2257
|
opacity = 1;
|
|
2223
2258
|
load(data) {
|
|
@@ -2227,6 +2262,8 @@
|
|
|
2227
2262
|
if (data.color !== undefined) {
|
|
2228
2263
|
this.color = OptionsColor.create(this.color, data.color);
|
|
2229
2264
|
}
|
|
2265
|
+
loadProperty(this, "draw", data.draw);
|
|
2266
|
+
loadProperty(this, "element", data.element);
|
|
2230
2267
|
loadProperty(this, "image", data.image);
|
|
2231
2268
|
loadProperty(this, "opacity", data.opacity);
|
|
2232
2269
|
}
|
|
@@ -2243,7 +2280,12 @@
|
|
|
2243
2280
|
loadProperty(this, "composite", data.composite);
|
|
2244
2281
|
if (data.cover !== undefined) {
|
|
2245
2282
|
const cover = data.cover, color = (isString(data.cover) ? { color: data.cover } : data.cover);
|
|
2246
|
-
this.cover.load(cover.color !== undefined ||
|
|
2283
|
+
this.cover.load(cover.color !== undefined ||
|
|
2284
|
+
cover.draw !== undefined ||
|
|
2285
|
+
cover.element !== undefined ||
|
|
2286
|
+
cover.image !== undefined
|
|
2287
|
+
? cover
|
|
2288
|
+
: { color: color });
|
|
2247
2289
|
}
|
|
2248
2290
|
loadProperty(this, "enable", data.enable);
|
|
2249
2291
|
}
|
|
@@ -11108,8 +11150,8 @@
|
|
|
11108
11150
|
if (!this.isEnabled(particle)) {
|
|
11109
11151
|
return;
|
|
11110
11152
|
}
|
|
11111
|
-
updateColor(particle.fillColor, delta);
|
|
11112
|
-
updateColor(particle.strokeColor, delta);
|
|
11153
|
+
updateColor(particle.fillColor, delta, this.#container.hdr);
|
|
11154
|
+
updateColor(particle.strokeColor, delta, this.#container.hdr);
|
|
11113
11155
|
}
|
|
11114
11156
|
}
|
|
11115
11157
|
|
|
@@ -11862,6 +11904,19 @@
|
|
|
11862
11904
|
}
|
|
11863
11905
|
}
|
|
11864
11906
|
|
|
11907
|
+
class BubbleModifier {
|
|
11908
|
+
div;
|
|
11909
|
+
enabled = false;
|
|
11910
|
+
fillColor;
|
|
11911
|
+
finalColor;
|
|
11912
|
+
id = "bubble";
|
|
11913
|
+
inRange = false;
|
|
11914
|
+
opacity;
|
|
11915
|
+
priority = 100;
|
|
11916
|
+
radius;
|
|
11917
|
+
strokeColor;
|
|
11918
|
+
}
|
|
11919
|
+
|
|
11865
11920
|
var ProcessBubbleType;
|
|
11866
11921
|
(function (ProcessBubbleType) {
|
|
11867
11922
|
ProcessBubbleType["color"] = "color";
|
|
@@ -11885,6 +11940,7 @@
|
|
|
11885
11940
|
class Bubbler extends ExternalInteractorBase {
|
|
11886
11941
|
handleClickMode;
|
|
11887
11942
|
#maxDistance;
|
|
11943
|
+
#modifiers = new WeakMap();
|
|
11888
11944
|
#pluginManager;
|
|
11889
11945
|
constructor(pluginManager, container) {
|
|
11890
11946
|
super(container);
|
|
@@ -11903,13 +11959,21 @@
|
|
|
11903
11959
|
return this.#maxDistance;
|
|
11904
11960
|
}
|
|
11905
11961
|
clear(particle, _delta, force) {
|
|
11906
|
-
|
|
11962
|
+
const mod = this.#modifiers.get(particle);
|
|
11963
|
+
if (mod?.inRange && !force) {
|
|
11907
11964
|
return;
|
|
11908
11965
|
}
|
|
11909
|
-
|
|
11910
|
-
delete
|
|
11911
|
-
|
|
11912
|
-
|
|
11966
|
+
particle.removeModifier(bubbleMode);
|
|
11967
|
+
this.#modifiers.delete(particle);
|
|
11968
|
+
}
|
|
11969
|
+
getOrCreateModifier(particle) {
|
|
11970
|
+
let mod = this.#modifiers.get(particle);
|
|
11971
|
+
if (!mod) {
|
|
11972
|
+
mod = new BubbleModifier();
|
|
11973
|
+
this.#modifiers.set(particle, mod);
|
|
11974
|
+
particle.addModifier(mod);
|
|
11975
|
+
}
|
|
11976
|
+
return mod;
|
|
11913
11977
|
}
|
|
11914
11978
|
init() {
|
|
11915
11979
|
const container = this.container, bubble = container.actualOptions.interactivity?.modes.bubble;
|
|
@@ -11955,7 +12019,11 @@
|
|
|
11955
12019
|
loadOptionProperty(options, "bubble", Bubble, ...sources);
|
|
11956
12020
|
}
|
|
11957
12021
|
reset(_interactivityData, particle) {
|
|
11958
|
-
|
|
12022
|
+
const mod = this.#modifiers.get(particle);
|
|
12023
|
+
if (mod) {
|
|
12024
|
+
mod.enabled = false;
|
|
12025
|
+
mod.inRange = false;
|
|
12026
|
+
}
|
|
11959
12027
|
}
|
|
11960
12028
|
#clickBubble(interactivityData) {
|
|
11961
12029
|
const container = this.container, options = container.actualOptions, mouseClickPos = interactivityData.mouse.clickPosition, bubbleOptions = options.interactivity?.modes.bubble;
|
|
@@ -11972,7 +12040,9 @@
|
|
|
11972
12040
|
if (!bubble.clicking) {
|
|
11973
12041
|
continue;
|
|
11974
12042
|
}
|
|
11975
|
-
|
|
12043
|
+
const mod = this.getOrCreateModifier(particle);
|
|
12044
|
+
mod.enabled = !bubble.durationEnd;
|
|
12045
|
+
mod.inRange = !bubble.durationEnd;
|
|
11976
12046
|
const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (performance.now() - (interactivityData.mouse.clickTime ?? defaultClickTime)) / millisecondsToSeconds$1;
|
|
11977
12047
|
if (timeSpent > bubbleOptions.duration) {
|
|
11978
12048
|
bubble.durationEnd = true;
|
|
@@ -11984,7 +12054,7 @@
|
|
|
11984
12054
|
const sizeData = {
|
|
11985
12055
|
bubbleObj: {
|
|
11986
12056
|
optValue: container.retina.bubbleModeSize,
|
|
11987
|
-
value:
|
|
12057
|
+
value: mod.radius,
|
|
11988
12058
|
},
|
|
11989
12059
|
particlesObj: {
|
|
11990
12060
|
optValue: particle.size.max,
|
|
@@ -11996,7 +12066,7 @@
|
|
|
11996
12066
|
const opacityData = {
|
|
11997
12067
|
bubbleObj: {
|
|
11998
12068
|
optValue: bubbleOptions.opacity,
|
|
11999
|
-
value:
|
|
12069
|
+
value: mod.opacity,
|
|
12000
12070
|
},
|
|
12001
12071
|
particlesObj: {
|
|
12002
12072
|
optValue: particle.opacity?.max ?? defaultOpacity$1,
|
|
@@ -12009,7 +12079,8 @@
|
|
|
12009
12079
|
this.#hoverBubbleColor(particle, distMouse);
|
|
12010
12080
|
}
|
|
12011
12081
|
else {
|
|
12012
|
-
|
|
12082
|
+
mod.fillColor = undefined;
|
|
12083
|
+
mod.strokeColor = undefined;
|
|
12013
12084
|
}
|
|
12014
12085
|
}
|
|
12015
12086
|
}
|
|
@@ -12020,7 +12091,9 @@
|
|
|
12020
12091
|
}
|
|
12021
12092
|
const query = container.particles.grid.queryCircle(mousePos, distance, p => this.isEnabled(interactivityData, p));
|
|
12022
12093
|
for (const particle of query) {
|
|
12023
|
-
|
|
12094
|
+
const mod = this.getOrCreateModifier(particle);
|
|
12095
|
+
mod.enabled = true;
|
|
12096
|
+
mod.inRange = true;
|
|
12024
12097
|
const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = ratioOffset - pointDistance / distance;
|
|
12025
12098
|
if (pointDistance <= distance) {
|
|
12026
12099
|
if (ratio >= minRatio && interactivityData.status === mouseMoveEvent) {
|
|
@@ -12038,30 +12111,38 @@
|
|
|
12038
12111
|
}
|
|
12039
12112
|
}
|
|
12040
12113
|
#hoverBubbleColor(particle, ratio, divBubble) {
|
|
12041
|
-
const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble;
|
|
12114
|
+
const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity?.modes.bubble, mod = this.getOrCreateModifier(particle);
|
|
12042
12115
|
if (!bubbleOptions) {
|
|
12043
12116
|
return;
|
|
12044
12117
|
}
|
|
12045
|
-
if (!
|
|
12118
|
+
if (!mod.finalColor) {
|
|
12046
12119
|
const modeColor = bubbleOptions.color;
|
|
12047
12120
|
if (!modeColor) {
|
|
12048
12121
|
return;
|
|
12049
12122
|
}
|
|
12050
12123
|
const bubbleColor = itemFromSingleOrMultiple(modeColor);
|
|
12051
|
-
|
|
12124
|
+
mod.finalColor = rangeColorToHsl(this.#pluginManager, bubbleColor);
|
|
12052
12125
|
}
|
|
12053
|
-
if (!
|
|
12126
|
+
if (!mod.finalColor) {
|
|
12054
12127
|
return;
|
|
12055
12128
|
}
|
|
12056
12129
|
if (bubbleOptions.mix) {
|
|
12057
|
-
|
|
12130
|
+
mod.fillColor = undefined;
|
|
12131
|
+
mod.strokeColor = undefined;
|
|
12058
12132
|
const pColor = particle.getFillColor();
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12133
|
+
if (pColor) {
|
|
12134
|
+
const mixedColor = rgbToHsl(colorMix(pColor, mod.finalColor, ratioOffset - ratio, ratio));
|
|
12135
|
+
mod.fillColor = mixedColor;
|
|
12136
|
+
mod.strokeColor = mixedColor;
|
|
12137
|
+
}
|
|
12138
|
+
else {
|
|
12139
|
+
mod.fillColor = mod.finalColor;
|
|
12140
|
+
mod.strokeColor = mod.finalColor;
|
|
12141
|
+
}
|
|
12062
12142
|
}
|
|
12063
12143
|
else {
|
|
12064
|
-
|
|
12144
|
+
mod.fillColor = mod.finalColor;
|
|
12145
|
+
mod.strokeColor = mod.finalColor;
|
|
12065
12146
|
}
|
|
12066
12147
|
}
|
|
12067
12148
|
#hoverBubbleOpacity(particle, ratio, divBubble) {
|
|
@@ -12071,7 +12152,8 @@
|
|
|
12071
12152
|
}
|
|
12072
12153
|
const pOpacity = particle.opacity?.value ?? defaultOpacity$1, opacity = calculateBubbleValue(pOpacity, modeOpacity, particle.opacity?.max ?? defaultOpacity$1, ratio);
|
|
12073
12154
|
if (opacity !== undefined) {
|
|
12074
|
-
|
|
12155
|
+
const mod = this.getOrCreateModifier(particle);
|
|
12156
|
+
mod.opacity = opacity;
|
|
12075
12157
|
}
|
|
12076
12158
|
}
|
|
12077
12159
|
#hoverBubbleSize(particle, ratio, divBubble) {
|
|
@@ -12081,7 +12163,8 @@
|
|
|
12081
12163
|
}
|
|
12082
12164
|
const pSize = particle.size.value, size = calculateBubbleValue(pSize, modeSize, particle.size.max, ratio);
|
|
12083
12165
|
if (size !== undefined) {
|
|
12084
|
-
|
|
12166
|
+
const mod = this.getOrCreateModifier(particle);
|
|
12167
|
+
mod.radius = size;
|
|
12085
12168
|
}
|
|
12086
12169
|
}
|
|
12087
12170
|
#process(particle, distMouse, timeSpent, data) {
|
|
@@ -12094,13 +12177,14 @@
|
|
|
12094
12177
|
return;
|
|
12095
12178
|
}
|
|
12096
12179
|
container.bubble ??= {};
|
|
12180
|
+
const mod = this.getOrCreateModifier(particle);
|
|
12097
12181
|
if (container.bubble.durationEnd) {
|
|
12098
12182
|
if (pObjBubble) {
|
|
12099
12183
|
if (type === ProcessBubbleType.size) {
|
|
12100
|
-
|
|
12184
|
+
mod.radius = undefined;
|
|
12101
12185
|
}
|
|
12102
12186
|
if (type === ProcessBubbleType.opacity) {
|
|
12103
|
-
|
|
12187
|
+
mod.opacity = undefined;
|
|
12104
12188
|
}
|
|
12105
12189
|
}
|
|
12106
12190
|
}
|
|
@@ -12110,19 +12194,19 @@
|
|
|
12110
12194
|
if (obj !== bubbleParam) {
|
|
12111
12195
|
const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
|
|
12112
12196
|
if (type === ProcessBubbleType.size) {
|
|
12113
|
-
|
|
12197
|
+
mod.radius = value;
|
|
12114
12198
|
}
|
|
12115
12199
|
if (type === ProcessBubbleType.opacity) {
|
|
12116
|
-
|
|
12200
|
+
mod.opacity = value;
|
|
12117
12201
|
}
|
|
12118
12202
|
}
|
|
12119
12203
|
}
|
|
12120
12204
|
else {
|
|
12121
12205
|
if (type === ProcessBubbleType.size) {
|
|
12122
|
-
|
|
12206
|
+
mod.radius = undefined;
|
|
12123
12207
|
}
|
|
12124
12208
|
if (type === ProcessBubbleType.opacity) {
|
|
12125
|
-
|
|
12209
|
+
mod.opacity = undefined;
|
|
12126
12210
|
}
|
|
12127
12211
|
}
|
|
12128
12212
|
}
|
|
@@ -12143,11 +12227,13 @@
|
|
|
12143
12227
|
if (!area.contains(particle.getPosition())) {
|
|
12144
12228
|
continue;
|
|
12145
12229
|
}
|
|
12146
|
-
|
|
12230
|
+
const mod = this.getOrCreateModifier(particle);
|
|
12231
|
+
mod.enabled = true;
|
|
12232
|
+
mod.inRange = true;
|
|
12147
12233
|
const divs = bubble.divs, divBubble = divMode(divs, elem);
|
|
12148
|
-
if (!
|
|
12234
|
+
if (!mod.div || mod.div !== elem) {
|
|
12149
12235
|
this.clear(particle, delta, true);
|
|
12150
|
-
|
|
12236
|
+
mod.div = elem;
|
|
12151
12237
|
}
|
|
12152
12238
|
this.#hoverBubbleSize(particle, defaultRatio, divBubble);
|
|
12153
12239
|
this.#hoverBubbleOpacity(particle, defaultRatio, divBubble);
|
|
@@ -13081,9 +13167,17 @@
|
|
|
13081
13167
|
}
|
|
13082
13168
|
}
|
|
13083
13169
|
|
|
13170
|
+
class SlowModifier {
|
|
13171
|
+
enabled = false;
|
|
13172
|
+
id = "slow";
|
|
13173
|
+
priority = 100;
|
|
13174
|
+
speedFactor = 1;
|
|
13175
|
+
}
|
|
13176
|
+
|
|
13084
13177
|
const slowMode = "slow", minRadius$3 = 0;
|
|
13085
13178
|
class Slower extends ExternalInteractorBase {
|
|
13086
13179
|
#maxDistance;
|
|
13180
|
+
#modifiers = new WeakMap();
|
|
13087
13181
|
constructor(container) {
|
|
13088
13182
|
super(container);
|
|
13089
13183
|
this.#maxDistance = 0;
|
|
@@ -13092,10 +13186,21 @@
|
|
|
13092
13186
|
return this.#maxDistance;
|
|
13093
13187
|
}
|
|
13094
13188
|
clear(particle, _delta, force) {
|
|
13095
|
-
|
|
13189
|
+
const mod = this.#modifiers.get(particle);
|
|
13190
|
+
if (mod?.enabled && !force) {
|
|
13096
13191
|
return;
|
|
13097
13192
|
}
|
|
13098
|
-
particle.
|
|
13193
|
+
particle.removeModifier(slowMode);
|
|
13194
|
+
this.#modifiers.delete(particle);
|
|
13195
|
+
}
|
|
13196
|
+
getOrCreateModifier(particle) {
|
|
13197
|
+
let mod = this.#modifiers.get(particle);
|
|
13198
|
+
if (!mod) {
|
|
13199
|
+
mod = new SlowModifier();
|
|
13200
|
+
this.#modifiers.set(particle, mod);
|
|
13201
|
+
particle.addModifier(mod);
|
|
13202
|
+
}
|
|
13203
|
+
return mod;
|
|
13099
13204
|
}
|
|
13100
13205
|
init() {
|
|
13101
13206
|
const container = this.container, slow = container.actualOptions.interactivity?.modes.slow;
|
|
@@ -13115,17 +13220,21 @@
|
|
|
13115
13220
|
loadOptionProperty(options, "slow", Slow, ...sources);
|
|
13116
13221
|
}
|
|
13117
13222
|
reset(interactivityData, particle) {
|
|
13118
|
-
|
|
13223
|
+
const mod = this.#modifiers.get(particle);
|
|
13224
|
+
if (mod) {
|
|
13225
|
+
mod.enabled = false;
|
|
13226
|
+
}
|
|
13119
13227
|
const container = this.container, options = container.actualOptions, mousePos = interactivityData.mouse.position, radius = container.retina.slowModeRadius, slowOptions = options.interactivity?.modes.slow;
|
|
13120
13228
|
if (!slowOptions || !radius || radius < minRadius$3 || !mousePos) {
|
|
13121
13229
|
return;
|
|
13122
13230
|
}
|
|
13123
|
-
const particlePos = particle.getPosition(), dist = getDistance(mousePos, particlePos), proximityFactor = dist / radius, slowFactor = slowOptions.factor
|
|
13231
|
+
const particlePos = particle.getPosition(), dist = getDistance(mousePos, particlePos), proximityFactor = dist / radius, slowFactor = slowOptions.factor;
|
|
13124
13232
|
if (dist > radius) {
|
|
13125
13233
|
return;
|
|
13126
13234
|
}
|
|
13127
|
-
|
|
13128
|
-
|
|
13235
|
+
const activeMod = this.getOrCreateModifier(particle);
|
|
13236
|
+
activeMod.enabled = true;
|
|
13237
|
+
activeMod.speedFactor = proximityFactor / slowFactor;
|
|
13129
13238
|
}
|
|
13130
13239
|
}
|
|
13131
13240
|
|
|
@@ -13192,7 +13301,6 @@
|
|
|
13192
13301
|
function replaceImageColor(image, imageData, color, particle, hdr = false) {
|
|
13193
13302
|
const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ?? defaultOpacity, hdr), imageRes = {
|
|
13194
13303
|
color,
|
|
13195
|
-
gif: imageData.gif,
|
|
13196
13304
|
data: {
|
|
13197
13305
|
...image,
|
|
13198
13306
|
svgData: svgColoredData,
|
|
@@ -13227,932 +13335,827 @@
|
|
|
13227
13335
|
});
|
|
13228
13336
|
}
|
|
13229
13337
|
|
|
13230
|
-
const
|
|
13231
|
-
|
|
13232
|
-
|
|
13233
|
-
|
|
13234
|
-
|
|
13235
|
-
|
|
13236
|
-
|
|
13237
|
-
this.pos = 0;
|
|
13238
|
-
this.data = new Uint8ClampedArray(bytes);
|
|
13239
|
-
}
|
|
13240
|
-
getString(count) {
|
|
13241
|
-
const slice = this.data.slice(this.pos, this.pos + count);
|
|
13242
|
-
this.pos += slice.length;
|
|
13243
|
-
return slice.reduce((acc, curr) => acc + String.fromCharCode(curr), "");
|
|
13244
|
-
}
|
|
13245
|
-
nextByte() {
|
|
13246
|
-
return this.data[this.pos++];
|
|
13338
|
+
const sides$3 = 12;
|
|
13339
|
+
class ImageDrawer {
|
|
13340
|
+
#container;
|
|
13341
|
+
#engine;
|
|
13342
|
+
constructor(engine, container) {
|
|
13343
|
+
this.#engine = engine;
|
|
13344
|
+
this.#container = container;
|
|
13247
13345
|
}
|
|
13248
|
-
|
|
13249
|
-
const
|
|
13250
|
-
|
|
13251
|
-
|
|
13346
|
+
draw(data) {
|
|
13347
|
+
const { context, radius, particle, opacity } = data, image = particle.image, element = image?.element;
|
|
13348
|
+
if (!image) {
|
|
13349
|
+
return;
|
|
13350
|
+
}
|
|
13351
|
+
context.globalAlpha = opacity;
|
|
13352
|
+
if (element) {
|
|
13353
|
+
const ratio = image.ratio, pos = {
|
|
13354
|
+
x: -radius,
|
|
13355
|
+
y: -radius,
|
|
13356
|
+
}, diameter = radius * double;
|
|
13357
|
+
context.drawImage(element, pos.x, pos.y, diameter, diameter / ratio);
|
|
13358
|
+
}
|
|
13359
|
+
context.globalAlpha = defaultAlpha$1;
|
|
13252
13360
|
}
|
|
13253
|
-
|
|
13254
|
-
|
|
13255
|
-
const minCount = 0, emptySize = 0;
|
|
13256
|
-
do {
|
|
13257
|
-
size = this.data[this.pos++];
|
|
13258
|
-
for (let count = size; --count >= minCount; blockString += String.fromCharCode(this.data[this.pos++])) {
|
|
13259
|
-
}
|
|
13260
|
-
} while (size !== emptySize);
|
|
13261
|
-
return blockString;
|
|
13361
|
+
getSidesCount() {
|
|
13362
|
+
return sides$3;
|
|
13262
13363
|
}
|
|
13263
|
-
|
|
13264
|
-
|
|
13265
|
-
|
|
13266
|
-
|
|
13267
|
-
len += size;
|
|
13364
|
+
async init(container) {
|
|
13365
|
+
const options = container.actualOptions;
|
|
13366
|
+
if (!options.preload || !this.#engine.loadImage) {
|
|
13367
|
+
return;
|
|
13268
13368
|
}
|
|
13269
|
-
const
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {
|
|
13273
|
-
}
|
|
13369
|
+
const promises = [];
|
|
13370
|
+
for (const imageData of options.preload) {
|
|
13371
|
+
promises.push(this.#engine.loadImage(container, imageData));
|
|
13274
13372
|
}
|
|
13275
|
-
|
|
13373
|
+
await Promise.all(promises);
|
|
13276
13374
|
}
|
|
13277
|
-
|
|
13278
|
-
|
|
13375
|
+
loadShape(particle) {
|
|
13376
|
+
const container = this.#container;
|
|
13377
|
+
if (!particle.shape || !shapeTypes.includes(particle.shape)) {
|
|
13378
|
+
return;
|
|
13279
13379
|
}
|
|
13280
|
-
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
|
|
13285
|
-
|
|
13286
|
-
|
|
13287
|
-
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
DisposalMethod[DisposalMethod["UndefinedA"] = 4] = "UndefinedA";
|
|
13291
|
-
DisposalMethod[DisposalMethod["UndefinedB"] = 5] = "UndefinedB";
|
|
13292
|
-
DisposalMethod[DisposalMethod["UndefinedC"] = 6] = "UndefinedC";
|
|
13293
|
-
DisposalMethod[DisposalMethod["UndefinedD"] = 7] = "UndefinedD";
|
|
13294
|
-
})(DisposalMethod || (DisposalMethod = {}));
|
|
13295
|
-
|
|
13296
|
-
var GIFDataHeaders;
|
|
13297
|
-
(function (GIFDataHeaders) {
|
|
13298
|
-
GIFDataHeaders[GIFDataHeaders["Extension"] = 33] = "Extension";
|
|
13299
|
-
GIFDataHeaders[GIFDataHeaders["ApplicationExtension"] = 255] = "ApplicationExtension";
|
|
13300
|
-
GIFDataHeaders[GIFDataHeaders["GraphicsControlExtension"] = 249] = "GraphicsControlExtension";
|
|
13301
|
-
GIFDataHeaders[GIFDataHeaders["PlainTextExtension"] = 1] = "PlainTextExtension";
|
|
13302
|
-
GIFDataHeaders[GIFDataHeaders["CommentExtension"] = 254] = "CommentExtension";
|
|
13303
|
-
GIFDataHeaders[GIFDataHeaders["Image"] = 44] = "Image";
|
|
13304
|
-
GIFDataHeaders[GIFDataHeaders["EndOfFile"] = 59] = "EndOfFile";
|
|
13305
|
-
})(GIFDataHeaders || (GIFDataHeaders = {}));
|
|
13306
|
-
|
|
13307
|
-
const defaultFrame = 0, initialTime = 0, firstIndex$3 = 0, defaultLoopCount = 0;
|
|
13308
|
-
function parseColorTable(byteStream, count) {
|
|
13309
|
-
const colors = [];
|
|
13310
|
-
for (let i = 0; i < count; i++) {
|
|
13311
|
-
colors.push({
|
|
13312
|
-
r: byteStream.data[byteStream.pos],
|
|
13313
|
-
g: byteStream.data[byteStream.pos + 1],
|
|
13314
|
-
b: byteStream.data[byteStream.pos + 2],
|
|
13380
|
+
const imageData = particle.shapeData;
|
|
13381
|
+
if (!imageData) {
|
|
13382
|
+
return;
|
|
13383
|
+
}
|
|
13384
|
+
const images = this.#engine.getImages?.(container), image = images?.find((t) => t.name === imageData.name || t.source === imageData.src);
|
|
13385
|
+
if (image) {
|
|
13386
|
+
return;
|
|
13387
|
+
}
|
|
13388
|
+
void this.#loadImageShape(container, imageData).then(() => {
|
|
13389
|
+
this.loadShape(particle);
|
|
13315
13390
|
});
|
|
13316
|
-
byteStream.pos += 3;
|
|
13317
13391
|
}
|
|
13318
|
-
|
|
13319
|
-
|
|
13320
|
-
|
|
13321
|
-
switch (byteStream.nextByte()) {
|
|
13322
|
-
case GIFDataHeaders.GraphicsControlExtension: {
|
|
13323
|
-
const frame = gif.frames[getFrameIndex(false)];
|
|
13324
|
-
byteStream.pos++;
|
|
13325
|
-
const packedByte = byteStream.nextByte();
|
|
13326
|
-
frame.GCreserved = (packedByte & 0xe0) >>> 5;
|
|
13327
|
-
frame.disposalMethod = (packedByte & 0x1c) >>> 2;
|
|
13328
|
-
frame.userInputDelayFlag = (packedByte & 2) === 2;
|
|
13329
|
-
const transparencyFlag = (packedByte & 1) === 1;
|
|
13330
|
-
frame.delayTime = byteStream.nextTwoBytes() * 0xa;
|
|
13331
|
-
const transparencyIndex = byteStream.nextByte();
|
|
13332
|
-
if (transparencyFlag) {
|
|
13333
|
-
getTransparencyIndex(transparencyIndex);
|
|
13334
|
-
}
|
|
13335
|
-
byteStream.pos++;
|
|
13336
|
-
break;
|
|
13392
|
+
particleInit(container, particle) {
|
|
13393
|
+
if (particle.shape !== "image" && particle.shape !== "images") {
|
|
13394
|
+
return;
|
|
13337
13395
|
}
|
|
13338
|
-
|
|
13339
|
-
|
|
13340
|
-
|
|
13341
|
-
identifier: byteStream.getString(8),
|
|
13342
|
-
authenticationCode: byteStream.getString(3),
|
|
13343
|
-
data: byteStream.readSubBlocksBin(),
|
|
13344
|
-
};
|
|
13345
|
-
gif.applicationExtensions.push(applicationExtension);
|
|
13346
|
-
break;
|
|
13396
|
+
const images = this.#engine.getImages?.(container), imageData = particle.shapeData;
|
|
13397
|
+
if (!imageData) {
|
|
13398
|
+
return;
|
|
13347
13399
|
}
|
|
13348
|
-
|
|
13349
|
-
|
|
13350
|
-
|
|
13400
|
+
const color = particle.getFillColor(), image = images?.find((t) => t.name === imageData.name || t.source === imageData.src);
|
|
13401
|
+
if (!image) {
|
|
13402
|
+
return;
|
|
13351
13403
|
}
|
|
13352
|
-
|
|
13353
|
-
|
|
13354
|
-
|
|
13404
|
+
const replaceColor = imageData.replaceColor;
|
|
13405
|
+
if (image.loading) {
|
|
13406
|
+
setTimeout(() => {
|
|
13407
|
+
this.particleInit(container, particle);
|
|
13408
|
+
});
|
|
13409
|
+
return;
|
|
13410
|
+
}
|
|
13411
|
+
void (async () => {
|
|
13412
|
+
let imageRes;
|
|
13413
|
+
if (image.svgData && color) {
|
|
13414
|
+
imageRes = await replaceImageColor(image, imageData, color, particle, container.hdr);
|
|
13355
13415
|
}
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
|
|
13365
|
-
}
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13416
|
+
else {
|
|
13417
|
+
imageRes = {
|
|
13418
|
+
color,
|
|
13419
|
+
data: image,
|
|
13420
|
+
element: image.element,
|
|
13421
|
+
loaded: true,
|
|
13422
|
+
ratio: imageData.width && imageData.height ? imageData.width / imageData.height : (image.ratio ?? defaultRatio$1),
|
|
13423
|
+
replaceColor: replaceColor,
|
|
13424
|
+
source: imageData.src,
|
|
13425
|
+
};
|
|
13426
|
+
}
|
|
13427
|
+
if (!imageRes.ratio) {
|
|
13428
|
+
imageRes.ratio = 1;
|
|
13429
|
+
}
|
|
13430
|
+
const close = imageData.close ?? particle.shapeClose, imageShape = {
|
|
13431
|
+
image: imageRes,
|
|
13432
|
+
close,
|
|
13369
13433
|
};
|
|
13370
|
-
|
|
13371
|
-
|
|
13372
|
-
|
|
13373
|
-
byteStream.skipSubBlocks();
|
|
13374
|
-
break;
|
|
13434
|
+
particle.image = imageShape.image;
|
|
13435
|
+
particle.shapeClose = imageShape.close;
|
|
13436
|
+
})();
|
|
13375
13437
|
}
|
|
13438
|
+
#loadImageShape = async (container, imageShape) => {
|
|
13439
|
+
if (!this.#engine.loadImage) {
|
|
13440
|
+
throw new Error(`Image shape not initialized`);
|
|
13441
|
+
}
|
|
13442
|
+
await this.#engine.loadImage(container, {
|
|
13443
|
+
name: imageShape.name,
|
|
13444
|
+
replaceColor: imageShape.replaceColor,
|
|
13445
|
+
src: imageShape.src,
|
|
13446
|
+
});
|
|
13447
|
+
};
|
|
13376
13448
|
}
|
|
13377
|
-
|
|
13378
|
-
|
|
13379
|
-
|
|
13380
|
-
|
|
13381
|
-
|
|
13382
|
-
|
|
13383
|
-
|
|
13384
|
-
|
|
13385
|
-
|
|
13386
|
-
|
|
13387
|
-
frame.width = byteStream.nextTwoBytes();
|
|
13388
|
-
frame.height = byteStream.nextTwoBytes();
|
|
13389
|
-
const packedByte = byteStream.nextByte(), localColorTableFlag = (packedByte & 0x80) === 0x80, interlacedFlag = (packedByte & 0x40) === 0x40;
|
|
13390
|
-
frame.sortFlag = (packedByte & 0x20) === 0x20;
|
|
13391
|
-
frame.reserved = (packedByte & 0x18) >>> 3;
|
|
13392
|
-
const localColorCount = 1 << ((packedByte & 7) + 1);
|
|
13393
|
-
if (localColorTableFlag) {
|
|
13394
|
-
frame.localColorTable = parseColorTable(byteStream, localColorCount);
|
|
13395
|
-
}
|
|
13396
|
-
const getColor = (index) => {
|
|
13397
|
-
const { r, g, b } = (localColorTableFlag ? frame.localColorTable : gif.globalColorTable)[index];
|
|
13398
|
-
if (index !== getTransparencyIndex(null)) {
|
|
13399
|
-
return { r, g, b, a: 255 };
|
|
13449
|
+
|
|
13450
|
+
class Preload {
|
|
13451
|
+
height;
|
|
13452
|
+
name;
|
|
13453
|
+
replaceColor;
|
|
13454
|
+
src = "";
|
|
13455
|
+
width;
|
|
13456
|
+
load(data) {
|
|
13457
|
+
if (isNull(data)) {
|
|
13458
|
+
return;
|
|
13400
13459
|
}
|
|
13401
|
-
|
|
13402
|
-
|
|
13403
|
-
|
|
13404
|
-
|
|
13460
|
+
loadProperty(this, "height", data.height);
|
|
13461
|
+
loadProperty(this, "name", data.name);
|
|
13462
|
+
loadProperty(this, "replaceColor", data.replaceColor);
|
|
13463
|
+
loadProperty(this, "src", data.src);
|
|
13464
|
+
loadProperty(this, "width", data.width);
|
|
13465
|
+
}
|
|
13466
|
+
}
|
|
13467
|
+
|
|
13468
|
+
class ImagePreloaderPlugin {
|
|
13469
|
+
id = "image-preloader";
|
|
13470
|
+
#engine;
|
|
13471
|
+
constructor(engine) {
|
|
13472
|
+
this.#engine = engine;
|
|
13473
|
+
}
|
|
13474
|
+
async getPlugin(container) {
|
|
13475
|
+
const { ImagePreloaderInstance } = await Promise.resolve().then(function () { return ImagePreloaderInstance$1; });
|
|
13476
|
+
return new ImagePreloaderInstance(this.#engine, container);
|
|
13477
|
+
}
|
|
13478
|
+
loadOptions(_container, options, source) {
|
|
13479
|
+
if (!source?.preload) {
|
|
13480
|
+
return;
|
|
13405
13481
|
}
|
|
13406
|
-
|
|
13407
|
-
|
|
13408
|
-
|
|
13482
|
+
options.preload ??= [];
|
|
13483
|
+
const preloadOptions = options.preload;
|
|
13484
|
+
for (const item of source.preload) {
|
|
13485
|
+
const existing = preloadOptions.find(t => t.name === item.name || t.src === item.src);
|
|
13486
|
+
if (existing) {
|
|
13487
|
+
existing.load(item);
|
|
13409
13488
|
}
|
|
13410
|
-
|
|
13411
|
-
|
|
13412
|
-
|
|
13413
|
-
|
|
13414
|
-
throw new EvalError("GIF frame size is to large");
|
|
13415
|
-
}
|
|
13416
|
-
const minCodeSize = byteStream.nextByte(), imageData = byteStream.readSubBlocksBin(), clearCode = 1 << minCodeSize;
|
|
13417
|
-
if (interlacedFlag) {
|
|
13418
|
-
for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {
|
|
13419
|
-
if (InterlaceOffsets[pass] < frame.height) {
|
|
13420
|
-
let pixelPos = 0, lineIndex = 0, exit = false;
|
|
13421
|
-
while (!exit) {
|
|
13422
|
-
const last = code;
|
|
13423
|
-
code = readBits(imageData, pos, size);
|
|
13424
|
-
pos += size + 1;
|
|
13425
|
-
if (code === clearCode) {
|
|
13426
|
-
size = minCodeSize + 1;
|
|
13427
|
-
dic.length = clearCode + 2;
|
|
13428
|
-
for (let i = 0; i < dic.length; i++) {
|
|
13429
|
-
dic[i] = i < clearCode ? [i] : [];
|
|
13430
|
-
}
|
|
13431
|
-
}
|
|
13432
|
-
else {
|
|
13433
|
-
if (code >= dic.length) {
|
|
13434
|
-
dic.push(dic[last].concat(dic[last][0]));
|
|
13435
|
-
}
|
|
13436
|
-
else if (last !== clearCode) {
|
|
13437
|
-
dic.push(dic[last].concat(dic[code][0]));
|
|
13438
|
-
}
|
|
13439
|
-
for (const item of dic[code]) {
|
|
13440
|
-
const { r, g, b, a } = getColor(item);
|
|
13441
|
-
image.data.set([r, g, b, a], InterlaceOffsets[pass] * frame.width +
|
|
13442
|
-
InterlaceSteps[pass] * lineIndex +
|
|
13443
|
-
(pixelPos % (frame.width * 4)));
|
|
13444
|
-
pixelPos += 4;
|
|
13445
|
-
}
|
|
13446
|
-
if (dic.length === 1 << size && size < 0xc) {
|
|
13447
|
-
size++;
|
|
13448
|
-
}
|
|
13449
|
-
}
|
|
13450
|
-
if (pixelPos === frame.width * 4 * (lineIndex + 1)) {
|
|
13451
|
-
lineIndex++;
|
|
13452
|
-
if (InterlaceOffsets[pass] + InterlaceSteps[pass] * lineIndex >= frame.height) {
|
|
13453
|
-
exit = true;
|
|
13454
|
-
}
|
|
13455
|
-
}
|
|
13456
|
-
}
|
|
13489
|
+
else {
|
|
13490
|
+
const preload = new Preload();
|
|
13491
|
+
preload.load(item);
|
|
13492
|
+
preloadOptions.push(preload);
|
|
13457
13493
|
}
|
|
13458
13494
|
}
|
|
13459
|
-
frame.image = image;
|
|
13460
|
-
frame.bitmap = await createImageBitmap(image);
|
|
13461
13495
|
}
|
|
13462
|
-
|
|
13463
|
-
|
|
13464
|
-
|
|
13465
|
-
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
|
|
13474
|
-
|
|
13496
|
+
needsPlugin() {
|
|
13497
|
+
return true;
|
|
13498
|
+
}
|
|
13499
|
+
}
|
|
13500
|
+
|
|
13501
|
+
const extLength = 3;
|
|
13502
|
+
function addLoadImageToEngine(engine) {
|
|
13503
|
+
engine.getImages ??= (container) => {
|
|
13504
|
+
engine.images ??= new Map();
|
|
13505
|
+
let images = engine.images.get(container);
|
|
13506
|
+
if (!images) {
|
|
13507
|
+
images = [];
|
|
13508
|
+
engine.images.set(container, images);
|
|
13509
|
+
}
|
|
13510
|
+
return images;
|
|
13511
|
+
};
|
|
13512
|
+
engine.loadImage ??= async (container, data) => {
|
|
13513
|
+
if (!engine.getImages) {
|
|
13514
|
+
throw new Error("No images collection found");
|
|
13515
|
+
}
|
|
13516
|
+
if (!data.name && !data.src) {
|
|
13517
|
+
throw new Error("No image source provided");
|
|
13518
|
+
}
|
|
13519
|
+
engine.images ??= new Map();
|
|
13520
|
+
const containerImages = engine.getImages(container);
|
|
13521
|
+
if (containerImages.some((t) => t.name === data.name || t.source === data.src)) {
|
|
13522
|
+
return;
|
|
13523
|
+
}
|
|
13524
|
+
try {
|
|
13525
|
+
const image = {
|
|
13526
|
+
name: data.name ?? data.src,
|
|
13527
|
+
source: data.src,
|
|
13528
|
+
type: data.src.substring(data.src.length - extLength),
|
|
13529
|
+
error: false,
|
|
13530
|
+
loading: true,
|
|
13531
|
+
replaceColor: data.replaceColor,
|
|
13532
|
+
ratio: data.width && data.height ? data.width / data.height : undefined,
|
|
13533
|
+
};
|
|
13534
|
+
containerImages.push(image);
|
|
13535
|
+
engine.images.set(container, containerImages);
|
|
13536
|
+
let imageFunc;
|
|
13537
|
+
if (data.replaceColor) {
|
|
13538
|
+
imageFunc = downloadSvgImage;
|
|
13475
13539
|
}
|
|
13476
13540
|
else {
|
|
13477
|
-
|
|
13478
|
-
break;
|
|
13479
|
-
}
|
|
13480
|
-
if (code >= dic.length) {
|
|
13481
|
-
dic.push(dic[last].concat(dic[last][0]));
|
|
13482
|
-
}
|
|
13483
|
-
else if (last !== clearCode) {
|
|
13484
|
-
dic.push(dic[last].concat(dic[code][0]));
|
|
13485
|
-
}
|
|
13486
|
-
for (const item of dic[code]) {
|
|
13487
|
-
const { r, g, b, a } = getColor(item);
|
|
13488
|
-
pixelPos += 4;
|
|
13489
|
-
image.data.set([r, g, b, a], pixelPos);
|
|
13490
|
-
}
|
|
13491
|
-
if (dic.length >= 1 << size && size < 0xc) {
|
|
13492
|
-
size++;
|
|
13493
|
-
}
|
|
13541
|
+
imageFunc = loadImage;
|
|
13494
13542
|
}
|
|
13543
|
+
await imageFunc(image);
|
|
13495
13544
|
}
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
|
|
13545
|
+
catch {
|
|
13546
|
+
throw new Error(`${data.name ?? data.src} not found`);
|
|
13547
|
+
}
|
|
13548
|
+
};
|
|
13499
13549
|
}
|
|
13500
|
-
async function
|
|
13501
|
-
|
|
13502
|
-
|
|
13503
|
-
|
|
13504
|
-
|
|
13505
|
-
|
|
13506
|
-
|
|
13507
|
-
case GIFDataHeaders.Extension:
|
|
13508
|
-
parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
|
|
13509
|
-
break;
|
|
13510
|
-
default:
|
|
13511
|
-
throw new EvalError("undefined block found");
|
|
13512
|
-
}
|
|
13513
|
-
return false;
|
|
13550
|
+
async function loadImageShape(engine) {
|
|
13551
|
+
engine.checkVersion("4.2.1");
|
|
13552
|
+
await engine.pluginManager.register(e => {
|
|
13553
|
+
addLoadImageToEngine(e);
|
|
13554
|
+
e.pluginManager.addPlugin(new ImagePreloaderPlugin(e));
|
|
13555
|
+
e.pluginManager.addShape(shapeTypes, container => Promise.resolve(new ImageDrawer(e, container)));
|
|
13556
|
+
});
|
|
13514
13557
|
}
|
|
13515
|
-
|
|
13516
|
-
|
|
13517
|
-
|
|
13518
|
-
|
|
13558
|
+
|
|
13559
|
+
class LifeDelay extends ValueWithRandom {
|
|
13560
|
+
sync = false;
|
|
13561
|
+
load(data) {
|
|
13562
|
+
if (isNull(data)) {
|
|
13563
|
+
return;
|
|
13519
13564
|
}
|
|
13520
|
-
|
|
13565
|
+
super.load(data);
|
|
13566
|
+
loadProperty(this, "sync", data.sync);
|
|
13521
13567
|
}
|
|
13522
|
-
return Number.NaN;
|
|
13523
13568
|
}
|
|
13524
|
-
|
|
13525
|
-
|
|
13526
|
-
|
|
13527
|
-
|
|
13528
|
-
|
|
13569
|
+
|
|
13570
|
+
class LifeDuration extends ValueWithRandom {
|
|
13571
|
+
sync = false;
|
|
13572
|
+
load(data) {
|
|
13573
|
+
if (isNull(data)) {
|
|
13574
|
+
return;
|
|
13575
|
+
}
|
|
13576
|
+
super.load(data);
|
|
13577
|
+
loadProperty(this, "sync", data.sync);
|
|
13529
13578
|
}
|
|
13530
|
-
|
|
13531
|
-
|
|
13532
|
-
|
|
13533
|
-
|
|
13534
|
-
|
|
13535
|
-
|
|
13536
|
-
|
|
13537
|
-
|
|
13538
|
-
|
|
13539
|
-
backgroundImage: new ImageData(1, 1, canvasSettings),
|
|
13540
|
-
comments: [],
|
|
13541
|
-
applicationExtensions: [],
|
|
13542
|
-
}, byteStream = new ByteStream(new Uint8ClampedArray(buffer));
|
|
13543
|
-
if (byteStream.getString(6) !== "GIF89a") {
|
|
13544
|
-
throw new Error("not a supported GIF file");
|
|
13545
|
-
}
|
|
13546
|
-
gif.width = byteStream.nextTwoBytes();
|
|
13547
|
-
gif.height = byteStream.nextTwoBytes();
|
|
13548
|
-
const packedByte = byteStream.nextByte(), globalColorTableFlag = (packedByte & 0x80) === 0x80;
|
|
13549
|
-
gif.colorRes = (packedByte & 0x70) >>> 4;
|
|
13550
|
-
gif.sortFlag = (packedByte & 8) === 8;
|
|
13551
|
-
const globalColorCount = 1 << ((packedByte & 7) + 1), backgroundColorIndex = byteStream.nextByte();
|
|
13552
|
-
gif.pixelAspectRatio = byteStream.nextByte();
|
|
13553
|
-
if (gif.pixelAspectRatio !== 0) {
|
|
13554
|
-
gif.pixelAspectRatio = (gif.pixelAspectRatio + 0xf) / 0x40;
|
|
13555
|
-
}
|
|
13556
|
-
if (globalColorTableFlag) {
|
|
13557
|
-
gif.globalColorTable = parseColorTable(byteStream, globalColorCount);
|
|
13558
|
-
}
|
|
13559
|
-
const backgroundImage = (() => {
|
|
13560
|
-
try {
|
|
13561
|
-
return new ImageData(gif.width, gif.height, canvasSettings);
|
|
13562
|
-
}
|
|
13563
|
-
catch (error) {
|
|
13564
|
-
if (error instanceof DOMException && error.name === "IndexSizeError") {
|
|
13565
|
-
return null;
|
|
13566
|
-
}
|
|
13567
|
-
throw error;
|
|
13579
|
+
}
|
|
13580
|
+
|
|
13581
|
+
class Life {
|
|
13582
|
+
count = 0;
|
|
13583
|
+
delay = new LifeDelay();
|
|
13584
|
+
duration = new LifeDuration();
|
|
13585
|
+
load(data) {
|
|
13586
|
+
if (isNull(data)) {
|
|
13587
|
+
return;
|
|
13568
13588
|
}
|
|
13569
|
-
|
|
13570
|
-
|
|
13571
|
-
|
|
13589
|
+
loadProperty(this, "count", data.count);
|
|
13590
|
+
this.delay.load(data.delay);
|
|
13591
|
+
this.duration.load(data.duration);
|
|
13572
13592
|
}
|
|
13573
|
-
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13593
|
+
}
|
|
13594
|
+
|
|
13595
|
+
const noTime$1 = 0, infiniteValue$1 = -1, noLife = 0, minCanvasSize = 0;
|
|
13596
|
+
function updateLife(particle, delta, canvasSize) {
|
|
13597
|
+
if (!particle.life) {
|
|
13598
|
+
return;
|
|
13577
13599
|
}
|
|
13578
|
-
|
|
13579
|
-
let
|
|
13580
|
-
|
|
13581
|
-
|
|
13582
|
-
|
|
13583
|
-
|
|
13584
|
-
|
|
13585
|
-
|
|
13586
|
-
|
|
13587
|
-
transparencyIndex = newValue;
|
|
13588
|
-
}
|
|
13589
|
-
return transparencyIndex;
|
|
13590
|
-
};
|
|
13591
|
-
try {
|
|
13592
|
-
do {
|
|
13593
|
-
if (incrementFrameIndex) {
|
|
13594
|
-
gif.frames.push({
|
|
13595
|
-
left: 0,
|
|
13596
|
-
top: 0,
|
|
13597
|
-
width: 0,
|
|
13598
|
-
height: 0,
|
|
13599
|
-
disposalMethod: DisposalMethod.Replace,
|
|
13600
|
-
image: new ImageData(1, 1, canvasSettings),
|
|
13601
|
-
plainTextData: null,
|
|
13602
|
-
userInputDelayFlag: false,
|
|
13603
|
-
delayTime: 0,
|
|
13604
|
-
sortFlag: false,
|
|
13605
|
-
localColorTable: [],
|
|
13606
|
-
reserved: 0,
|
|
13607
|
-
GCreserved: 0,
|
|
13608
|
-
});
|
|
13609
|
-
frameIndex++;
|
|
13610
|
-
transparencyIndex = -1;
|
|
13611
|
-
incrementFrameIndex = false;
|
|
13612
|
-
}
|
|
13613
|
-
} while (!(await parseBlock(byteStream, gif, avgAlpha, getframeIndex, getTransparencyIndex, canvasSettings, progressCallback)));
|
|
13614
|
-
gif.frames.length--;
|
|
13615
|
-
for (const frame of gif.frames) {
|
|
13616
|
-
if (frame.userInputDelayFlag && frame.delayTime === 0) {
|
|
13617
|
-
gif.totalTime = Infinity;
|
|
13618
|
-
break;
|
|
13619
|
-
}
|
|
13620
|
-
gif.totalTime += frame.delayTime;
|
|
13600
|
+
const life = particle.life;
|
|
13601
|
+
let justSpawned = false;
|
|
13602
|
+
if (particle.spawning) {
|
|
13603
|
+
life.delayTime += delta.value;
|
|
13604
|
+
if (life.delayTime >= particle.life.delay) {
|
|
13605
|
+
justSpawned = true;
|
|
13606
|
+
particle.spawning = false;
|
|
13607
|
+
life.delayTime = noTime$1;
|
|
13608
|
+
life.time = noTime$1;
|
|
13621
13609
|
}
|
|
13622
|
-
|
|
13623
|
-
|
|
13624
|
-
catch (error) {
|
|
13625
|
-
if (error instanceof EvalError) {
|
|
13626
|
-
throw new Error(`error while parsing frame ${frameIndex.toString()} "${error.message}"`, { cause: error });
|
|
13610
|
+
else {
|
|
13611
|
+
return;
|
|
13627
13612
|
}
|
|
13628
|
-
throw error;
|
|
13629
13613
|
}
|
|
13630
|
-
|
|
13631
|
-
function drawGif(data, canvasSettings) {
|
|
13632
|
-
const { context, radius, particle, delta } = data, image = particle.image;
|
|
13633
|
-
if (!image?.gifData || !image.gif) {
|
|
13614
|
+
if (life.duration === infiniteValue$1) {
|
|
13634
13615
|
return;
|
|
13635
13616
|
}
|
|
13636
|
-
|
|
13637
|
-
|
|
13638
|
-
throw new Error("could not create offscreen canvas context");
|
|
13617
|
+
if (justSpawned) {
|
|
13618
|
+
life.time = noTime$1;
|
|
13639
13619
|
}
|
|
13640
|
-
|
|
13641
|
-
|
|
13642
|
-
offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
13643
|
-
particle.gifLoopCount ??= image.gifLoopCount ?? defaultLoopCount;
|
|
13644
|
-
let frameIndex = particle.gifFrame ?? defaultFrame;
|
|
13645
|
-
const pos = { x: -image.gifData.width * half$2, y: -image.gifData.height * half$2 }, frame = image.gifData.frames[frameIndex];
|
|
13646
|
-
particle.gifTime ??= initialTime;
|
|
13647
|
-
if (!frame.bitmap) {
|
|
13648
|
-
return;
|
|
13620
|
+
else {
|
|
13621
|
+
life.time += delta.value;
|
|
13649
13622
|
}
|
|
13650
|
-
|
|
13651
|
-
|
|
13652
|
-
case DisposalMethod.UndefinedA:
|
|
13653
|
-
case DisposalMethod.UndefinedB:
|
|
13654
|
-
case DisposalMethod.UndefinedC:
|
|
13655
|
-
case DisposalMethod.UndefinedD:
|
|
13656
|
-
case DisposalMethod.Replace:
|
|
13657
|
-
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
13658
|
-
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
13659
|
-
offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
13660
|
-
break;
|
|
13661
|
-
case DisposalMethod.Combine:
|
|
13662
|
-
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
13663
|
-
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
13664
|
-
break;
|
|
13665
|
-
case DisposalMethod.RestoreBackground:
|
|
13666
|
-
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
13667
|
-
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
13668
|
-
offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
13669
|
-
if (!image.gifData.globalColorTable.length) {
|
|
13670
|
-
offscreenContext.putImageData(image.gifData.frames[firstIndex$3].image, pos.x + frame.left, pos.y + frame.top);
|
|
13671
|
-
}
|
|
13672
|
-
else {
|
|
13673
|
-
offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);
|
|
13674
|
-
}
|
|
13675
|
-
break;
|
|
13676
|
-
case DisposalMethod.RestorePrevious:
|
|
13677
|
-
{
|
|
13678
|
-
const previousImageData = offscreenContext.getImageData(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
13679
|
-
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
13680
|
-
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
13681
|
-
offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
13682
|
-
offscreenContext.putImageData(previousImageData, originPoint.x, originPoint.y);
|
|
13683
|
-
}
|
|
13684
|
-
break;
|
|
13623
|
+
if (life.time < life.duration) {
|
|
13624
|
+
return;
|
|
13685
13625
|
}
|
|
13686
|
-
|
|
13687
|
-
if (particle.
|
|
13688
|
-
particle.
|
|
13689
|
-
if (++frameIndex >= image.gifData.frames.length) {
|
|
13690
|
-
if (--particle.gifLoopCount <= defaultLoopCount) {
|
|
13691
|
-
return;
|
|
13692
|
-
}
|
|
13693
|
-
frameIndex = firstIndex$3;
|
|
13694
|
-
offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
13695
|
-
}
|
|
13696
|
-
particle.gifFrame = frameIndex;
|
|
13626
|
+
life.time = noTime$1;
|
|
13627
|
+
if (particle.life.count > noLife) {
|
|
13628
|
+
particle.life.count--;
|
|
13697
13629
|
}
|
|
13698
|
-
|
|
13699
|
-
|
|
13700
|
-
async function loadGifImage(image, canvasSettings) {
|
|
13701
|
-
if (image.type !== "gif") {
|
|
13702
|
-
await loadImage(image);
|
|
13630
|
+
if (particle.life.count === noLife) {
|
|
13631
|
+
particle.destroy();
|
|
13703
13632
|
return;
|
|
13704
13633
|
}
|
|
13705
|
-
|
|
13706
|
-
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
13710
|
-
|
|
13711
|
-
|
|
13712
|
-
|
|
13713
|
-
|
|
13714
|
-
|
|
13634
|
+
const widthRange = setRangeValue(minCanvasSize, canvasSize.width), heightRange = setRangeValue(minCanvasSize, canvasSize.width);
|
|
13635
|
+
particle.position.x = randomInRangeValue(widthRange);
|
|
13636
|
+
particle.position.y = randomInRangeValue(heightRange);
|
|
13637
|
+
particle.spawning = true;
|
|
13638
|
+
life.delayTime = noTime$1;
|
|
13639
|
+
life.time = noTime$1;
|
|
13640
|
+
particle.reset();
|
|
13641
|
+
const lifeOptions = particle.options.life;
|
|
13642
|
+
if (lifeOptions) {
|
|
13643
|
+
life.delay = getRangeValue(lifeOptions.delay.value) * millisecondsToSeconds$1;
|
|
13644
|
+
life.duration = getRangeValue(lifeOptions.duration.value) * millisecondsToSeconds$1;
|
|
13715
13645
|
}
|
|
13716
|
-
image.loading = false;
|
|
13717
13646
|
}
|
|
13718
13647
|
|
|
13719
|
-
const
|
|
13720
|
-
class
|
|
13648
|
+
const noTime = 0, identity$2 = 1, infiniteValue = -1;
|
|
13649
|
+
class LifeUpdater {
|
|
13721
13650
|
#container;
|
|
13722
|
-
|
|
13723
|
-
constructor(engine, container) {
|
|
13724
|
-
this.#engine = engine;
|
|
13651
|
+
constructor(container) {
|
|
13725
13652
|
this.#container = container;
|
|
13726
13653
|
}
|
|
13727
|
-
|
|
13728
|
-
const
|
|
13729
|
-
if (!
|
|
13654
|
+
init(particle) {
|
|
13655
|
+
const container = this.#container, particlesOptions = particle.options, lifeOptions = particlesOptions.life;
|
|
13656
|
+
if (!lifeOptions) {
|
|
13730
13657
|
return;
|
|
13731
13658
|
}
|
|
13732
|
-
|
|
13733
|
-
|
|
13734
|
-
|
|
13659
|
+
const delayFactor = lifeOptions.delay.sync ? identity$2 : getRandom(), durationFactor = lifeOptions.duration.sync ? identity$2 : getRandom();
|
|
13660
|
+
particle.life = {
|
|
13661
|
+
delay: container.retina.reduceFactor
|
|
13662
|
+
? ((getRangeValue(lifeOptions.delay.value) * delayFactor) / container.retina.reduceFactor) *
|
|
13663
|
+
millisecondsToSeconds$1
|
|
13664
|
+
: noTime,
|
|
13665
|
+
delayTime: noTime,
|
|
13666
|
+
duration: container.retina.reduceFactor
|
|
13667
|
+
? ((getRangeValue(lifeOptions.duration.value) * durationFactor) / container.retina.reduceFactor) *
|
|
13668
|
+
millisecondsToSeconds$1
|
|
13669
|
+
: noTime,
|
|
13670
|
+
time: noTime,
|
|
13671
|
+
count: lifeOptions.count,
|
|
13672
|
+
};
|
|
13673
|
+
if (particle.life.duration <= noTime) {
|
|
13674
|
+
particle.life.duration = infiniteValue;
|
|
13735
13675
|
}
|
|
13736
|
-
|
|
13737
|
-
|
|
13738
|
-
x: -radius,
|
|
13739
|
-
y: -radius,
|
|
13740
|
-
}, diameter = radius * double;
|
|
13741
|
-
context.drawImage(element, pos.x, pos.y, diameter, diameter / ratio);
|
|
13676
|
+
if (particle.life.count <= noTime) {
|
|
13677
|
+
particle.life.count = infiniteValue;
|
|
13742
13678
|
}
|
|
13743
|
-
|
|
13679
|
+
particle.spawning = particle.life.delay > noTime;
|
|
13744
13680
|
}
|
|
13745
|
-
|
|
13746
|
-
return
|
|
13681
|
+
isEnabled(particle) {
|
|
13682
|
+
return !particle.destroyed;
|
|
13747
13683
|
}
|
|
13748
|
-
|
|
13749
|
-
|
|
13750
|
-
|
|
13684
|
+
loadOptions(options, ...sources) {
|
|
13685
|
+
loadOptionProperty(options, "life", Life, ...sources);
|
|
13686
|
+
}
|
|
13687
|
+
update(particle, delta) {
|
|
13688
|
+
if (!this.isEnabled(particle) || !particle.life) {
|
|
13751
13689
|
return;
|
|
13752
13690
|
}
|
|
13753
|
-
|
|
13754
|
-
for (const imageData of options.preload) {
|
|
13755
|
-
promises.push(this.#engine.loadImage(container, imageData));
|
|
13756
|
-
}
|
|
13757
|
-
await Promise.all(promises);
|
|
13691
|
+
updateLife(particle, delta, this.#container.canvas.size);
|
|
13758
13692
|
}
|
|
13759
|
-
|
|
13760
|
-
|
|
13761
|
-
|
|
13762
|
-
|
|
13763
|
-
|
|
13764
|
-
|
|
13765
|
-
|
|
13766
|
-
return;
|
|
13767
|
-
}
|
|
13768
|
-
const images = this.#engine.getImages?.(container), image = images?.find((t) => t.name === imageData.name || t.source === imageData.src);
|
|
13769
|
-
if (image) {
|
|
13770
|
-
return;
|
|
13771
|
-
}
|
|
13772
|
-
void this.#loadImageShape(container, imageData).then(() => {
|
|
13773
|
-
this.loadShape(particle);
|
|
13693
|
+
}
|
|
13694
|
+
|
|
13695
|
+
async function loadLifeUpdater(engine) {
|
|
13696
|
+
engine.checkVersion("4.2.1");
|
|
13697
|
+
await engine.pluginManager.register(e => {
|
|
13698
|
+
e.pluginManager.addParticleUpdater("life", container => {
|
|
13699
|
+
return Promise.resolve(new LifeUpdater(container));
|
|
13774
13700
|
});
|
|
13701
|
+
});
|
|
13702
|
+
}
|
|
13703
|
+
|
|
13704
|
+
function drawLine(data) {
|
|
13705
|
+
const { context, particle, radius } = data, shapeData = particle.shapeData, centerY = 0;
|
|
13706
|
+
context.moveTo(-radius, centerY);
|
|
13707
|
+
context.lineTo(radius, centerY);
|
|
13708
|
+
context.lineCap = shapeData?.cap ?? "butt";
|
|
13709
|
+
}
|
|
13710
|
+
|
|
13711
|
+
const sides$2 = 1;
|
|
13712
|
+
class LineDrawer {
|
|
13713
|
+
draw(data) {
|
|
13714
|
+
drawLine(data);
|
|
13775
13715
|
}
|
|
13776
|
-
|
|
13777
|
-
|
|
13778
|
-
return;
|
|
13779
|
-
}
|
|
13780
|
-
const images = this.#engine.getImages?.(container), imageData = particle.shapeData;
|
|
13781
|
-
if (!imageData) {
|
|
13782
|
-
return;
|
|
13783
|
-
}
|
|
13784
|
-
const color = particle.getFillColor(), image = images?.find((t) => t.name === imageData.name || t.source === imageData.src);
|
|
13785
|
-
if (!image) {
|
|
13786
|
-
return;
|
|
13787
|
-
}
|
|
13788
|
-
const replaceColor = imageData.replaceColor;
|
|
13789
|
-
if (image.loading) {
|
|
13790
|
-
setTimeout(() => {
|
|
13791
|
-
this.particleInit(container, particle);
|
|
13792
|
-
});
|
|
13793
|
-
return;
|
|
13794
|
-
}
|
|
13795
|
-
void (async () => {
|
|
13796
|
-
let imageRes;
|
|
13797
|
-
if (image.svgData && color) {
|
|
13798
|
-
imageRes = await replaceImageColor(image, imageData, color, particle, container.hdr);
|
|
13799
|
-
}
|
|
13800
|
-
else {
|
|
13801
|
-
imageRes = {
|
|
13802
|
-
color,
|
|
13803
|
-
data: image,
|
|
13804
|
-
element: image.element,
|
|
13805
|
-
gif: image.gif,
|
|
13806
|
-
gifData: image.gifData,
|
|
13807
|
-
gifLoopCount: image.gifLoopCount,
|
|
13808
|
-
loaded: true,
|
|
13809
|
-
ratio: imageData.width && imageData.height ? imageData.width / imageData.height : (image.ratio ?? defaultRatio$1),
|
|
13810
|
-
replaceColor: replaceColor,
|
|
13811
|
-
source: imageData.src,
|
|
13812
|
-
};
|
|
13813
|
-
}
|
|
13814
|
-
if (!imageRes.ratio) {
|
|
13815
|
-
imageRes.ratio = 1;
|
|
13816
|
-
}
|
|
13817
|
-
const close = imageData.close ?? particle.shapeClose, imageShape = {
|
|
13818
|
-
image: imageRes,
|
|
13819
|
-
close,
|
|
13820
|
-
};
|
|
13821
|
-
particle.image = imageShape.image;
|
|
13822
|
-
particle.shapeClose = imageShape.close;
|
|
13823
|
-
})();
|
|
13716
|
+
getSidesCount() {
|
|
13717
|
+
return sides$2;
|
|
13824
13718
|
}
|
|
13825
|
-
#loadImageShape = async (container, imageShape) => {
|
|
13826
|
-
if (!this.#engine.loadImage) {
|
|
13827
|
-
throw new Error(`Image shape not initialized`);
|
|
13828
|
-
}
|
|
13829
|
-
await this.#engine.loadImage(container, {
|
|
13830
|
-
gif: imageShape.gif,
|
|
13831
|
-
name: imageShape.name,
|
|
13832
|
-
replaceColor: imageShape.replaceColor,
|
|
13833
|
-
src: imageShape.src,
|
|
13834
|
-
});
|
|
13835
|
-
};
|
|
13836
13719
|
}
|
|
13837
13720
|
|
|
13838
|
-
|
|
13839
|
-
|
|
13840
|
-
|
|
13841
|
-
|
|
13842
|
-
|
|
13843
|
-
|
|
13844
|
-
|
|
13721
|
+
async function loadLineShape(engine) {
|
|
13722
|
+
engine.checkVersion("4.2.1");
|
|
13723
|
+
await engine.pluginManager.register(e => {
|
|
13724
|
+
e.pluginManager.addShape(["line"], () => Promise.resolve(new LineDrawer()));
|
|
13725
|
+
});
|
|
13726
|
+
}
|
|
13727
|
+
|
|
13728
|
+
class Attract {
|
|
13729
|
+
distance = 200;
|
|
13730
|
+
enable = false;
|
|
13731
|
+
rotate;
|
|
13732
|
+
constructor() {
|
|
13733
|
+
this.rotate = {
|
|
13734
|
+
x: 3000,
|
|
13735
|
+
y: 3000,
|
|
13736
|
+
};
|
|
13737
|
+
}
|
|
13845
13738
|
load(data) {
|
|
13846
13739
|
if (isNull(data)) {
|
|
13847
13740
|
return;
|
|
13848
13741
|
}
|
|
13849
|
-
|
|
13850
|
-
loadProperty(this, "
|
|
13851
|
-
|
|
13852
|
-
|
|
13853
|
-
|
|
13854
|
-
|
|
13742
|
+
loadRangeProperty(this, "distance", data.distance);
|
|
13743
|
+
loadProperty(this, "enable", data.enable);
|
|
13744
|
+
if (data.rotate) {
|
|
13745
|
+
const rotateX = data.rotate.x;
|
|
13746
|
+
if (rotateX !== undefined) {
|
|
13747
|
+
this.rotate.x = rotateX;
|
|
13748
|
+
}
|
|
13749
|
+
const rotateY = data.rotate.y;
|
|
13750
|
+
if (rotateY !== undefined) {
|
|
13751
|
+
this.rotate.y = rotateY;
|
|
13752
|
+
}
|
|
13753
|
+
}
|
|
13855
13754
|
}
|
|
13856
13755
|
}
|
|
13857
13756
|
|
|
13858
|
-
|
|
13859
|
-
|
|
13860
|
-
#
|
|
13861
|
-
constructor(
|
|
13862
|
-
|
|
13757
|
+
const attractFactor = 1000, identity$1 = 1;
|
|
13758
|
+
class Attractor extends ParticlesInteractorBase {
|
|
13759
|
+
#maxDistance;
|
|
13760
|
+
constructor(container) {
|
|
13761
|
+
super(container);
|
|
13762
|
+
this.#maxDistance = 0;
|
|
13863
13763
|
}
|
|
13864
|
-
|
|
13865
|
-
|
|
13866
|
-
return new ImagePreloaderInstance(this.#engine, container);
|
|
13764
|
+
get maxDistance() {
|
|
13765
|
+
return this.#maxDistance;
|
|
13867
13766
|
}
|
|
13868
|
-
|
|
13869
|
-
|
|
13767
|
+
clear() {
|
|
13768
|
+
}
|
|
13769
|
+
init() {
|
|
13770
|
+
}
|
|
13771
|
+
interact(p1) {
|
|
13772
|
+
if (!p1.options.attract?.enable) {
|
|
13870
13773
|
return;
|
|
13871
13774
|
}
|
|
13872
|
-
|
|
13873
|
-
|
|
13874
|
-
|
|
13875
|
-
|
|
13876
|
-
|
|
13877
|
-
existing.load(item);
|
|
13775
|
+
const container = this.container;
|
|
13776
|
+
if (isNull(p1.attractDistance)) {
|
|
13777
|
+
const attractDistance = getRangeValue(p1.options.attract.distance);
|
|
13778
|
+
if (attractDistance > this.#maxDistance) {
|
|
13779
|
+
this.#maxDistance = attractDistance;
|
|
13878
13780
|
}
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
|
|
13882
|
-
|
|
13781
|
+
p1.attractDistance = attractDistance * container.retina.pixelRatio;
|
|
13782
|
+
}
|
|
13783
|
+
const distance = p1.attractDistance, pos1 = p1.getPosition(), query = container.particles.grid.queryCircle(pos1, distance);
|
|
13784
|
+
for (const p2 of query) {
|
|
13785
|
+
if (p1 === p2 || !p2.options.attract?.enable || p2.destroyed || p2.spawning) {
|
|
13786
|
+
continue;
|
|
13883
13787
|
}
|
|
13788
|
+
const pos2 = p2.getPosition(), { dx, dy } = getDistances(pos1, pos2), rotate = p1.options.attract.rotate, ax = dx / (rotate.x * attractFactor), ay = dy / (rotate.y * attractFactor), p1Factor = p2.size.value / p1.size.value, p2Factor = identity$1 / p1Factor;
|
|
13789
|
+
p1.velocity.x -= ax * p1Factor;
|
|
13790
|
+
p1.velocity.y -= ay * p1Factor;
|
|
13791
|
+
p2.velocity.x += ax * p2Factor;
|
|
13792
|
+
p2.velocity.y += ay * p2Factor;
|
|
13884
13793
|
}
|
|
13885
13794
|
}
|
|
13886
|
-
|
|
13887
|
-
return
|
|
13795
|
+
isEnabled(particle) {
|
|
13796
|
+
return particle.options.attract?.enable ?? false;
|
|
13797
|
+
}
|
|
13798
|
+
loadParticlesOptions(options, ...sources) {
|
|
13799
|
+
loadOptionProperty(options, "attract", Attract, ...sources);
|
|
13800
|
+
}
|
|
13801
|
+
reset() {
|
|
13888
13802
|
}
|
|
13889
13803
|
}
|
|
13890
13804
|
|
|
13891
|
-
|
|
13892
|
-
|
|
13893
|
-
engine.
|
|
13894
|
-
|
|
13895
|
-
|
|
13896
|
-
|
|
13897
|
-
|
|
13898
|
-
|
|
13899
|
-
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
|
|
13907
|
-
|
|
13805
|
+
async function loadParticlesAttractInteraction(engine) {
|
|
13806
|
+
engine.checkVersion("4.2.1");
|
|
13807
|
+
await engine.pluginManager.register((e) => {
|
|
13808
|
+
ensureInteractivityPluginLoaded(e);
|
|
13809
|
+
e.pluginManager.addInteractor?.("particlesAttract", container => {
|
|
13810
|
+
return Promise.resolve(new Attractor(container));
|
|
13811
|
+
});
|
|
13812
|
+
});
|
|
13813
|
+
}
|
|
13814
|
+
|
|
13815
|
+
var CollisionMode;
|
|
13816
|
+
(function (CollisionMode) {
|
|
13817
|
+
CollisionMode["absorb"] = "absorb";
|
|
13818
|
+
CollisionMode["bounce"] = "bounce";
|
|
13819
|
+
CollisionMode["destroy"] = "destroy";
|
|
13820
|
+
})(CollisionMode || (CollisionMode = {}));
|
|
13821
|
+
|
|
13822
|
+
class CollisionsAbsorb {
|
|
13823
|
+
speed = 2;
|
|
13824
|
+
load(data) {
|
|
13825
|
+
if (isNull(data)) {
|
|
13826
|
+
return;
|
|
13908
13827
|
}
|
|
13909
|
-
|
|
13910
|
-
|
|
13911
|
-
|
|
13828
|
+
loadProperty(this, "speed", data.speed);
|
|
13829
|
+
}
|
|
13830
|
+
}
|
|
13831
|
+
|
|
13832
|
+
class CollisionsOverlap {
|
|
13833
|
+
enable = true;
|
|
13834
|
+
retries = 0;
|
|
13835
|
+
load(data) {
|
|
13836
|
+
if (isNull(data)) {
|
|
13912
13837
|
return;
|
|
13913
13838
|
}
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
gif: data.gif,
|
|
13917
|
-
name: data.name ?? data.src,
|
|
13918
|
-
source: data.src,
|
|
13919
|
-
type: data.src.substring(data.src.length - extLength),
|
|
13920
|
-
error: false,
|
|
13921
|
-
loading: true,
|
|
13922
|
-
replaceColor: data.replaceColor,
|
|
13923
|
-
ratio: data.width && data.height ? data.width / data.height : undefined,
|
|
13924
|
-
};
|
|
13925
|
-
containerImages.push(image);
|
|
13926
|
-
engine.images.set(container, containerImages);
|
|
13927
|
-
let imageFunc;
|
|
13928
|
-
if (data.gif) {
|
|
13929
|
-
imageFunc = (img) => loadGifImage(img, { colorSpace: "srgb" });
|
|
13930
|
-
}
|
|
13931
|
-
else if (data.replaceColor) {
|
|
13932
|
-
imageFunc = downloadSvgImage;
|
|
13933
|
-
}
|
|
13934
|
-
else {
|
|
13935
|
-
imageFunc = loadImage;
|
|
13936
|
-
}
|
|
13937
|
-
await imageFunc(image);
|
|
13938
|
-
}
|
|
13939
|
-
catch {
|
|
13940
|
-
throw new Error(`${data.name ?? data.src} not found`);
|
|
13941
|
-
}
|
|
13942
|
-
};
|
|
13943
|
-
}
|
|
13944
|
-
async function loadImageShape(engine) {
|
|
13945
|
-
engine.checkVersion("4.2.1");
|
|
13946
|
-
await engine.pluginManager.register(e => {
|
|
13947
|
-
addLoadImageToEngine(e);
|
|
13948
|
-
e.pluginManager.addPlugin(new ImagePreloaderPlugin(e));
|
|
13949
|
-
e.pluginManager.addShape(shapeTypes, container => Promise.resolve(new ImageDrawer(e, container)));
|
|
13950
|
-
});
|
|
13951
|
-
}
|
|
13952
|
-
|
|
13953
|
-
class LifeDelay extends ValueWithRandom {
|
|
13954
|
-
sync = false;
|
|
13955
|
-
load(data) {
|
|
13956
|
-
if (isNull(data)) {
|
|
13957
|
-
return;
|
|
13958
|
-
}
|
|
13959
|
-
super.load(data);
|
|
13960
|
-
loadProperty(this, "sync", data.sync);
|
|
13839
|
+
loadProperty(this, "enable", data.enable);
|
|
13840
|
+
loadProperty(this, "retries", data.retries);
|
|
13961
13841
|
}
|
|
13962
13842
|
}
|
|
13963
13843
|
|
|
13964
|
-
class
|
|
13965
|
-
|
|
13844
|
+
class Collisions {
|
|
13845
|
+
absorb = new CollisionsAbsorb();
|
|
13846
|
+
bounce = new ParticlesBounce();
|
|
13847
|
+
enable = false;
|
|
13848
|
+
maxSpeed = 50;
|
|
13849
|
+
mode = CollisionMode.bounce;
|
|
13850
|
+
overlap = new CollisionsOverlap();
|
|
13966
13851
|
load(data) {
|
|
13967
13852
|
if (isNull(data)) {
|
|
13968
13853
|
return;
|
|
13969
13854
|
}
|
|
13970
|
-
|
|
13971
|
-
|
|
13855
|
+
this.absorb.load(data.absorb);
|
|
13856
|
+
this.bounce.load(data.bounce);
|
|
13857
|
+
loadProperty(this, "enable", data.enable);
|
|
13858
|
+
loadRangeProperty(this, "maxSpeed", data.maxSpeed);
|
|
13859
|
+
loadProperty(this, "mode", data.mode);
|
|
13860
|
+
this.overlap.load(data.overlap);
|
|
13972
13861
|
}
|
|
13973
13862
|
}
|
|
13974
13863
|
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13864
|
+
const minAbsorbAmount = 0;
|
|
13865
|
+
function updateAbsorb(p1, r1, p2, r2, delta, pixelRatio) {
|
|
13866
|
+
if (!p1.options.collisions || !p2.options.collisions) {
|
|
13867
|
+
return;
|
|
13868
|
+
}
|
|
13869
|
+
const absorbSpeed = p1.options.collisions.absorb.speed, shrinkAmount = clamp(absorbSpeed * delta.factor, minAbsorbAmount, r2);
|
|
13870
|
+
p1.size.value = Math.sqrt(r1 * r1 + shrinkAmount * shrinkAmount);
|
|
13871
|
+
p2.size.value -= shrinkAmount;
|
|
13872
|
+
if (p2.size.value <= pixelRatio) {
|
|
13873
|
+
p2.size.value = 0;
|
|
13874
|
+
p2.destroy();
|
|
13986
13875
|
}
|
|
13987
13876
|
}
|
|
13988
|
-
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
return;
|
|
13877
|
+
function absorb(p1, p2, delta, pixelRatio) {
|
|
13878
|
+
const r1 = p1.getRadius(), r2 = p2.getRadius();
|
|
13879
|
+
if (!r1 && r2) {
|
|
13880
|
+
p1.destroy();
|
|
13993
13881
|
}
|
|
13994
|
-
|
|
13995
|
-
|
|
13996
|
-
|
|
13997
|
-
|
|
13998
|
-
if (
|
|
13999
|
-
|
|
14000
|
-
particle.spawning = false;
|
|
14001
|
-
life.delayTime = noTime$1;
|
|
14002
|
-
life.time = noTime$1;
|
|
13882
|
+
else if (r1 && !r2) {
|
|
13883
|
+
p2.destroy();
|
|
13884
|
+
}
|
|
13885
|
+
else if (r1 && r2) {
|
|
13886
|
+
if (r1 >= r2) {
|
|
13887
|
+
updateAbsorb(p1, r1, p2, r2, delta, pixelRatio);
|
|
14003
13888
|
}
|
|
14004
13889
|
else {
|
|
14005
|
-
|
|
13890
|
+
updateAbsorb(p2, r2, p1, r1, delta, pixelRatio);
|
|
14006
13891
|
}
|
|
14007
13892
|
}
|
|
14008
|
-
|
|
13893
|
+
}
|
|
13894
|
+
|
|
13895
|
+
const energyCorrectionMinRatio = 1e-6, energyDriftThreshold = 1e-4, correctionFactorNeutral = 1, fixBounceSpeed = (p) => {
|
|
13896
|
+
if (!p.options.collisions) {
|
|
14009
13897
|
return;
|
|
14010
13898
|
}
|
|
14011
|
-
|
|
14012
|
-
|
|
13899
|
+
p.collisionMaxSpeed ??= getRangeValue(p.options.collisions.maxSpeed);
|
|
13900
|
+
if (p.velocity.length > p.collisionMaxSpeed) {
|
|
13901
|
+
p.velocity.length = p.collisionMaxSpeed;
|
|
14013
13902
|
}
|
|
14014
|
-
|
|
14015
|
-
|
|
13903
|
+
};
|
|
13904
|
+
function bounce(p1, p2) {
|
|
13905
|
+
const m1 = p1.getMass(), m2 = p2.getMass(), speed1Before = p1.velocity.length, speed2Before = p2.velocity.length, keBefore = m1 * speed1Before * speed1Before + m2 * speed2Before * speed2Before;
|
|
13906
|
+
circleBounce(circleBounceDataFromParticle(p1), circleBounceDataFromParticle(p2));
|
|
13907
|
+
const speed1After = p1.velocity.length, speed2After = p2.velocity.length, keAfter = m1 * speed1After * speed1After + m2 * speed2After * speed2After;
|
|
13908
|
+
if (keAfter > keBefore * energyCorrectionMinRatio) {
|
|
13909
|
+
const correctionFactor = Math.sqrt(keBefore / keAfter);
|
|
13910
|
+
if (Math.abs(correctionFactor - correctionFactorNeutral) > energyDriftThreshold) {
|
|
13911
|
+
p1.velocity.length = speed1After * correctionFactor;
|
|
13912
|
+
p2.velocity.length = speed2After * correctionFactor;
|
|
13913
|
+
}
|
|
14016
13914
|
}
|
|
14017
|
-
|
|
14018
|
-
|
|
13915
|
+
fixBounceSpeed(p1);
|
|
13916
|
+
fixBounceSpeed(p2);
|
|
13917
|
+
}
|
|
13918
|
+
|
|
13919
|
+
function destroy(p1, p2) {
|
|
13920
|
+
if (!p1.unbreakable && !p2.unbreakable) {
|
|
13921
|
+
bounce(p1, p2);
|
|
14019
13922
|
}
|
|
14020
|
-
|
|
14021
|
-
if (
|
|
14022
|
-
|
|
13923
|
+
const p1Radius = p1.getRadius(), p2Radius = p2.getRadius();
|
|
13924
|
+
if (!p1Radius && p2Radius) {
|
|
13925
|
+
p1.destroy();
|
|
14023
13926
|
}
|
|
14024
|
-
if (
|
|
14025
|
-
|
|
13927
|
+
else if (p1Radius && !p2Radius) {
|
|
13928
|
+
p2.destroy();
|
|
13929
|
+
}
|
|
13930
|
+
else if (p1Radius && p2Radius) {
|
|
13931
|
+
const deleteP = p1.getRadius() >= p2.getRadius() ? p2 : p1;
|
|
13932
|
+
deleteP.destroy();
|
|
13933
|
+
}
|
|
13934
|
+
}
|
|
13935
|
+
|
|
13936
|
+
function resolveCollision(p1, p2, delta, pixelRatio) {
|
|
13937
|
+
if (!p1.options.collisions || !p2.options.collisions) {
|
|
14026
13938
|
return;
|
|
14027
13939
|
}
|
|
14028
|
-
|
|
14029
|
-
|
|
14030
|
-
|
|
14031
|
-
|
|
14032
|
-
|
|
14033
|
-
|
|
14034
|
-
|
|
14035
|
-
|
|
14036
|
-
|
|
14037
|
-
|
|
14038
|
-
|
|
13940
|
+
switch (p1.options.collisions.mode) {
|
|
13941
|
+
case CollisionMode.absorb: {
|
|
13942
|
+
absorb(p1, p2, delta, pixelRatio);
|
|
13943
|
+
break;
|
|
13944
|
+
}
|
|
13945
|
+
case CollisionMode.bounce: {
|
|
13946
|
+
bounce(p1, p2);
|
|
13947
|
+
break;
|
|
13948
|
+
}
|
|
13949
|
+
case CollisionMode.destroy: {
|
|
13950
|
+
destroy(p1, p2);
|
|
13951
|
+
break;
|
|
13952
|
+
}
|
|
14039
13953
|
}
|
|
14040
13954
|
}
|
|
14041
13955
|
|
|
14042
|
-
|
|
14043
|
-
|
|
14044
|
-
#container;
|
|
13956
|
+
class Collider extends ParticlesInteractorBase {
|
|
13957
|
+
maxDistance;
|
|
14045
13958
|
constructor(container) {
|
|
14046
|
-
|
|
13959
|
+
super(container);
|
|
13960
|
+
this.maxDistance = 0;
|
|
14047
13961
|
}
|
|
14048
|
-
|
|
14049
|
-
|
|
14050
|
-
|
|
13962
|
+
clear() {
|
|
13963
|
+
}
|
|
13964
|
+
init() {
|
|
13965
|
+
}
|
|
13966
|
+
interact(p1, _interactivityData, delta) {
|
|
13967
|
+
if (p1.destroyed || p1.spawning) {
|
|
14051
13968
|
return;
|
|
14052
13969
|
}
|
|
14053
|
-
const
|
|
14054
|
-
|
|
14055
|
-
|
|
14056
|
-
|
|
14057
|
-
|
|
14058
|
-
|
|
14059
|
-
|
|
14060
|
-
|
|
14061
|
-
|
|
14062
|
-
|
|
14063
|
-
|
|
14064
|
-
|
|
14065
|
-
|
|
14066
|
-
|
|
14067
|
-
|
|
14068
|
-
|
|
14069
|
-
|
|
14070
|
-
|
|
14071
|
-
|
|
13970
|
+
const container = this.container, pos1 = p1.getPosition(), radius1 = p1.getRadius(), query = container.particles.grid.queryCircle(pos1, radius1 * double);
|
|
13971
|
+
for (const p2 of query) {
|
|
13972
|
+
if (p1 === p2 ||
|
|
13973
|
+
p1.id >= p2.id ||
|
|
13974
|
+
!p1.options.collisions?.enable ||
|
|
13975
|
+
!p2.options.collisions?.enable ||
|
|
13976
|
+
p1.options.collisions.mode !== p2.options.collisions.mode ||
|
|
13977
|
+
p2.destroyed ||
|
|
13978
|
+
p2.spawning) {
|
|
13979
|
+
continue;
|
|
13980
|
+
}
|
|
13981
|
+
const pos2 = p2.getPosition(), radius2 = p2.getRadius();
|
|
13982
|
+
if (Math.abs(Math.round(pos1.z) - Math.round(pos2.z)) > radius1 + radius2) {
|
|
13983
|
+
continue;
|
|
13984
|
+
}
|
|
13985
|
+
const dist = getDistance(pos1, pos2), distP = radius1 + radius2;
|
|
13986
|
+
if (dist > distP) {
|
|
13987
|
+
continue;
|
|
13988
|
+
}
|
|
13989
|
+
resolveCollision(p1, p2, delta, container.retina.pixelRatio);
|
|
14072
13990
|
}
|
|
14073
|
-
particle.spawning = particle.life.delay > noTime;
|
|
14074
13991
|
}
|
|
14075
13992
|
isEnabled(particle) {
|
|
14076
|
-
return
|
|
13993
|
+
return !!particle.options.collisions?.enable;
|
|
14077
13994
|
}
|
|
14078
|
-
|
|
14079
|
-
loadOptionProperty(options, "
|
|
13995
|
+
loadParticlesOptions(options, ...sources) {
|
|
13996
|
+
loadOptionProperty(options, "collisions", Collisions, ...sources);
|
|
14080
13997
|
}
|
|
14081
|
-
|
|
14082
|
-
if (!this.isEnabled(particle) || !particle.life) {
|
|
14083
|
-
return;
|
|
14084
|
-
}
|
|
14085
|
-
updateLife(particle, delta, this.#container.canvas.size);
|
|
13998
|
+
reset() {
|
|
14086
13999
|
}
|
|
14087
14000
|
}
|
|
14088
14001
|
|
|
14089
|
-
|
|
14090
|
-
|
|
14091
|
-
|
|
14092
|
-
|
|
14093
|
-
|
|
14094
|
-
});
|
|
14095
|
-
});
|
|
14096
|
-
}
|
|
14097
|
-
|
|
14098
|
-
function drawLine(data) {
|
|
14099
|
-
const { context, particle, radius } = data, shapeData = particle.shapeData, centerY = 0;
|
|
14100
|
-
context.moveTo(-radius, centerY);
|
|
14101
|
-
context.lineTo(radius, centerY);
|
|
14102
|
-
context.lineCap = shapeData?.cap ?? "butt";
|
|
14103
|
-
}
|
|
14104
|
-
|
|
14105
|
-
const sides$2 = 1;
|
|
14106
|
-
class LineDrawer {
|
|
14107
|
-
draw(data) {
|
|
14108
|
-
drawLine(data);
|
|
14002
|
+
class OverlapPlugin {
|
|
14003
|
+
id = "overlap";
|
|
14004
|
+
async getPlugin(container) {
|
|
14005
|
+
const { OverlapPluginInstance } = await Promise.resolve().then(function () { return OverlapPluginInstance$1; });
|
|
14006
|
+
return new OverlapPluginInstance(container);
|
|
14109
14007
|
}
|
|
14110
|
-
|
|
14111
|
-
|
|
14008
|
+
loadOptions() {
|
|
14009
|
+
}
|
|
14010
|
+
needsPlugin() {
|
|
14011
|
+
return true;
|
|
14112
14012
|
}
|
|
14113
14013
|
}
|
|
14114
14014
|
|
|
14115
|
-
async function
|
|
14015
|
+
async function loadParticlesCollisionsInteraction(engine) {
|
|
14116
14016
|
engine.checkVersion("4.2.1");
|
|
14117
|
-
await engine.pluginManager.register(e => {
|
|
14118
|
-
e
|
|
14017
|
+
await engine.pluginManager.register((e) => {
|
|
14018
|
+
ensureInteractivityPluginLoaded(e);
|
|
14019
|
+
e.pluginManager.addPlugin(new OverlapPlugin());
|
|
14020
|
+
e.pluginManager.addInteractor?.("particlesCollisions", container => {
|
|
14021
|
+
return Promise.resolve(new Collider(container));
|
|
14022
|
+
});
|
|
14119
14023
|
});
|
|
14120
14024
|
}
|
|
14121
14025
|
|
|
14122
|
-
class
|
|
14123
|
-
|
|
14026
|
+
class CircleWarp extends Circle {
|
|
14027
|
+
#canvasSize;
|
|
14028
|
+
constructor(x, y, radius, canvasSize) {
|
|
14029
|
+
super(x, y, radius);
|
|
14030
|
+
this.#canvasSize = canvasSize;
|
|
14031
|
+
}
|
|
14032
|
+
contains(point) {
|
|
14033
|
+
if (super.contains(point))
|
|
14034
|
+
return true;
|
|
14035
|
+
const { width, height } = this.#canvasSize, { x, y } = point;
|
|
14036
|
+
return (super.contains({ x: x - width, y }) ||
|
|
14037
|
+
super.contains({ x: x + width, y }) ||
|
|
14038
|
+
super.contains({ x, y: y - height }) ||
|
|
14039
|
+
super.contains({ x, y: y + height }) ||
|
|
14040
|
+
super.contains({ x: x - width, y: y - height }) ||
|
|
14041
|
+
super.contains({ x: x + width, y: y + height }) ||
|
|
14042
|
+
super.contains({ x: x - width, y: y + height }) ||
|
|
14043
|
+
super.contains({ x: x + width, y: y - height }));
|
|
14044
|
+
}
|
|
14045
|
+
intersects(range) {
|
|
14046
|
+
if (super.intersects(range))
|
|
14047
|
+
return true;
|
|
14048
|
+
const { width, height } = this.#canvasSize, pos = range.position, shifts = [
|
|
14049
|
+
{ x: -width, y: 0 },
|
|
14050
|
+
{ x: width, y: 0 },
|
|
14051
|
+
{ x: 0, y: -height },
|
|
14052
|
+
{ x: 0, y: height },
|
|
14053
|
+
{ x: -width, y: -height },
|
|
14054
|
+
{ x: width, y: height },
|
|
14055
|
+
{ x: -width, y: height },
|
|
14056
|
+
{ x: width, y: -height },
|
|
14057
|
+
];
|
|
14058
|
+
for (const shift of shifts) {
|
|
14059
|
+
const shiftedPos = { x: pos.x + shift.x, y: pos.y + shift.y };
|
|
14060
|
+
let shiftedRange;
|
|
14061
|
+
if (range instanceof Circle) {
|
|
14062
|
+
shiftedRange = new Circle(shiftedPos.x, shiftedPos.y, range.radius);
|
|
14063
|
+
}
|
|
14064
|
+
else {
|
|
14065
|
+
const rect = range;
|
|
14066
|
+
shiftedRange = new Rectangle(shiftedPos.x, shiftedPos.y, rect.size.width, rect.size.height);
|
|
14067
|
+
}
|
|
14068
|
+
if (super.intersects(shiftedRange))
|
|
14069
|
+
return true;
|
|
14070
|
+
}
|
|
14071
|
+
return false;
|
|
14072
|
+
}
|
|
14073
|
+
}
|
|
14074
|
+
|
|
14075
|
+
class LinksShadow {
|
|
14076
|
+
blur = 5;
|
|
14077
|
+
color = new OptionsColor();
|
|
14124
14078
|
enable = false;
|
|
14125
|
-
rotate;
|
|
14126
14079
|
constructor() {
|
|
14127
|
-
this.
|
|
14128
|
-
x: 3000,
|
|
14129
|
-
y: 3000,
|
|
14130
|
-
};
|
|
14080
|
+
this.color.value = "#000";
|
|
14131
14081
|
}
|
|
14132
14082
|
load(data) {
|
|
14133
14083
|
if (isNull(data)) {
|
|
14134
14084
|
return;
|
|
14135
14085
|
}
|
|
14136
|
-
|
|
14086
|
+
loadProperty(this, "blur", data.blur);
|
|
14087
|
+
this.color = OptionsColor.create(this.color, data.color);
|
|
14137
14088
|
loadProperty(this, "enable", data.enable);
|
|
14138
|
-
|
|
14139
|
-
|
|
14140
|
-
|
|
14141
|
-
|
|
14142
|
-
|
|
14143
|
-
|
|
14144
|
-
|
|
14145
|
-
|
|
14146
|
-
|
|
14089
|
+
}
|
|
14090
|
+
}
|
|
14091
|
+
|
|
14092
|
+
class LinksTriangle {
|
|
14093
|
+
color;
|
|
14094
|
+
enable = false;
|
|
14095
|
+
frequency = 1;
|
|
14096
|
+
opacity;
|
|
14097
|
+
load(data) {
|
|
14098
|
+
if (isNull(data)) {
|
|
14099
|
+
return;
|
|
14100
|
+
}
|
|
14101
|
+
if (data.color !== undefined) {
|
|
14102
|
+
this.color = OptionsColor.create(this.color, data.color);
|
|
14147
14103
|
}
|
|
14104
|
+
loadProperty(this, "enable", data.enable);
|
|
14105
|
+
loadProperty(this, "frequency", data.frequency);
|
|
14106
|
+
loadProperty(this, "opacity", data.opacity);
|
|
14148
14107
|
}
|
|
14149
14108
|
}
|
|
14150
14109
|
|
|
14151
|
-
|
|
14152
|
-
|
|
14110
|
+
class Links {
|
|
14111
|
+
blink = false;
|
|
14112
|
+
color = new OptionsColor();
|
|
14113
|
+
consent = false;
|
|
14114
|
+
distance = 100;
|
|
14115
|
+
enable = false;
|
|
14116
|
+
frequency = 1;
|
|
14117
|
+
id;
|
|
14118
|
+
opacity = 1;
|
|
14119
|
+
shadow = new LinksShadow();
|
|
14120
|
+
triangles = new LinksTriangle();
|
|
14121
|
+
warp = false;
|
|
14122
|
+
width = 1;
|
|
14123
|
+
constructor() {
|
|
14124
|
+
this.color.value = "#fff";
|
|
14125
|
+
}
|
|
14126
|
+
load(data) {
|
|
14127
|
+
if (isNull(data)) {
|
|
14128
|
+
return;
|
|
14129
|
+
}
|
|
14130
|
+
loadProperty(this, "id", data.id);
|
|
14131
|
+
loadProperty(this, "blink", data.blink);
|
|
14132
|
+
this.color = OptionsColor.create(this.color, data.color);
|
|
14133
|
+
loadProperty(this, "consent", data.consent);
|
|
14134
|
+
loadProperty(this, "distance", data.distance);
|
|
14135
|
+
loadProperty(this, "enable", data.enable);
|
|
14136
|
+
loadProperty(this, "frequency", data.frequency);
|
|
14137
|
+
loadProperty(this, "opacity", data.opacity);
|
|
14138
|
+
this.shadow.load(data.shadow);
|
|
14139
|
+
this.triangles.load(data.triangles);
|
|
14140
|
+
loadProperty(this, "width", data.width);
|
|
14141
|
+
loadProperty(this, "warp", data.warp);
|
|
14142
|
+
}
|
|
14143
|
+
}
|
|
14144
|
+
|
|
14145
|
+
const opacityOffset = 1, minDistance$1 = 0;
|
|
14146
|
+
function getWarpDistance(pos1, pos2, canvasSize) {
|
|
14147
|
+
const { dx, dy } = getDistances(pos1, pos2), absDiffs = { x: Math.abs(dx), y: Math.abs(dy) }, warpDistances = {
|
|
14148
|
+
x: Math.min(absDiffs.x, canvasSize.width - absDiffs.x),
|
|
14149
|
+
y: Math.min(absDiffs.y, canvasSize.height - absDiffs.y),
|
|
14150
|
+
};
|
|
14151
|
+
return Math.hypot(warpDistances.x, warpDistances.y);
|
|
14152
|
+
}
|
|
14153
|
+
class Linker extends ParticlesInteractorBase {
|
|
14153
14154
|
#maxDistance;
|
|
14154
|
-
|
|
14155
|
+
#pluginManager;
|
|
14156
|
+
constructor(pluginManager, container) {
|
|
14155
14157
|
super(container);
|
|
14158
|
+
this.#pluginManager = pluginManager;
|
|
14156
14159
|
this.#maxDistance = 0;
|
|
14157
14160
|
}
|
|
14158
14161
|
get maxDistance() {
|
|
@@ -14161,705 +14164,308 @@
|
|
|
14161
14164
|
clear() {
|
|
14162
14165
|
}
|
|
14163
14166
|
init() {
|
|
14167
|
+
this.container.particles.linksColor = undefined;
|
|
14168
|
+
this.container.particles.linksColors = new Map();
|
|
14164
14169
|
}
|
|
14165
14170
|
interact(p1) {
|
|
14166
|
-
if (!p1.options.
|
|
14171
|
+
if (!p1.options.links) {
|
|
14167
14172
|
return;
|
|
14168
14173
|
}
|
|
14169
|
-
|
|
14170
|
-
if (
|
|
14171
|
-
|
|
14172
|
-
if (attractDistance > this.#maxDistance) {
|
|
14173
|
-
this.#maxDistance = attractDistance;
|
|
14174
|
-
}
|
|
14175
|
-
p1.attractDistance = attractDistance * container.retina.pixelRatio;
|
|
14174
|
+
p1.links = [];
|
|
14175
|
+
if (p1.linksDistance && p1.linksDistance > this.#maxDistance) {
|
|
14176
|
+
this.#maxDistance = p1.linksDistance;
|
|
14176
14177
|
}
|
|
14177
|
-
const
|
|
14178
|
+
const pos1 = p1.getPosition(), container = this.container, canvasSize = container.canvas.size;
|
|
14179
|
+
if (pos1.x < originPoint.x || pos1.y < originPoint.y || pos1.x > canvasSize.width || pos1.y > canvasSize.height) {
|
|
14180
|
+
return;
|
|
14181
|
+
}
|
|
14182
|
+
const linkOpt1 = p1.options.links, optOpacity = linkOpt1.opacity, optDistance = p1.retina.linksDistance ?? minDistance$1, warp = linkOpt1.warp, range = warp ? new CircleWarp(pos1.x, pos1.y, optDistance, canvasSize) : new Circle(pos1.x, pos1.y, optDistance), query = container.particles.grid.query(range);
|
|
14178
14183
|
for (const p2 of query) {
|
|
14179
|
-
|
|
14184
|
+
const linkOpt2 = p2.options.links;
|
|
14185
|
+
if (p1 === p2 ||
|
|
14186
|
+
!linkOpt2?.enable ||
|
|
14187
|
+
linkOpt1.id !== linkOpt2.id ||
|
|
14188
|
+
p2.spawning ||
|
|
14189
|
+
p2.destroyed ||
|
|
14190
|
+
!p2.links ||
|
|
14191
|
+
p1.links.some(t => t.destination === p2) ||
|
|
14192
|
+
p2.links.some(t => t.destination === p1)) {
|
|
14180
14193
|
continue;
|
|
14181
14194
|
}
|
|
14182
|
-
const pos2 = p2.getPosition()
|
|
14183
|
-
|
|
14184
|
-
|
|
14185
|
-
|
|
14186
|
-
|
|
14195
|
+
const pos2 = p2.getPosition();
|
|
14196
|
+
if (pos2.x < originPoint.x || pos2.y < originPoint.y || pos2.x > canvasSize.width || pos2.y > canvasSize.height) {
|
|
14197
|
+
continue;
|
|
14198
|
+
}
|
|
14199
|
+
const distDirect = getDistances(pos1, pos2).distance, distWarp = warp && linkOpt2.warp ? getWarpDistance(pos1, pos2, canvasSize) : distDirect, distance = Math.min(distDirect, distWarp);
|
|
14200
|
+
if (distance > optDistance) {
|
|
14201
|
+
continue;
|
|
14202
|
+
}
|
|
14203
|
+
const opacityLine = (opacityOffset - distance / optDistance) * optOpacity;
|
|
14204
|
+
this.#setColor(p1);
|
|
14205
|
+
p1.links.push({
|
|
14206
|
+
destination: p2,
|
|
14207
|
+
opacity: opacityLine,
|
|
14208
|
+
color: this.#getLinkColor(p1, p2),
|
|
14209
|
+
isWarped: distWarp < distDirect,
|
|
14210
|
+
});
|
|
14187
14211
|
}
|
|
14188
14212
|
}
|
|
14189
14213
|
isEnabled(particle) {
|
|
14190
|
-
return particle.options.
|
|
14214
|
+
return !!particle.options.links?.enable;
|
|
14191
14215
|
}
|
|
14192
14216
|
loadParticlesOptions(options, ...sources) {
|
|
14193
|
-
loadOptionProperty(options, "
|
|
14217
|
+
loadOptionProperty(options, "links", Links, ...sources);
|
|
14194
14218
|
}
|
|
14195
14219
|
reset() {
|
|
14196
14220
|
}
|
|
14197
|
-
|
|
14198
|
-
|
|
14199
|
-
|
|
14200
|
-
engine.checkVersion("4.2.1");
|
|
14201
|
-
await engine.pluginManager.register((e) => {
|
|
14202
|
-
ensureInteractivityPluginLoaded(e);
|
|
14203
|
-
e.pluginManager.addInteractor?.("particlesAttract", container => {
|
|
14204
|
-
return Promise.resolve(new Attractor(container));
|
|
14205
|
-
});
|
|
14206
|
-
});
|
|
14207
|
-
}
|
|
14208
|
-
|
|
14209
|
-
var CollisionMode;
|
|
14210
|
-
(function (CollisionMode) {
|
|
14211
|
-
CollisionMode["absorb"] = "absorb";
|
|
14212
|
-
CollisionMode["bounce"] = "bounce";
|
|
14213
|
-
CollisionMode["destroy"] = "destroy";
|
|
14214
|
-
})(CollisionMode || (CollisionMode = {}));
|
|
14215
|
-
|
|
14216
|
-
class CollisionsAbsorb {
|
|
14217
|
-
speed = 2;
|
|
14218
|
-
load(data) {
|
|
14219
|
-
if (isNull(data)) {
|
|
14221
|
+
#getLinkColor(p1, p2) {
|
|
14222
|
+
const container = this.container, linksOptions = p1.options.links;
|
|
14223
|
+
if (!linksOptions) {
|
|
14220
14224
|
return;
|
|
14221
14225
|
}
|
|
14222
|
-
|
|
14223
|
-
|
|
14224
|
-
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
|
|
14228
|
-
|
|
14229
|
-
load(data) {
|
|
14230
|
-
if (isNull(data)) {
|
|
14226
|
+
const linkColor = linksOptions.id !== undefined
|
|
14227
|
+
? container.particles.linksColors.get(linksOptions.id)
|
|
14228
|
+
: container.particles.linksColor;
|
|
14229
|
+
return getLinkColor(p1, p2, linkColor);
|
|
14230
|
+
}
|
|
14231
|
+
#setColor(p1) {
|
|
14232
|
+
if (!p1.options.links) {
|
|
14231
14233
|
return;
|
|
14232
14234
|
}
|
|
14233
|
-
|
|
14234
|
-
|
|
14235
|
-
|
|
14236
|
-
|
|
14237
|
-
|
|
14238
|
-
class Collisions {
|
|
14239
|
-
absorb = new CollisionsAbsorb();
|
|
14240
|
-
bounce = new ParticlesBounce();
|
|
14241
|
-
enable = false;
|
|
14242
|
-
maxSpeed = 50;
|
|
14243
|
-
mode = CollisionMode.bounce;
|
|
14244
|
-
overlap = new CollisionsOverlap();
|
|
14245
|
-
load(data) {
|
|
14246
|
-
if (isNull(data)) {
|
|
14235
|
+
const container = this.container, linksOptions = p1.options.links;
|
|
14236
|
+
let linkColor = linksOptions.id === undefined
|
|
14237
|
+
? container.particles.linksColor
|
|
14238
|
+
: container.particles.linksColors.get(linksOptions.id);
|
|
14239
|
+
if (linkColor) {
|
|
14247
14240
|
return;
|
|
14248
14241
|
}
|
|
14249
|
-
this.
|
|
14250
|
-
|
|
14251
|
-
|
|
14252
|
-
loadRangeProperty(this, "maxSpeed", data.maxSpeed);
|
|
14253
|
-
loadProperty(this, "mode", data.mode);
|
|
14254
|
-
this.overlap.load(data.overlap);
|
|
14255
|
-
}
|
|
14256
|
-
}
|
|
14257
|
-
|
|
14258
|
-
const minAbsorbAmount = 0;
|
|
14259
|
-
function updateAbsorb(p1, r1, p2, r2, delta, pixelRatio) {
|
|
14260
|
-
if (!p1.options.collisions || !p2.options.collisions) {
|
|
14261
|
-
return;
|
|
14262
|
-
}
|
|
14263
|
-
const absorbSpeed = p1.options.collisions.absorb.speed, shrinkAmount = clamp(absorbSpeed * delta.factor, minAbsorbAmount, r2);
|
|
14264
|
-
p1.size.value = Math.sqrt(r1 * r1 + shrinkAmount * shrinkAmount);
|
|
14265
|
-
p2.size.value -= shrinkAmount;
|
|
14266
|
-
if (p2.size.value <= pixelRatio) {
|
|
14267
|
-
p2.size.value = 0;
|
|
14268
|
-
p2.destroy();
|
|
14269
|
-
}
|
|
14270
|
-
}
|
|
14271
|
-
function absorb(p1, p2, delta, pixelRatio) {
|
|
14272
|
-
const r1 = p1.getRadius(), r2 = p2.getRadius();
|
|
14273
|
-
if (!r1 && r2) {
|
|
14274
|
-
p1.destroy();
|
|
14275
|
-
}
|
|
14276
|
-
else if (r1 && !r2) {
|
|
14277
|
-
p2.destroy();
|
|
14278
|
-
}
|
|
14279
|
-
else if (r1 && r2) {
|
|
14280
|
-
if (r1 >= r2) {
|
|
14281
|
-
updateAbsorb(p1, r1, p2, r2, delta, pixelRatio);
|
|
14242
|
+
linkColor = getLinkRandomColor(this.#pluginManager, linksOptions.color, linksOptions.blink, linksOptions.consent);
|
|
14243
|
+
if (linksOptions.id === undefined) {
|
|
14244
|
+
container.particles.linksColor = linkColor;
|
|
14282
14245
|
}
|
|
14283
14246
|
else {
|
|
14284
|
-
|
|
14247
|
+
container.particles.linksColors.set(linksOptions.id, linkColor);
|
|
14285
14248
|
}
|
|
14286
14249
|
}
|
|
14287
14250
|
}
|
|
14288
14251
|
|
|
14289
|
-
|
|
14290
|
-
|
|
14291
|
-
|
|
14252
|
+
class LinksPlugin {
|
|
14253
|
+
id = "links";
|
|
14254
|
+
#pluginManager;
|
|
14255
|
+
constructor(pluginManager) {
|
|
14256
|
+
this.#pluginManager = pluginManager;
|
|
14292
14257
|
}
|
|
14293
|
-
|
|
14294
|
-
|
|
14295
|
-
|
|
14258
|
+
async getPlugin(container) {
|
|
14259
|
+
const { LinkInstance } = await Promise.resolve().then(function () { return LinkInstance$1; });
|
|
14260
|
+
return new LinkInstance(this.#pluginManager, container);
|
|
14296
14261
|
}
|
|
14297
|
-
|
|
14298
|
-
|
|
14299
|
-
|
|
14300
|
-
|
|
14301
|
-
const speed1After = p1.velocity.length, speed2After = p2.velocity.length, keAfter = m1 * speed1After * speed1After + m2 * speed2After * speed2After;
|
|
14302
|
-
if (keAfter > keBefore * energyCorrectionMinRatio) {
|
|
14303
|
-
const correctionFactor = Math.sqrt(keBefore / keAfter);
|
|
14304
|
-
if (Math.abs(correctionFactor - correctionFactorNeutral) > energyDriftThreshold) {
|
|
14305
|
-
p1.velocity.length = speed1After * correctionFactor;
|
|
14306
|
-
p2.velocity.length = speed2After * correctionFactor;
|
|
14307
|
-
}
|
|
14262
|
+
loadOptions() {
|
|
14263
|
+
}
|
|
14264
|
+
needsPlugin() {
|
|
14265
|
+
return true;
|
|
14308
14266
|
}
|
|
14309
|
-
fixBounceSpeed(p1);
|
|
14310
|
-
fixBounceSpeed(p2);
|
|
14311
14267
|
}
|
|
14312
14268
|
|
|
14313
|
-
function
|
|
14314
|
-
|
|
14315
|
-
|
|
14316
|
-
|
|
14317
|
-
|
|
14318
|
-
|
|
14319
|
-
|
|
14320
|
-
|
|
14321
|
-
|
|
14322
|
-
|
|
14323
|
-
}
|
|
14324
|
-
else if (p1Radius && p2Radius) {
|
|
14325
|
-
const deleteP = p1.getRadius() >= p2.getRadius() ? p2 : p1;
|
|
14326
|
-
deleteP.destroy();
|
|
14327
|
-
}
|
|
14269
|
+
async function loadParticlesLinksInteraction(engine) {
|
|
14270
|
+
engine.checkVersion("4.2.1");
|
|
14271
|
+
await engine.pluginManager.register((e) => {
|
|
14272
|
+
const pluginManager = e.pluginManager;
|
|
14273
|
+
ensureInteractivityPluginLoaded(e);
|
|
14274
|
+
pluginManager.addPlugin(new LinksPlugin(pluginManager));
|
|
14275
|
+
pluginManager.addInteractor?.("particlesLinks", container => {
|
|
14276
|
+
return Promise.resolve(new Linker(pluginManager, container));
|
|
14277
|
+
});
|
|
14278
|
+
});
|
|
14328
14279
|
}
|
|
14329
14280
|
|
|
14330
|
-
|
|
14331
|
-
|
|
14332
|
-
|
|
14281
|
+
const polygonCache = new Map(), noOffset = 0;
|
|
14282
|
+
function getUnitPolygon(sides) {
|
|
14283
|
+
const cached = polygonCache.get(sides);
|
|
14284
|
+
if (cached) {
|
|
14285
|
+
return cached;
|
|
14333
14286
|
}
|
|
14334
|
-
|
|
14335
|
-
|
|
14336
|
-
|
|
14337
|
-
|
|
14287
|
+
const step = doublePI / sides, isOdd = !!(sides % double), baseAngle = (-Math.PI + (isOdd ? noOffset : step)) * half$2, verts = [];
|
|
14288
|
+
for (let i = 0; i < sides; i++) {
|
|
14289
|
+
const angle = baseAngle + i * step;
|
|
14290
|
+
verts[i] = {
|
|
14291
|
+
x: Math.cos(angle),
|
|
14292
|
+
y: Math.sin(angle),
|
|
14293
|
+
};
|
|
14294
|
+
}
|
|
14295
|
+
polygonCache.set(sides, verts);
|
|
14296
|
+
return verts;
|
|
14297
|
+
}
|
|
14298
|
+
function drawPolygon(data, side) {
|
|
14299
|
+
const { context, radius } = data, sides = side.count.numerator / side.count.denominator, verts = getUnitPolygon(sides);
|
|
14300
|
+
context.beginPath();
|
|
14301
|
+
for (let i = 0; i < verts.length; i++) {
|
|
14302
|
+
const vert = verts[i];
|
|
14303
|
+
if (!vert) {
|
|
14304
|
+
continue;
|
|
14338
14305
|
}
|
|
14339
|
-
|
|
14340
|
-
|
|
14341
|
-
|
|
14306
|
+
const x = vert.x * radius, y = vert.y * radius;
|
|
14307
|
+
if (i) {
|
|
14308
|
+
context.lineTo(x, y);
|
|
14342
14309
|
}
|
|
14343
|
-
|
|
14344
|
-
|
|
14345
|
-
break;
|
|
14310
|
+
else {
|
|
14311
|
+
context.moveTo(x, y);
|
|
14346
14312
|
}
|
|
14347
14313
|
}
|
|
14314
|
+
context.closePath();
|
|
14348
14315
|
}
|
|
14349
14316
|
|
|
14350
|
-
|
|
14351
|
-
|
|
14352
|
-
|
|
14353
|
-
|
|
14354
|
-
|
|
14355
|
-
}
|
|
14356
|
-
clear() {
|
|
14357
|
-
}
|
|
14358
|
-
init() {
|
|
14359
|
-
}
|
|
14360
|
-
interact(p1, _interactivityData, delta) {
|
|
14361
|
-
if (p1.destroyed || p1.spawning) {
|
|
14362
|
-
return;
|
|
14363
|
-
}
|
|
14364
|
-
const container = this.container, pos1 = p1.getPosition(), radius1 = p1.getRadius(), query = container.particles.grid.queryCircle(pos1, radius1 * double);
|
|
14365
|
-
for (const p2 of query) {
|
|
14366
|
-
if (p1 === p2 ||
|
|
14367
|
-
p1.id >= p2.id ||
|
|
14368
|
-
!p1.options.collisions?.enable ||
|
|
14369
|
-
!p2.options.collisions?.enable ||
|
|
14370
|
-
p1.options.collisions.mode !== p2.options.collisions.mode ||
|
|
14371
|
-
p2.destroyed ||
|
|
14372
|
-
p2.spawning) {
|
|
14373
|
-
continue;
|
|
14374
|
-
}
|
|
14375
|
-
const pos2 = p2.getPosition(), radius2 = p2.getRadius();
|
|
14376
|
-
if (Math.abs(Math.round(pos1.z) - Math.round(pos2.z)) > radius1 + radius2) {
|
|
14377
|
-
continue;
|
|
14378
|
-
}
|
|
14379
|
-
const dist = getDistance(pos1, pos2), distP = radius1 + radius2;
|
|
14380
|
-
if (dist > distP) {
|
|
14381
|
-
continue;
|
|
14382
|
-
}
|
|
14383
|
-
resolveCollision(p1, p2, delta, container.retina.pixelRatio);
|
|
14384
|
-
}
|
|
14385
|
-
}
|
|
14386
|
-
isEnabled(particle) {
|
|
14387
|
-
return !!particle.options.collisions?.enable;
|
|
14388
|
-
}
|
|
14389
|
-
loadParticlesOptions(options, ...sources) {
|
|
14390
|
-
loadOptionProperty(options, "collisions", Collisions, ...sources);
|
|
14317
|
+
const defaultSides$3 = 5;
|
|
14318
|
+
class PolygonDrawerBase {
|
|
14319
|
+
draw(data) {
|
|
14320
|
+
const { particle, radius } = data, side = this.getSidesData(particle, radius);
|
|
14321
|
+
drawPolygon(data, side);
|
|
14391
14322
|
}
|
|
14392
|
-
|
|
14323
|
+
getSidesCount(particle) {
|
|
14324
|
+
const polygon = particle.shapeData;
|
|
14325
|
+
return Math.round(getRangeValue(polygon?.sides ?? defaultSides$3));
|
|
14393
14326
|
}
|
|
14394
14327
|
}
|
|
14395
14328
|
|
|
14396
|
-
|
|
14397
|
-
|
|
14398
|
-
|
|
14399
|
-
const {
|
|
14400
|
-
return
|
|
14329
|
+
const yFactor$1 = 2.66, sidesFactor$1 = 3;
|
|
14330
|
+
class PolygonDrawer extends PolygonDrawerBase {
|
|
14331
|
+
getSidesData(particle, radius) {
|
|
14332
|
+
const { sides } = particle;
|
|
14333
|
+
return {
|
|
14334
|
+
count: {
|
|
14335
|
+
denominator: 1,
|
|
14336
|
+
numerator: sides,
|
|
14337
|
+
},
|
|
14338
|
+
length: (radius * yFactor$1) / (sides / sidesFactor$1),
|
|
14339
|
+
};
|
|
14401
14340
|
}
|
|
14402
|
-
|
|
14341
|
+
}
|
|
14342
|
+
|
|
14343
|
+
const sides$1 = 3, yFactor = 2.66, sidesFactor = 3;
|
|
14344
|
+
class TriangleDrawer extends PolygonDrawerBase {
|
|
14345
|
+
getSidesCount() {
|
|
14346
|
+
return sides$1;
|
|
14403
14347
|
}
|
|
14404
|
-
|
|
14405
|
-
return
|
|
14348
|
+
getSidesData(_particle, radius) {
|
|
14349
|
+
return {
|
|
14350
|
+
count: {
|
|
14351
|
+
denominator: 1,
|
|
14352
|
+
numerator: sides$1,
|
|
14353
|
+
},
|
|
14354
|
+
length: (radius * yFactor) / (sides$1 / sidesFactor),
|
|
14355
|
+
};
|
|
14406
14356
|
}
|
|
14407
14357
|
}
|
|
14408
14358
|
|
|
14409
|
-
async function
|
|
14359
|
+
async function loadGenericPolygonShape(engine) {
|
|
14410
14360
|
engine.checkVersion("4.2.1");
|
|
14411
|
-
await engine.pluginManager.register(
|
|
14412
|
-
|
|
14413
|
-
e.pluginManager.addPlugin(new OverlapPlugin());
|
|
14414
|
-
e.pluginManager.addInteractor?.("particlesCollisions", container => {
|
|
14415
|
-
return Promise.resolve(new Collider(container));
|
|
14416
|
-
});
|
|
14361
|
+
await engine.pluginManager.register(e => {
|
|
14362
|
+
e.pluginManager.addShape(["polygon"], () => Promise.resolve(new PolygonDrawer()));
|
|
14417
14363
|
});
|
|
14418
14364
|
}
|
|
14419
|
-
|
|
14420
|
-
|
|
14421
|
-
|
|
14422
|
-
|
|
14423
|
-
|
|
14424
|
-
this.#canvasSize = canvasSize;
|
|
14425
|
-
}
|
|
14426
|
-
contains(point) {
|
|
14427
|
-
if (super.contains(point))
|
|
14428
|
-
return true;
|
|
14429
|
-
const { width, height } = this.#canvasSize, { x, y } = point;
|
|
14430
|
-
return (super.contains({ x: x - width, y }) ||
|
|
14431
|
-
super.contains({ x: x + width, y }) ||
|
|
14432
|
-
super.contains({ x, y: y - height }) ||
|
|
14433
|
-
super.contains({ x, y: y + height }) ||
|
|
14434
|
-
super.contains({ x: x - width, y: y - height }) ||
|
|
14435
|
-
super.contains({ x: x + width, y: y + height }) ||
|
|
14436
|
-
super.contains({ x: x - width, y: y + height }) ||
|
|
14437
|
-
super.contains({ x: x + width, y: y - height }));
|
|
14438
|
-
}
|
|
14439
|
-
intersects(range) {
|
|
14440
|
-
if (super.intersects(range))
|
|
14441
|
-
return true;
|
|
14442
|
-
const { width, height } = this.#canvasSize, pos = range.position, shifts = [
|
|
14443
|
-
{ x: -width, y: 0 },
|
|
14444
|
-
{ x: width, y: 0 },
|
|
14445
|
-
{ x: 0, y: -height },
|
|
14446
|
-
{ x: 0, y: height },
|
|
14447
|
-
{ x: -width, y: -height },
|
|
14448
|
-
{ x: width, y: height },
|
|
14449
|
-
{ x: -width, y: height },
|
|
14450
|
-
{ x: width, y: -height },
|
|
14451
|
-
];
|
|
14452
|
-
for (const shift of shifts) {
|
|
14453
|
-
const shiftedPos = { x: pos.x + shift.x, y: pos.y + shift.y };
|
|
14454
|
-
let shiftedRange;
|
|
14455
|
-
if (range instanceof Circle) {
|
|
14456
|
-
shiftedRange = new Circle(shiftedPos.x, shiftedPos.y, range.radius);
|
|
14457
|
-
}
|
|
14458
|
-
else {
|
|
14459
|
-
const rect = range;
|
|
14460
|
-
shiftedRange = new Rectangle(shiftedPos.x, shiftedPos.y, rect.size.width, rect.size.height);
|
|
14461
|
-
}
|
|
14462
|
-
if (super.intersects(shiftedRange))
|
|
14463
|
-
return true;
|
|
14464
|
-
}
|
|
14465
|
-
return false;
|
|
14466
|
-
}
|
|
14365
|
+
async function loadTriangleShape(engine) {
|
|
14366
|
+
engine.checkVersion("4.2.1");
|
|
14367
|
+
await engine.pluginManager.register(e => {
|
|
14368
|
+
e.pluginManager.addShape(["triangle"], () => Promise.resolve(new TriangleDrawer()));
|
|
14369
|
+
});
|
|
14467
14370
|
}
|
|
14468
|
-
|
|
14469
|
-
|
|
14470
|
-
|
|
14471
|
-
|
|
14472
|
-
|
|
14473
|
-
|
|
14474
|
-
this.color.value = "#000";
|
|
14475
|
-
}
|
|
14476
|
-
load(data) {
|
|
14477
|
-
if (isNull(data)) {
|
|
14478
|
-
return;
|
|
14479
|
-
}
|
|
14480
|
-
loadProperty(this, "blur", data.blur);
|
|
14481
|
-
this.color = OptionsColor.create(this.color, data.color);
|
|
14482
|
-
loadProperty(this, "enable", data.enable);
|
|
14483
|
-
}
|
|
14371
|
+
async function loadPolygonShape(engine) {
|
|
14372
|
+
engine.checkVersion("4.2.1");
|
|
14373
|
+
await Promise.all([
|
|
14374
|
+
loadGenericPolygonShape(engine),
|
|
14375
|
+
loadTriangleShape(engine),
|
|
14376
|
+
]);
|
|
14484
14377
|
}
|
|
14485
14378
|
|
|
14486
|
-
class
|
|
14487
|
-
|
|
14379
|
+
class RotateAnimation {
|
|
14380
|
+
decay = 0;
|
|
14488
14381
|
enable = false;
|
|
14489
|
-
|
|
14490
|
-
|
|
14382
|
+
speed = 0;
|
|
14383
|
+
sync = false;
|
|
14491
14384
|
load(data) {
|
|
14492
14385
|
if (isNull(data)) {
|
|
14493
14386
|
return;
|
|
14494
14387
|
}
|
|
14495
|
-
if (data.color !== undefined) {
|
|
14496
|
-
this.color = OptionsColor.create(this.color, data.color);
|
|
14497
|
-
}
|
|
14498
14388
|
loadProperty(this, "enable", data.enable);
|
|
14499
|
-
|
|
14500
|
-
|
|
14389
|
+
loadRangeProperty(this, "speed", data.speed);
|
|
14390
|
+
loadRangeProperty(this, "decay", data.decay);
|
|
14391
|
+
loadProperty(this, "sync", data.sync);
|
|
14501
14392
|
}
|
|
14502
14393
|
}
|
|
14503
14394
|
|
|
14504
|
-
class
|
|
14505
|
-
|
|
14506
|
-
|
|
14507
|
-
|
|
14508
|
-
distance = 100;
|
|
14509
|
-
enable = false;
|
|
14510
|
-
frequency = 1;
|
|
14511
|
-
id;
|
|
14512
|
-
opacity = 1;
|
|
14513
|
-
shadow = new LinksShadow();
|
|
14514
|
-
triangles = new LinksTriangle();
|
|
14515
|
-
warp = false;
|
|
14516
|
-
width = 1;
|
|
14517
|
-
constructor() {
|
|
14518
|
-
this.color.value = "#fff";
|
|
14519
|
-
}
|
|
14395
|
+
class Rotate extends ValueWithRandom {
|
|
14396
|
+
animation = new RotateAnimation();
|
|
14397
|
+
direction = exports.RotateDirection.clockwise;
|
|
14398
|
+
path = false;
|
|
14520
14399
|
load(data) {
|
|
14521
14400
|
if (isNull(data)) {
|
|
14522
14401
|
return;
|
|
14523
14402
|
}
|
|
14524
|
-
|
|
14525
|
-
loadProperty(this, "
|
|
14526
|
-
this.
|
|
14527
|
-
loadProperty(this, "
|
|
14528
|
-
loadProperty(this, "distance", data.distance);
|
|
14529
|
-
loadProperty(this, "enable", data.enable);
|
|
14530
|
-
loadProperty(this, "frequency", data.frequency);
|
|
14531
|
-
loadProperty(this, "opacity", data.opacity);
|
|
14532
|
-
this.shadow.load(data.shadow);
|
|
14533
|
-
this.triangles.load(data.triangles);
|
|
14534
|
-
loadProperty(this, "width", data.width);
|
|
14535
|
-
loadProperty(this, "warp", data.warp);
|
|
14403
|
+
super.load(data);
|
|
14404
|
+
loadProperty(this, "direction", data.direction);
|
|
14405
|
+
this.animation.load(data.animation);
|
|
14406
|
+
loadProperty(this, "path", data.path);
|
|
14536
14407
|
}
|
|
14537
14408
|
}
|
|
14538
14409
|
|
|
14539
|
-
const
|
|
14540
|
-
|
|
14541
|
-
|
|
14542
|
-
|
|
14543
|
-
|
|
14544
|
-
};
|
|
14545
|
-
return Math.hypot(warpDistances.x, warpDistances.y);
|
|
14546
|
-
}
|
|
14547
|
-
class Linker extends ParticlesInteractorBase {
|
|
14548
|
-
#maxDistance;
|
|
14549
|
-
#pluginManager;
|
|
14550
|
-
constructor(pluginManager, container) {
|
|
14551
|
-
super(container);
|
|
14552
|
-
this.#pluginManager = pluginManager;
|
|
14553
|
-
this.#maxDistance = 0;
|
|
14554
|
-
}
|
|
14555
|
-
get maxDistance() {
|
|
14556
|
-
return this.#maxDistance;
|
|
14557
|
-
}
|
|
14558
|
-
clear() {
|
|
14559
|
-
}
|
|
14560
|
-
init() {
|
|
14561
|
-
this.container.particles.linksColor = undefined;
|
|
14562
|
-
this.container.particles.linksColors = new Map();
|
|
14410
|
+
const doublePIDeg = 360;
|
|
14411
|
+
class RotateUpdater {
|
|
14412
|
+
#container;
|
|
14413
|
+
constructor(container) {
|
|
14414
|
+
this.#container = container;
|
|
14563
14415
|
}
|
|
14564
|
-
|
|
14565
|
-
|
|
14416
|
+
init(particle) {
|
|
14417
|
+
const rotateOptions = particle.options.rotate;
|
|
14418
|
+
if (!rotateOptions) {
|
|
14566
14419
|
return;
|
|
14567
14420
|
}
|
|
14568
|
-
|
|
14569
|
-
|
|
14570
|
-
|
|
14421
|
+
particle.rotate = {
|
|
14422
|
+
enable: rotateOptions.animation.enable,
|
|
14423
|
+
value: degToRad(getRangeValue(rotateOptions.value)),
|
|
14424
|
+
min: 0,
|
|
14425
|
+
max: doublePI,
|
|
14426
|
+
};
|
|
14427
|
+
particle.pathRotation = rotateOptions.path;
|
|
14428
|
+
let rotateDirection = rotateOptions.direction;
|
|
14429
|
+
if (rotateDirection === exports.RotateDirection.random) {
|
|
14430
|
+
const index = Math.floor(getRandom() * double), minIndex = 0;
|
|
14431
|
+
rotateDirection = index > minIndex ? exports.RotateDirection.counterClockwise : exports.RotateDirection.clockwise;
|
|
14571
14432
|
}
|
|
14572
|
-
|
|
14573
|
-
|
|
14574
|
-
|
|
14433
|
+
switch (rotateDirection) {
|
|
14434
|
+
case exports.RotateDirection.counterClockwise:
|
|
14435
|
+
case "counterClockwise":
|
|
14436
|
+
particle.rotate.status = exports.AnimationStatus.decreasing;
|
|
14437
|
+
break;
|
|
14438
|
+
case exports.RotateDirection.clockwise:
|
|
14439
|
+
particle.rotate.status = exports.AnimationStatus.increasing;
|
|
14440
|
+
break;
|
|
14575
14441
|
}
|
|
14576
|
-
const
|
|
14577
|
-
|
|
14578
|
-
|
|
14579
|
-
|
|
14580
|
-
|
|
14581
|
-
|
|
14582
|
-
|
|
14583
|
-
p2.destroyed ||
|
|
14584
|
-
!p2.links ||
|
|
14585
|
-
p1.links.some(t => t.destination === p2) ||
|
|
14586
|
-
p2.links.some(t => t.destination === p1)) {
|
|
14587
|
-
continue;
|
|
14588
|
-
}
|
|
14589
|
-
const pos2 = p2.getPosition();
|
|
14590
|
-
if (pos2.x < originPoint.x || pos2.y < originPoint.y || pos2.x > canvasSize.width || pos2.y > canvasSize.height) {
|
|
14591
|
-
continue;
|
|
14592
|
-
}
|
|
14593
|
-
const distDirect = getDistances(pos1, pos2).distance, distWarp = warp && linkOpt2.warp ? getWarpDistance(pos1, pos2, canvasSize) : distDirect, distance = Math.min(distDirect, distWarp);
|
|
14594
|
-
if (distance > optDistance) {
|
|
14595
|
-
continue;
|
|
14442
|
+
const rotateAnimation = rotateOptions.animation;
|
|
14443
|
+
if (rotateAnimation.enable) {
|
|
14444
|
+
particle.rotate.decay = identity$3 - getRangeValue(rotateAnimation.decay);
|
|
14445
|
+
particle.rotate.velocity =
|
|
14446
|
+
(getRangeValue(rotateAnimation.speed) / doublePIDeg) * this.#container.retina.reduceFactor;
|
|
14447
|
+
if (!rotateAnimation.sync) {
|
|
14448
|
+
particle.rotate.velocity *= getRandom();
|
|
14596
14449
|
}
|
|
14597
|
-
const opacityLine = (opacityOffset - distance / optDistance) * optOpacity;
|
|
14598
|
-
this.#setColor(p1);
|
|
14599
|
-
p1.links.push({
|
|
14600
|
-
destination: p2,
|
|
14601
|
-
opacity: opacityLine,
|
|
14602
|
-
color: this.#getLinkColor(p1, p2),
|
|
14603
|
-
isWarped: distWarp < distDirect,
|
|
14604
|
-
});
|
|
14605
14450
|
}
|
|
14451
|
+
particle.rotation = particle.rotate.value;
|
|
14606
14452
|
}
|
|
14607
14453
|
isEnabled(particle) {
|
|
14608
|
-
|
|
14609
|
-
|
|
14610
|
-
|
|
14611
|
-
|
|
14454
|
+
const rotate = particle.options.rotate;
|
|
14455
|
+
if (!rotate) {
|
|
14456
|
+
return false;
|
|
14457
|
+
}
|
|
14458
|
+
return !particle.destroyed && !particle.spawning && (!!rotate.value || rotate.animation.enable || rotate.path);
|
|
14612
14459
|
}
|
|
14613
|
-
|
|
14460
|
+
loadOptions(options, ...sources) {
|
|
14461
|
+
loadOptionProperty(options, "rotate", Rotate, ...sources);
|
|
14614
14462
|
}
|
|
14615
|
-
|
|
14616
|
-
|
|
14617
|
-
if (!linksOptions) {
|
|
14463
|
+
update(particle, delta) {
|
|
14464
|
+
if (!this.isEnabled(particle)) {
|
|
14618
14465
|
return;
|
|
14619
14466
|
}
|
|
14620
|
-
|
|
14621
|
-
|
|
14622
|
-
: container.particles.linksColor;
|
|
14623
|
-
return getLinkColor(p1, p2, linkColor);
|
|
14624
|
-
}
|
|
14625
|
-
#setColor(p1) {
|
|
14626
|
-
if (!p1.options.links) {
|
|
14627
|
-
return;
|
|
14628
|
-
}
|
|
14629
|
-
const container = this.container, linksOptions = p1.options.links;
|
|
14630
|
-
let linkColor = linksOptions.id === undefined
|
|
14631
|
-
? container.particles.linksColor
|
|
14632
|
-
: container.particles.linksColors.get(linksOptions.id);
|
|
14633
|
-
if (linkColor) {
|
|
14634
|
-
return;
|
|
14635
|
-
}
|
|
14636
|
-
linkColor = getLinkRandomColor(this.#pluginManager, linksOptions.color, linksOptions.blink, linksOptions.consent);
|
|
14637
|
-
if (linksOptions.id === undefined) {
|
|
14638
|
-
container.particles.linksColor = linkColor;
|
|
14639
|
-
}
|
|
14640
|
-
else {
|
|
14641
|
-
container.particles.linksColors.set(linksOptions.id, linkColor);
|
|
14642
|
-
}
|
|
14643
|
-
}
|
|
14644
|
-
}
|
|
14645
|
-
|
|
14646
|
-
class LinksPlugin {
|
|
14647
|
-
id = "links";
|
|
14648
|
-
#pluginManager;
|
|
14649
|
-
constructor(pluginManager) {
|
|
14650
|
-
this.#pluginManager = pluginManager;
|
|
14651
|
-
}
|
|
14652
|
-
async getPlugin(container) {
|
|
14653
|
-
const { LinkInstance } = await Promise.resolve().then(function () { return LinkInstance$1; });
|
|
14654
|
-
return new LinkInstance(this.#pluginManager, container);
|
|
14655
|
-
}
|
|
14656
|
-
loadOptions() {
|
|
14657
|
-
}
|
|
14658
|
-
needsPlugin() {
|
|
14659
|
-
return true;
|
|
14660
|
-
}
|
|
14661
|
-
}
|
|
14662
|
-
|
|
14663
|
-
async function loadParticlesLinksInteraction(engine) {
|
|
14664
|
-
engine.checkVersion("4.2.1");
|
|
14665
|
-
await engine.pluginManager.register((e) => {
|
|
14666
|
-
const pluginManager = e.pluginManager;
|
|
14667
|
-
ensureInteractivityPluginLoaded(e);
|
|
14668
|
-
pluginManager.addPlugin(new LinksPlugin(pluginManager));
|
|
14669
|
-
pluginManager.addInteractor?.("particlesLinks", container => {
|
|
14670
|
-
return Promise.resolve(new Linker(pluginManager, container));
|
|
14671
|
-
});
|
|
14672
|
-
});
|
|
14673
|
-
}
|
|
14674
|
-
|
|
14675
|
-
const polygonCache = new Map(), noOffset = 0;
|
|
14676
|
-
function getUnitPolygon(sides) {
|
|
14677
|
-
const cached = polygonCache.get(sides);
|
|
14678
|
-
if (cached) {
|
|
14679
|
-
return cached;
|
|
14680
|
-
}
|
|
14681
|
-
const step = doublePI / sides, isOdd = !!(sides % double), baseAngle = (-Math.PI + (isOdd ? noOffset : step)) * half$2, verts = [];
|
|
14682
|
-
for (let i = 0; i < sides; i++) {
|
|
14683
|
-
const angle = baseAngle + i * step;
|
|
14684
|
-
verts[i] = {
|
|
14685
|
-
x: Math.cos(angle),
|
|
14686
|
-
y: Math.sin(angle),
|
|
14687
|
-
};
|
|
14688
|
-
}
|
|
14689
|
-
polygonCache.set(sides, verts);
|
|
14690
|
-
return verts;
|
|
14691
|
-
}
|
|
14692
|
-
function drawPolygon(data, side) {
|
|
14693
|
-
const { context, radius } = data, sides = side.count.numerator / side.count.denominator, verts = getUnitPolygon(sides);
|
|
14694
|
-
context.beginPath();
|
|
14695
|
-
for (let i = 0; i < verts.length; i++) {
|
|
14696
|
-
const vert = verts[i];
|
|
14697
|
-
if (!vert) {
|
|
14698
|
-
continue;
|
|
14699
|
-
}
|
|
14700
|
-
const x = vert.x * radius, y = vert.y * radius;
|
|
14701
|
-
if (i) {
|
|
14702
|
-
context.lineTo(x, y);
|
|
14703
|
-
}
|
|
14704
|
-
else {
|
|
14705
|
-
context.moveTo(x, y);
|
|
14706
|
-
}
|
|
14707
|
-
}
|
|
14708
|
-
context.closePath();
|
|
14709
|
-
}
|
|
14710
|
-
|
|
14711
|
-
const defaultSides$3 = 5;
|
|
14712
|
-
class PolygonDrawerBase {
|
|
14713
|
-
draw(data) {
|
|
14714
|
-
const { particle, radius } = data, side = this.getSidesData(particle, radius);
|
|
14715
|
-
drawPolygon(data, side);
|
|
14716
|
-
}
|
|
14717
|
-
getSidesCount(particle) {
|
|
14718
|
-
const polygon = particle.shapeData;
|
|
14719
|
-
return Math.round(getRangeValue(polygon?.sides ?? defaultSides$3));
|
|
14720
|
-
}
|
|
14721
|
-
}
|
|
14722
|
-
|
|
14723
|
-
const yFactor$1 = 2.66, sidesFactor$1 = 3;
|
|
14724
|
-
class PolygonDrawer extends PolygonDrawerBase {
|
|
14725
|
-
getSidesData(particle, radius) {
|
|
14726
|
-
const { sides } = particle;
|
|
14727
|
-
return {
|
|
14728
|
-
count: {
|
|
14729
|
-
denominator: 1,
|
|
14730
|
-
numerator: sides,
|
|
14731
|
-
},
|
|
14732
|
-
length: (radius * yFactor$1) / (sides / sidesFactor$1),
|
|
14733
|
-
};
|
|
14734
|
-
}
|
|
14735
|
-
}
|
|
14736
|
-
|
|
14737
|
-
const sides$1 = 3, yFactor = 2.66, sidesFactor = 3;
|
|
14738
|
-
class TriangleDrawer extends PolygonDrawerBase {
|
|
14739
|
-
getSidesCount() {
|
|
14740
|
-
return sides$1;
|
|
14741
|
-
}
|
|
14742
|
-
getSidesData(_particle, radius) {
|
|
14743
|
-
return {
|
|
14744
|
-
count: {
|
|
14745
|
-
denominator: 1,
|
|
14746
|
-
numerator: sides$1,
|
|
14747
|
-
},
|
|
14748
|
-
length: (radius * yFactor) / (sides$1 / sidesFactor),
|
|
14749
|
-
};
|
|
14750
|
-
}
|
|
14751
|
-
}
|
|
14752
|
-
|
|
14753
|
-
async function loadGenericPolygonShape(engine) {
|
|
14754
|
-
engine.checkVersion("4.2.1");
|
|
14755
|
-
await engine.pluginManager.register(e => {
|
|
14756
|
-
e.pluginManager.addShape(["polygon"], () => Promise.resolve(new PolygonDrawer()));
|
|
14757
|
-
});
|
|
14758
|
-
}
|
|
14759
|
-
async function loadTriangleShape(engine) {
|
|
14760
|
-
engine.checkVersion("4.2.1");
|
|
14761
|
-
await engine.pluginManager.register(e => {
|
|
14762
|
-
e.pluginManager.addShape(["triangle"], () => Promise.resolve(new TriangleDrawer()));
|
|
14763
|
-
});
|
|
14764
|
-
}
|
|
14765
|
-
async function loadPolygonShape(engine) {
|
|
14766
|
-
engine.checkVersion("4.2.1");
|
|
14767
|
-
await Promise.all([
|
|
14768
|
-
loadGenericPolygonShape(engine),
|
|
14769
|
-
loadTriangleShape(engine),
|
|
14770
|
-
]);
|
|
14771
|
-
}
|
|
14772
|
-
|
|
14773
|
-
class RotateAnimation {
|
|
14774
|
-
decay = 0;
|
|
14775
|
-
enable = false;
|
|
14776
|
-
speed = 0;
|
|
14777
|
-
sync = false;
|
|
14778
|
-
load(data) {
|
|
14779
|
-
if (isNull(data)) {
|
|
14780
|
-
return;
|
|
14781
|
-
}
|
|
14782
|
-
loadProperty(this, "enable", data.enable);
|
|
14783
|
-
loadRangeProperty(this, "speed", data.speed);
|
|
14784
|
-
loadRangeProperty(this, "decay", data.decay);
|
|
14785
|
-
loadProperty(this, "sync", data.sync);
|
|
14786
|
-
}
|
|
14787
|
-
}
|
|
14788
|
-
|
|
14789
|
-
class Rotate extends ValueWithRandom {
|
|
14790
|
-
animation = new RotateAnimation();
|
|
14791
|
-
direction = exports.RotateDirection.clockwise;
|
|
14792
|
-
path = false;
|
|
14793
|
-
load(data) {
|
|
14794
|
-
if (isNull(data)) {
|
|
14795
|
-
return;
|
|
14796
|
-
}
|
|
14797
|
-
super.load(data);
|
|
14798
|
-
loadProperty(this, "direction", data.direction);
|
|
14799
|
-
this.animation.load(data.animation);
|
|
14800
|
-
loadProperty(this, "path", data.path);
|
|
14801
|
-
}
|
|
14802
|
-
}
|
|
14803
|
-
|
|
14804
|
-
const doublePIDeg = 360;
|
|
14805
|
-
class RotateUpdater {
|
|
14806
|
-
#container;
|
|
14807
|
-
constructor(container) {
|
|
14808
|
-
this.#container = container;
|
|
14809
|
-
}
|
|
14810
|
-
init(particle) {
|
|
14811
|
-
const rotateOptions = particle.options.rotate;
|
|
14812
|
-
if (!rotateOptions) {
|
|
14813
|
-
return;
|
|
14814
|
-
}
|
|
14815
|
-
particle.rotate = {
|
|
14816
|
-
enable: rotateOptions.animation.enable,
|
|
14817
|
-
value: degToRad(getRangeValue(rotateOptions.value)),
|
|
14818
|
-
min: 0,
|
|
14819
|
-
max: doublePI,
|
|
14820
|
-
};
|
|
14821
|
-
particle.pathRotation = rotateOptions.path;
|
|
14822
|
-
let rotateDirection = rotateOptions.direction;
|
|
14823
|
-
if (rotateDirection === exports.RotateDirection.random) {
|
|
14824
|
-
const index = Math.floor(getRandom() * double), minIndex = 0;
|
|
14825
|
-
rotateDirection = index > minIndex ? exports.RotateDirection.counterClockwise : exports.RotateDirection.clockwise;
|
|
14826
|
-
}
|
|
14827
|
-
switch (rotateDirection) {
|
|
14828
|
-
case exports.RotateDirection.counterClockwise:
|
|
14829
|
-
case "counterClockwise":
|
|
14830
|
-
particle.rotate.status = exports.AnimationStatus.decreasing;
|
|
14831
|
-
break;
|
|
14832
|
-
case exports.RotateDirection.clockwise:
|
|
14833
|
-
particle.rotate.status = exports.AnimationStatus.increasing;
|
|
14834
|
-
break;
|
|
14835
|
-
}
|
|
14836
|
-
const rotateAnimation = rotateOptions.animation;
|
|
14837
|
-
if (rotateAnimation.enable) {
|
|
14838
|
-
particle.rotate.decay = identity$3 - getRangeValue(rotateAnimation.decay);
|
|
14839
|
-
particle.rotate.velocity =
|
|
14840
|
-
(getRangeValue(rotateAnimation.speed) / doublePIDeg) * this.#container.retina.reduceFactor;
|
|
14841
|
-
if (!rotateAnimation.sync) {
|
|
14842
|
-
particle.rotate.velocity *= getRandom();
|
|
14843
|
-
}
|
|
14844
|
-
}
|
|
14845
|
-
particle.rotation = particle.rotate.value;
|
|
14846
|
-
}
|
|
14847
|
-
isEnabled(particle) {
|
|
14848
|
-
const rotate = particle.options.rotate;
|
|
14849
|
-
if (!rotate) {
|
|
14850
|
-
return false;
|
|
14851
|
-
}
|
|
14852
|
-
return !particle.destroyed && !particle.spawning && (!!rotate.value || rotate.animation.enable || rotate.path);
|
|
14853
|
-
}
|
|
14854
|
-
loadOptions(options, ...sources) {
|
|
14855
|
-
loadOptionProperty(options, "rotate", Rotate, ...sources);
|
|
14856
|
-
}
|
|
14857
|
-
update(particle, delta) {
|
|
14858
|
-
if (!this.isEnabled(particle)) {
|
|
14859
|
-
return;
|
|
14860
|
-
}
|
|
14861
|
-
particle.isRotating = !!particle.rotate;
|
|
14862
|
-
if (!particle.rotate) {
|
|
14467
|
+
particle.isRotating = !!particle.rotate;
|
|
14468
|
+
if (!particle.rotate) {
|
|
14863
14469
|
return;
|
|
14864
14470
|
}
|
|
14865
14471
|
updateAnimation(particle, particle.rotate, false, exports.DestroyType.none, delta);
|
|
@@ -14973,7 +14579,7 @@
|
|
|
14973
14579
|
}
|
|
14974
14580
|
|
|
14975
14581
|
const validTypes = ["text", "character", "char", "multiline-text"];
|
|
14976
|
-
const firstIndex$
|
|
14582
|
+
const firstIndex$3 = 0, minLength$2 = 0;
|
|
14977
14583
|
function drawText(data) {
|
|
14978
14584
|
const { context, particle, fill, stroke, radius, opacity } = data, character = particle.shapeData;
|
|
14979
14585
|
if (!character) {
|
|
@@ -14983,7 +14589,7 @@
|
|
|
14983
14589
|
particle.textLines ??= itemFromSingleOrMultiple(textData, particle.randomIndexData)?.split("\n") ?? [];
|
|
14984
14590
|
particle.maxTextLength ??= particle.textLines.length
|
|
14985
14591
|
? Math.max(...particle.textLines.map(t => t.length))
|
|
14986
|
-
: (particle.textLines[firstIndex$
|
|
14592
|
+
: (particle.textLines[firstIndex$3]?.length ?? minLength$2);
|
|
14987
14593
|
if (!particle.textLines.length || !particle.maxTextLength) {
|
|
14988
14594
|
return;
|
|
14989
14595
|
}
|
|
@@ -15013,7 +14619,7 @@
|
|
|
15013
14619
|
}
|
|
15014
14620
|
}
|
|
15015
14621
|
|
|
15016
|
-
const firstIndex$
|
|
14622
|
+
const firstIndex$2 = 0, minLength$1 = 0;
|
|
15017
14623
|
class TextDrawer {
|
|
15018
14624
|
draw(data) {
|
|
15019
14625
|
drawText(data);
|
|
@@ -15045,7 +14651,7 @@
|
|
|
15045
14651
|
particle.textLines = itemFromSingleOrMultiple(textData, particle.randomIndexData)?.split("\n") ?? [];
|
|
15046
14652
|
particle.maxTextLength = particle.textLines.length
|
|
15047
14653
|
? Math.max(...particle.textLines.map(t => t.length))
|
|
15048
|
-
: (particle.textLines[firstIndex$
|
|
14654
|
+
: (particle.textLines[firstIndex$2]?.length ?? minLength$1);
|
|
15049
14655
|
}
|
|
15050
14656
|
}
|
|
15051
14657
|
|
|
@@ -15143,263 +14749,792 @@
|
|
|
15143
14749
|
}
|
|
15144
14750
|
}
|
|
15145
14751
|
}
|
|
15146
|
-
isEnabled(particle) {
|
|
15147
|
-
const tiltAnimation = particle.options.tilt?.animation;
|
|
15148
|
-
return !particle.destroyed && !particle.spawning && !!tiltAnimation?.enable;
|
|
15149
|
-
}
|
|
15150
|
-
loadOptions(options, ...sources) {
|
|
15151
|
-
loadOptionProperty(options, "tilt", Tilt, ...sources);
|
|
15152
|
-
}
|
|
15153
|
-
update(particle, delta) {
|
|
15154
|
-
if (!this.isEnabled(particle) || !particle.tilt) {
|
|
15155
|
-
return;
|
|
15156
|
-
}
|
|
15157
|
-
updateAnimation(particle, particle.tilt, false, exports.DestroyType.none, delta);
|
|
15158
|
-
}
|
|
15159
|
-
}
|
|
15160
|
-
|
|
15161
|
-
async function loadTiltUpdater(engine) {
|
|
15162
|
-
engine.checkVersion("4.2.1");
|
|
15163
|
-
await engine.pluginManager.register(e => {
|
|
15164
|
-
e.pluginManager.addParticleUpdater("tilt", container => {
|
|
15165
|
-
return Promise.resolve(new TiltUpdater(container));
|
|
15166
|
-
});
|
|
15167
|
-
});
|
|
14752
|
+
isEnabled(particle) {
|
|
14753
|
+
const tiltAnimation = particle.options.tilt?.animation;
|
|
14754
|
+
return !particle.destroyed && !particle.spawning && !!tiltAnimation?.enable;
|
|
14755
|
+
}
|
|
14756
|
+
loadOptions(options, ...sources) {
|
|
14757
|
+
loadOptionProperty(options, "tilt", Tilt, ...sources);
|
|
14758
|
+
}
|
|
14759
|
+
update(particle, delta) {
|
|
14760
|
+
if (!this.isEnabled(particle) || !particle.tilt) {
|
|
14761
|
+
return;
|
|
14762
|
+
}
|
|
14763
|
+
updateAnimation(particle, particle.tilt, false, exports.DestroyType.none, delta);
|
|
14764
|
+
}
|
|
14765
|
+
}
|
|
14766
|
+
|
|
14767
|
+
async function loadTiltUpdater(engine) {
|
|
14768
|
+
engine.checkVersion("4.2.1");
|
|
14769
|
+
await engine.pluginManager.register(e => {
|
|
14770
|
+
e.pluginManager.addParticleUpdater("tilt", container => {
|
|
14771
|
+
return Promise.resolve(new TiltUpdater(container));
|
|
14772
|
+
});
|
|
14773
|
+
});
|
|
14774
|
+
}
|
|
14775
|
+
|
|
14776
|
+
class TwinkleLinksValues {
|
|
14777
|
+
color;
|
|
14778
|
+
enable = false;
|
|
14779
|
+
frequency = 0.05;
|
|
14780
|
+
opacity = 1;
|
|
14781
|
+
load(data) {
|
|
14782
|
+
if (isNull(data)) {
|
|
14783
|
+
return;
|
|
14784
|
+
}
|
|
14785
|
+
if (data.color !== undefined) {
|
|
14786
|
+
this.color = OptionsColor.create(this.color, data.color);
|
|
14787
|
+
}
|
|
14788
|
+
loadProperty(this, "enable", data.enable);
|
|
14789
|
+
loadProperty(this, "frequency", data.frequency);
|
|
14790
|
+
loadRangeProperty(this, "opacity", data.opacity);
|
|
14791
|
+
}
|
|
14792
|
+
}
|
|
14793
|
+
|
|
14794
|
+
class TwinkleParticlesValues {
|
|
14795
|
+
enable = false;
|
|
14796
|
+
fillColor;
|
|
14797
|
+
frequency = 0.05;
|
|
14798
|
+
opacity = 1;
|
|
14799
|
+
strokeColor;
|
|
14800
|
+
load(data) {
|
|
14801
|
+
if (isNull(data)) {
|
|
14802
|
+
return;
|
|
14803
|
+
}
|
|
14804
|
+
if (data.fillColor !== undefined) {
|
|
14805
|
+
this.fillColor = OptionsColor.create(this.fillColor, data.fillColor);
|
|
14806
|
+
}
|
|
14807
|
+
if (data.strokeColor !== undefined) {
|
|
14808
|
+
this.strokeColor = OptionsColor.create(this.strokeColor, data.strokeColor);
|
|
14809
|
+
}
|
|
14810
|
+
loadProperty(this, "enable", data.enable);
|
|
14811
|
+
loadProperty(this, "frequency", data.frequency);
|
|
14812
|
+
loadRangeProperty(this, "opacity", data.opacity);
|
|
14813
|
+
}
|
|
14814
|
+
}
|
|
14815
|
+
|
|
14816
|
+
class Twinkle {
|
|
14817
|
+
links = new TwinkleLinksValues();
|
|
14818
|
+
particles = new TwinkleParticlesValues();
|
|
14819
|
+
load(data) {
|
|
14820
|
+
if (isNull(data)) {
|
|
14821
|
+
return;
|
|
14822
|
+
}
|
|
14823
|
+
this.links.load(data.links);
|
|
14824
|
+
this.particles.load(data.particles);
|
|
14825
|
+
}
|
|
14826
|
+
}
|
|
14827
|
+
|
|
14828
|
+
class TwinkleUpdater {
|
|
14829
|
+
#container;
|
|
14830
|
+
#pluginManager;
|
|
14831
|
+
constructor(pluginManager, container) {
|
|
14832
|
+
this.#pluginManager = pluginManager;
|
|
14833
|
+
this.#container = container;
|
|
14834
|
+
}
|
|
14835
|
+
getColorStyles(particle, _context, _radius, opacity) {
|
|
14836
|
+
const pOptions = particle.options, container = this.#container, twinkleOptions = pOptions["twinkle"];
|
|
14837
|
+
if (!twinkleOptions) {
|
|
14838
|
+
return {};
|
|
14839
|
+
}
|
|
14840
|
+
const twinkle = twinkleOptions.particles, twinkling = twinkle.enable && getRandom() < twinkle.frequency, zIndexOptions = particle.options.zIndex, zOffset = 1, zOpacityFactor = (zOffset - particle.zIndexFactor) ** zIndexOptions.opacityRate, twinklingOpacity = twinkling ? getRangeValue(twinkle.opacity) * zOpacityFactor : opacity, twinkleFillRgb = rangeColorToHsl(this.#pluginManager, twinkle.fillColor), twinkleStrokeRgb = rangeColorToHsl(this.#pluginManager, twinkle.strokeColor), getTwinkleFillStyle = () => {
|
|
14841
|
+
if (!twinkleFillRgb) {
|
|
14842
|
+
return undefined;
|
|
14843
|
+
}
|
|
14844
|
+
return getStyleFromHsl(twinkleFillRgb, container.hdr, twinklingOpacity);
|
|
14845
|
+
}, getTwinkleStrokeStyle = () => {
|
|
14846
|
+
if (!twinkleStrokeRgb) {
|
|
14847
|
+
return undefined;
|
|
14848
|
+
}
|
|
14849
|
+
return getStyleFromHsl(twinkleStrokeRgb, container.hdr, twinklingOpacity);
|
|
14850
|
+
}, twinkleFillStyle = getTwinkleFillStyle(), twinkleStrokeStyle = getTwinkleStrokeStyle(), res = {}, needsTwinkle = twinkling && (!!twinkleFillStyle || !!twinkleStrokeStyle);
|
|
14851
|
+
res.fill = needsTwinkle ? twinkleFillStyle : undefined;
|
|
14852
|
+
res.stroke = needsTwinkle ? twinkleStrokeStyle : undefined;
|
|
14853
|
+
return res;
|
|
14854
|
+
}
|
|
14855
|
+
init() {
|
|
14856
|
+
}
|
|
14857
|
+
isEnabled(particle) {
|
|
14858
|
+
const pOptions = particle.options, twinkleOptions = pOptions.twinkle;
|
|
14859
|
+
if (!twinkleOptions) {
|
|
14860
|
+
return false;
|
|
14861
|
+
}
|
|
14862
|
+
return twinkleOptions.particles.enable;
|
|
14863
|
+
}
|
|
14864
|
+
loadOptions(options, ...sources) {
|
|
14865
|
+
loadOptionProperty(options, "twinkle", Twinkle, ...sources);
|
|
14866
|
+
}
|
|
14867
|
+
update() {
|
|
14868
|
+
}
|
|
14869
|
+
}
|
|
14870
|
+
|
|
14871
|
+
async function loadTwinkleUpdater(engine) {
|
|
14872
|
+
engine.checkVersion("4.2.1");
|
|
14873
|
+
await engine.pluginManager.register(e => {
|
|
14874
|
+
e.pluginManager.addParticleUpdater("twinkle", container => {
|
|
14875
|
+
return Promise.resolve(new TwinkleUpdater(e.pluginManager, container));
|
|
14876
|
+
});
|
|
14877
|
+
});
|
|
14878
|
+
}
|
|
14879
|
+
|
|
14880
|
+
class WobbleSpeed {
|
|
14881
|
+
angle = 50;
|
|
14882
|
+
move = 10;
|
|
14883
|
+
load(data) {
|
|
14884
|
+
if (isNull(data)) {
|
|
14885
|
+
return;
|
|
14886
|
+
}
|
|
14887
|
+
loadRangeProperty(this, "angle", data.angle);
|
|
14888
|
+
loadRangeProperty(this, "move", data.move);
|
|
14889
|
+
}
|
|
14890
|
+
}
|
|
14891
|
+
|
|
14892
|
+
class Wobble {
|
|
14893
|
+
distance = 5;
|
|
14894
|
+
enable = false;
|
|
14895
|
+
speed = new WobbleSpeed();
|
|
14896
|
+
load(data) {
|
|
14897
|
+
if (isNull(data)) {
|
|
14898
|
+
return;
|
|
14899
|
+
}
|
|
14900
|
+
loadRangeProperty(this, "distance", data.distance);
|
|
14901
|
+
loadProperty(this, "enable", data.enable);
|
|
14902
|
+
if (data.speed !== undefined) {
|
|
14903
|
+
if (isNumber(data.speed)) {
|
|
14904
|
+
this.speed.load({ angle: data.speed });
|
|
14905
|
+
}
|
|
14906
|
+
else {
|
|
14907
|
+
const rangeSpeed = data.speed;
|
|
14908
|
+
if ("min" in rangeSpeed) {
|
|
14909
|
+
this.speed.load({ angle: rangeSpeed });
|
|
14910
|
+
}
|
|
14911
|
+
else {
|
|
14912
|
+
this.speed.load(data.speed);
|
|
14913
|
+
}
|
|
14914
|
+
}
|
|
14915
|
+
}
|
|
14916
|
+
}
|
|
14917
|
+
}
|
|
14918
|
+
|
|
14919
|
+
const defaultDistance$1 = 0, distanceFactor = 60;
|
|
14920
|
+
function updateWobble(container, particle, delta) {
|
|
14921
|
+
const { wobble: wobbleOptions } = particle.options, { wobble } = particle;
|
|
14922
|
+
if (!wobbleOptions?.enable || !wobble) {
|
|
14923
|
+
return;
|
|
14924
|
+
}
|
|
14925
|
+
const reduceFactor = container.retina.reduceFactor, angleSpeed = wobble.angleSpeed * delta.factor * reduceFactor, moveSpeed = wobble.moveSpeed * delta.factor * reduceFactor, distance = (moveSpeed * (particle.retina.wobbleDistance ?? defaultDistance$1)) / (millisecondsToSeconds$1 / distanceFactor), max = doublePI, { position } = particle;
|
|
14926
|
+
wobble.angle += angleSpeed;
|
|
14927
|
+
if (wobble.angle > max) {
|
|
14928
|
+
wobble.angle -= max;
|
|
14929
|
+
}
|
|
14930
|
+
position.x += distance * Math.cos(wobble.angle);
|
|
14931
|
+
position.y += distance * Math.abs(Math.sin(wobble.angle));
|
|
14932
|
+
}
|
|
14933
|
+
|
|
14934
|
+
const maxAngle$1 = 360, moveSpeedFactor$1 = 10, defaultDistance = 0;
|
|
14935
|
+
class WobbleUpdater {
|
|
14936
|
+
#container;
|
|
14937
|
+
constructor(container) {
|
|
14938
|
+
this.#container = container;
|
|
14939
|
+
}
|
|
14940
|
+
init(particle) {
|
|
14941
|
+
const wobbleOpt = particle.options.wobble;
|
|
14942
|
+
if (wobbleOpt?.enable) {
|
|
14943
|
+
particle.wobble = {
|
|
14944
|
+
angle: getRandom() * doublePI,
|
|
14945
|
+
angleSpeed: getRangeValue(wobbleOpt.speed.angle) / maxAngle$1,
|
|
14946
|
+
moveSpeed: getRangeValue(wobbleOpt.speed.move) / moveSpeedFactor$1,
|
|
14947
|
+
};
|
|
14948
|
+
}
|
|
14949
|
+
else {
|
|
14950
|
+
particle.wobble = {
|
|
14951
|
+
angle: 0,
|
|
14952
|
+
angleSpeed: 0,
|
|
14953
|
+
moveSpeed: 0,
|
|
14954
|
+
};
|
|
14955
|
+
}
|
|
14956
|
+
particle.retina.wobbleDistance =
|
|
14957
|
+
getRangeValue(wobbleOpt?.distance ?? defaultDistance) * this.#container.retina.pixelRatio;
|
|
14958
|
+
}
|
|
14959
|
+
isEnabled(particle) {
|
|
14960
|
+
return !particle.destroyed && !particle.spawning && !!particle.options.wobble?.enable;
|
|
14961
|
+
}
|
|
14962
|
+
loadOptions(options, ...sources) {
|
|
14963
|
+
loadOptionProperty(options, "wobble", Wobble, ...sources);
|
|
14964
|
+
}
|
|
14965
|
+
update(particle, delta) {
|
|
14966
|
+
if (!this.isEnabled(particle)) {
|
|
14967
|
+
return;
|
|
14968
|
+
}
|
|
14969
|
+
updateWobble(this.#container, particle, delta);
|
|
14970
|
+
}
|
|
14971
|
+
}
|
|
14972
|
+
|
|
14973
|
+
async function loadWobbleUpdater(engine) {
|
|
14974
|
+
engine.checkVersion("4.2.1");
|
|
14975
|
+
await engine.pluginManager.register(e => {
|
|
14976
|
+
e.pluginManager.addParticleUpdater("wobble", container => {
|
|
14977
|
+
return Promise.resolve(new WobbleUpdater(container));
|
|
14978
|
+
});
|
|
14979
|
+
});
|
|
14980
|
+
}
|
|
14981
|
+
|
|
14982
|
+
async function loadFull(engine) {
|
|
14983
|
+
engine.checkVersion("4.2.1");
|
|
14984
|
+
await engine.pluginManager.register(async (e) => {
|
|
14985
|
+
const loadEmittersPluginBundle = async (e) => {
|
|
14986
|
+
await loadEmittersPlugin(e);
|
|
14987
|
+
await Promise.all([
|
|
14988
|
+
loadEmittersShapeCircle(e),
|
|
14989
|
+
loadEmittersShapeSquare(e),
|
|
14990
|
+
]);
|
|
14991
|
+
}, loadInteractivityForFull = async (e) => {
|
|
14992
|
+
await loadSlim(e);
|
|
14993
|
+
await Promise.all([
|
|
14994
|
+
loadExternalDragInteraction(e),
|
|
14995
|
+
loadExternalTrailInteraction(e),
|
|
14996
|
+
loadAbsorbersPlugin(e),
|
|
14997
|
+
loadEmittersPluginBundle(e),
|
|
14998
|
+
]);
|
|
14999
|
+
};
|
|
15000
|
+
await Promise.all([
|
|
15001
|
+
loadInteractivityForFull(e),
|
|
15002
|
+
loadDestroyUpdater(e),
|
|
15003
|
+
loadRollUpdater(e),
|
|
15004
|
+
loadTiltUpdater(e),
|
|
15005
|
+
loadTwinkleUpdater(e),
|
|
15006
|
+
loadWobbleUpdater(e),
|
|
15007
|
+
loadTextShape(e),
|
|
15008
|
+
]);
|
|
15009
|
+
});
|
|
15010
|
+
}
|
|
15011
|
+
|
|
15012
|
+
const InterlaceOffsets = [0, 4, 2, 1];
|
|
15013
|
+
const InterlaceSteps = [8, 8, 4, 2];
|
|
15014
|
+
|
|
15015
|
+
class ByteStream {
|
|
15016
|
+
data;
|
|
15017
|
+
pos;
|
|
15018
|
+
constructor(bytes) {
|
|
15019
|
+
this.pos = 0;
|
|
15020
|
+
this.data = new Uint8ClampedArray(bytes);
|
|
15021
|
+
}
|
|
15022
|
+
getString(count) {
|
|
15023
|
+
const slice = this.data.slice(this.pos, this.pos + count);
|
|
15024
|
+
this.pos += slice.length;
|
|
15025
|
+
return slice.reduce((acc, curr) => acc + String.fromCharCode(curr), "");
|
|
15026
|
+
}
|
|
15027
|
+
nextByte() {
|
|
15028
|
+
return this.data[this.pos++];
|
|
15029
|
+
}
|
|
15030
|
+
nextTwoBytes() {
|
|
15031
|
+
const increment = 2, previous = 1, shift = 8;
|
|
15032
|
+
this.pos += increment;
|
|
15033
|
+
return this.data[this.pos - increment] + (this.data[this.pos - previous] << shift);
|
|
15034
|
+
}
|
|
15035
|
+
readSubBlocks() {
|
|
15036
|
+
let blockString = "", size;
|
|
15037
|
+
const minCount = 0, emptySize = 0;
|
|
15038
|
+
do {
|
|
15039
|
+
size = this.data[this.pos++];
|
|
15040
|
+
for (let count = size; --count >= minCount; blockString += String.fromCharCode(this.data[this.pos++])) {
|
|
15041
|
+
}
|
|
15042
|
+
} while (size !== emptySize);
|
|
15043
|
+
return blockString;
|
|
15044
|
+
}
|
|
15045
|
+
readSubBlocksBin() {
|
|
15046
|
+
let size = this.data[this.pos], len = 0;
|
|
15047
|
+
const emptySize = 0, increment = 1;
|
|
15048
|
+
for (let offset = 0; size !== emptySize; offset += size + increment, size = this.data[this.pos + offset]) {
|
|
15049
|
+
len += size;
|
|
15050
|
+
}
|
|
15051
|
+
const blockData = new Uint8Array(len);
|
|
15052
|
+
size = this.data[this.pos++];
|
|
15053
|
+
for (let i = 0; size !== emptySize; size = this.data[this.pos++]) {
|
|
15054
|
+
for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {
|
|
15055
|
+
}
|
|
15056
|
+
}
|
|
15057
|
+
return blockData;
|
|
15058
|
+
}
|
|
15059
|
+
skipSubBlocks() {
|
|
15060
|
+
for (const increment = 1, noData = 0; this.data[this.pos] !== noData; this.pos += this.data[this.pos] + increment) {
|
|
15061
|
+
}
|
|
15062
|
+
this.pos++;
|
|
15063
|
+
}
|
|
15064
|
+
}
|
|
15065
|
+
|
|
15066
|
+
var DisposalMethod;
|
|
15067
|
+
(function (DisposalMethod) {
|
|
15068
|
+
DisposalMethod[DisposalMethod["Replace"] = 0] = "Replace";
|
|
15069
|
+
DisposalMethod[DisposalMethod["Combine"] = 1] = "Combine";
|
|
15070
|
+
DisposalMethod[DisposalMethod["RestoreBackground"] = 2] = "RestoreBackground";
|
|
15071
|
+
DisposalMethod[DisposalMethod["RestorePrevious"] = 3] = "RestorePrevious";
|
|
15072
|
+
DisposalMethod[DisposalMethod["UndefinedA"] = 4] = "UndefinedA";
|
|
15073
|
+
DisposalMethod[DisposalMethod["UndefinedB"] = 5] = "UndefinedB";
|
|
15074
|
+
DisposalMethod[DisposalMethod["UndefinedC"] = 6] = "UndefinedC";
|
|
15075
|
+
DisposalMethod[DisposalMethod["UndefinedD"] = 7] = "UndefinedD";
|
|
15076
|
+
})(DisposalMethod || (DisposalMethod = {}));
|
|
15077
|
+
|
|
15078
|
+
var GIFDataHeaders;
|
|
15079
|
+
(function (GIFDataHeaders) {
|
|
15080
|
+
GIFDataHeaders[GIFDataHeaders["Extension"] = 33] = "Extension";
|
|
15081
|
+
GIFDataHeaders[GIFDataHeaders["ApplicationExtension"] = 255] = "ApplicationExtension";
|
|
15082
|
+
GIFDataHeaders[GIFDataHeaders["GraphicsControlExtension"] = 249] = "GraphicsControlExtension";
|
|
15083
|
+
GIFDataHeaders[GIFDataHeaders["PlainTextExtension"] = 1] = "PlainTextExtension";
|
|
15084
|
+
GIFDataHeaders[GIFDataHeaders["CommentExtension"] = 254] = "CommentExtension";
|
|
15085
|
+
GIFDataHeaders[GIFDataHeaders["Image"] = 44] = "Image";
|
|
15086
|
+
GIFDataHeaders[GIFDataHeaders["EndOfFile"] = 59] = "EndOfFile";
|
|
15087
|
+
})(GIFDataHeaders || (GIFDataHeaders = {}));
|
|
15088
|
+
|
|
15089
|
+
const defaultFrame = 0, initialTime = 0, firstIndex$1 = 0, defaultLoopCount = 0;
|
|
15090
|
+
function parseColorTable(byteStream, count) {
|
|
15091
|
+
const colors = [];
|
|
15092
|
+
for (let i = 0; i < count; i++) {
|
|
15093
|
+
colors.push({
|
|
15094
|
+
r: byteStream.data[byteStream.pos],
|
|
15095
|
+
g: byteStream.data[byteStream.pos + 1],
|
|
15096
|
+
b: byteStream.data[byteStream.pos + 2],
|
|
15097
|
+
});
|
|
15098
|
+
byteStream.pos += 3;
|
|
15099
|
+
}
|
|
15100
|
+
return colors;
|
|
15101
|
+
}
|
|
15102
|
+
function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
|
|
15103
|
+
switch (byteStream.nextByte()) {
|
|
15104
|
+
case GIFDataHeaders.GraphicsControlExtension: {
|
|
15105
|
+
const frame = gif.frames[getFrameIndex(false)];
|
|
15106
|
+
byteStream.pos++;
|
|
15107
|
+
const packedByte = byteStream.nextByte();
|
|
15108
|
+
frame.GCreserved = (packedByte & 0xe0) >>> 5;
|
|
15109
|
+
frame.disposalMethod = (packedByte & 0x1c) >>> 2;
|
|
15110
|
+
frame.userInputDelayFlag = (packedByte & 2) === 2;
|
|
15111
|
+
const transparencyFlag = (packedByte & 1) === 1;
|
|
15112
|
+
frame.delayTime = byteStream.nextTwoBytes() * 0xa;
|
|
15113
|
+
const transparencyIndex = byteStream.nextByte();
|
|
15114
|
+
if (transparencyFlag) {
|
|
15115
|
+
getTransparencyIndex(transparencyIndex);
|
|
15116
|
+
}
|
|
15117
|
+
byteStream.pos++;
|
|
15118
|
+
break;
|
|
15119
|
+
}
|
|
15120
|
+
case GIFDataHeaders.ApplicationExtension: {
|
|
15121
|
+
byteStream.pos++;
|
|
15122
|
+
const applicationExtension = {
|
|
15123
|
+
identifier: byteStream.getString(8),
|
|
15124
|
+
authenticationCode: byteStream.getString(3),
|
|
15125
|
+
data: byteStream.readSubBlocksBin(),
|
|
15126
|
+
};
|
|
15127
|
+
gif.applicationExtensions.push(applicationExtension);
|
|
15128
|
+
break;
|
|
15129
|
+
}
|
|
15130
|
+
case GIFDataHeaders.CommentExtension: {
|
|
15131
|
+
gif.comments.push([getFrameIndex(false), byteStream.readSubBlocks()]);
|
|
15132
|
+
break;
|
|
15133
|
+
}
|
|
15134
|
+
case GIFDataHeaders.PlainTextExtension: {
|
|
15135
|
+
if (gif.globalColorTable.length === 0) {
|
|
15136
|
+
throw new EvalError("plain text extension without global color table");
|
|
15137
|
+
}
|
|
15138
|
+
byteStream.pos++;
|
|
15139
|
+
gif.frames[getFrameIndex(false)].plainTextData = {
|
|
15140
|
+
left: byteStream.nextTwoBytes(),
|
|
15141
|
+
top: byteStream.nextTwoBytes(),
|
|
15142
|
+
width: byteStream.nextTwoBytes(),
|
|
15143
|
+
height: byteStream.nextTwoBytes(),
|
|
15144
|
+
charSize: {
|
|
15145
|
+
width: byteStream.nextTwoBytes(),
|
|
15146
|
+
height: byteStream.nextTwoBytes(),
|
|
15147
|
+
},
|
|
15148
|
+
foregroundColor: byteStream.nextByte(),
|
|
15149
|
+
backgroundColor: byteStream.nextByte(),
|
|
15150
|
+
text: byteStream.readSubBlocks(),
|
|
15151
|
+
};
|
|
15152
|
+
break;
|
|
15153
|
+
}
|
|
15154
|
+
default:
|
|
15155
|
+
byteStream.skipSubBlocks();
|
|
15156
|
+
break;
|
|
15157
|
+
}
|
|
15158
|
+
}
|
|
15159
|
+
function readBits(imageData, pos, len) {
|
|
15160
|
+
const bytePos = pos >>> 3, bitPos = pos & 7;
|
|
15161
|
+
return (((imageData[bytePos] + (imageData[bytePos + 1] << 8) + (imageData[bytePos + 2] << 16)) &
|
|
15162
|
+
(((1 << len) - 1) << bitPos)) >>>
|
|
15163
|
+
bitPos);
|
|
15164
|
+
}
|
|
15165
|
+
async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, canvasSettings, progressCallback) {
|
|
15166
|
+
const frame = gif.frames[getFrameIndex(true)];
|
|
15167
|
+
frame.left = byteStream.nextTwoBytes();
|
|
15168
|
+
frame.top = byteStream.nextTwoBytes();
|
|
15169
|
+
frame.width = byteStream.nextTwoBytes();
|
|
15170
|
+
frame.height = byteStream.nextTwoBytes();
|
|
15171
|
+
const packedByte = byteStream.nextByte(), localColorTableFlag = (packedByte & 0x80) === 0x80, interlacedFlag = (packedByte & 0x40) === 0x40;
|
|
15172
|
+
frame.sortFlag = (packedByte & 0x20) === 0x20;
|
|
15173
|
+
frame.reserved = (packedByte & 0x18) >>> 3;
|
|
15174
|
+
const localColorCount = 1 << ((packedByte & 7) + 1);
|
|
15175
|
+
if (localColorTableFlag) {
|
|
15176
|
+
frame.localColorTable = parseColorTable(byteStream, localColorCount);
|
|
15177
|
+
}
|
|
15178
|
+
const getColor = (index) => {
|
|
15179
|
+
const { r, g, b } = (localColorTableFlag ? frame.localColorTable : gif.globalColorTable)[index];
|
|
15180
|
+
if (index !== getTransparencyIndex(null)) {
|
|
15181
|
+
return { r, g, b, a: 255 };
|
|
15182
|
+
}
|
|
15183
|
+
return { r, g, b, a: avgAlpha ? Math.trunc((r + g + b) / 3) : 0 };
|
|
15184
|
+
}, image = (() => {
|
|
15185
|
+
try {
|
|
15186
|
+
return new ImageData(frame.width, frame.height, canvasSettings);
|
|
15187
|
+
}
|
|
15188
|
+
catch (error) {
|
|
15189
|
+
if (error instanceof DOMException && error.name === "IndexSizeError") {
|
|
15190
|
+
return null;
|
|
15191
|
+
}
|
|
15192
|
+
throw error;
|
|
15193
|
+
}
|
|
15194
|
+
})();
|
|
15195
|
+
if (image == null) {
|
|
15196
|
+
throw new EvalError("GIF frame size is to large");
|
|
15197
|
+
}
|
|
15198
|
+
const minCodeSize = byteStream.nextByte(), imageData = byteStream.readSubBlocksBin(), clearCode = 1 << minCodeSize;
|
|
15199
|
+
if (interlacedFlag) {
|
|
15200
|
+
for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {
|
|
15201
|
+
if (InterlaceOffsets[pass] < frame.height) {
|
|
15202
|
+
let pixelPos = 0, lineIndex = 0, exit = false;
|
|
15203
|
+
while (!exit) {
|
|
15204
|
+
const last = code;
|
|
15205
|
+
code = readBits(imageData, pos, size);
|
|
15206
|
+
pos += size + 1;
|
|
15207
|
+
if (code === clearCode) {
|
|
15208
|
+
size = minCodeSize + 1;
|
|
15209
|
+
dic.length = clearCode + 2;
|
|
15210
|
+
for (let i = 0; i < dic.length; i++) {
|
|
15211
|
+
dic[i] = i < clearCode ? [i] : [];
|
|
15212
|
+
}
|
|
15213
|
+
}
|
|
15214
|
+
else {
|
|
15215
|
+
if (code >= dic.length) {
|
|
15216
|
+
dic.push(dic[last].concat(dic[last][0]));
|
|
15217
|
+
}
|
|
15218
|
+
else if (last !== clearCode) {
|
|
15219
|
+
dic.push(dic[last].concat(dic[code][0]));
|
|
15220
|
+
}
|
|
15221
|
+
for (const item of dic[code]) {
|
|
15222
|
+
const { r, g, b, a } = getColor(item);
|
|
15223
|
+
image.data.set([r, g, b, a], InterlaceOffsets[pass] * frame.width +
|
|
15224
|
+
InterlaceSteps[pass] * lineIndex +
|
|
15225
|
+
(pixelPos % (frame.width * 4)));
|
|
15226
|
+
pixelPos += 4;
|
|
15227
|
+
}
|
|
15228
|
+
if (dic.length === 1 << size && size < 0xc) {
|
|
15229
|
+
size++;
|
|
15230
|
+
}
|
|
15231
|
+
}
|
|
15232
|
+
if (pixelPos === frame.width * 4 * (lineIndex + 1)) {
|
|
15233
|
+
lineIndex++;
|
|
15234
|
+
if (InterlaceOffsets[pass] + InterlaceSteps[pass] * lineIndex >= frame.height) {
|
|
15235
|
+
exit = true;
|
|
15236
|
+
}
|
|
15237
|
+
}
|
|
15238
|
+
}
|
|
15239
|
+
}
|
|
15240
|
+
}
|
|
15241
|
+
frame.image = image;
|
|
15242
|
+
frame.bitmap = await createImageBitmap(image);
|
|
15243
|
+
}
|
|
15244
|
+
else {
|
|
15245
|
+
let code = 0, size = minCodeSize + 1, pos = 0, pixelPos = -4;
|
|
15246
|
+
const dic = [[0]];
|
|
15247
|
+
for (;;) {
|
|
15248
|
+
const last = code;
|
|
15249
|
+
code = readBits(imageData, pos, size);
|
|
15250
|
+
pos += size;
|
|
15251
|
+
if (code === clearCode) {
|
|
15252
|
+
size = minCodeSize + 1;
|
|
15253
|
+
dic.length = clearCode + 2;
|
|
15254
|
+
for (let i = 0; i < dic.length; i++) {
|
|
15255
|
+
dic[i] = i < clearCode ? [i] : [];
|
|
15256
|
+
}
|
|
15257
|
+
}
|
|
15258
|
+
else {
|
|
15259
|
+
if (code === clearCode + 1) {
|
|
15260
|
+
break;
|
|
15261
|
+
}
|
|
15262
|
+
if (code >= dic.length) {
|
|
15263
|
+
dic.push(dic[last].concat(dic[last][0]));
|
|
15264
|
+
}
|
|
15265
|
+
else if (last !== clearCode) {
|
|
15266
|
+
dic.push(dic[last].concat(dic[code][0]));
|
|
15267
|
+
}
|
|
15268
|
+
for (const item of dic[code]) {
|
|
15269
|
+
const { r, g, b, a } = getColor(item);
|
|
15270
|
+
pixelPos += 4;
|
|
15271
|
+
image.data.set([r, g, b, a], pixelPos);
|
|
15272
|
+
}
|
|
15273
|
+
if (dic.length >= 1 << size && size < 0xc) {
|
|
15274
|
+
size++;
|
|
15275
|
+
}
|
|
15276
|
+
}
|
|
15277
|
+
}
|
|
15278
|
+
frame.image = image;
|
|
15279
|
+
frame.bitmap = await createImageBitmap(image);
|
|
15280
|
+
}
|
|
15168
15281
|
}
|
|
15169
|
-
|
|
15170
|
-
|
|
15171
|
-
|
|
15172
|
-
|
|
15173
|
-
|
|
15174
|
-
|
|
15175
|
-
|
|
15176
|
-
|
|
15177
|
-
|
|
15178
|
-
|
|
15179
|
-
|
|
15180
|
-
|
|
15181
|
-
}
|
|
15182
|
-
loadProperty(this, "enable", data.enable);
|
|
15183
|
-
loadProperty(this, "frequency", data.frequency);
|
|
15184
|
-
loadRangeProperty(this, "opacity", data.opacity);
|
|
15282
|
+
async function parseBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, canvasSettings, progressCallback) {
|
|
15283
|
+
switch (byteStream.nextByte()) {
|
|
15284
|
+
case GIFDataHeaders.EndOfFile:
|
|
15285
|
+
return true;
|
|
15286
|
+
case GIFDataHeaders.Image:
|
|
15287
|
+
await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, canvasSettings);
|
|
15288
|
+
break;
|
|
15289
|
+
case GIFDataHeaders.Extension:
|
|
15290
|
+
parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
|
|
15291
|
+
break;
|
|
15292
|
+
default:
|
|
15293
|
+
throw new EvalError("undefined block found");
|
|
15185
15294
|
}
|
|
15295
|
+
return false;
|
|
15186
15296
|
}
|
|
15187
|
-
|
|
15188
|
-
|
|
15189
|
-
|
|
15190
|
-
|
|
15191
|
-
frequency = 0.05;
|
|
15192
|
-
opacity = 1;
|
|
15193
|
-
strokeColor;
|
|
15194
|
-
load(data) {
|
|
15195
|
-
if (isNull(data)) {
|
|
15196
|
-
return;
|
|
15197
|
-
}
|
|
15198
|
-
if (data.fillColor !== undefined) {
|
|
15199
|
-
this.fillColor = OptionsColor.create(this.fillColor, data.fillColor);
|
|
15200
|
-
}
|
|
15201
|
-
if (data.strokeColor !== undefined) {
|
|
15202
|
-
this.strokeColor = OptionsColor.create(this.strokeColor, data.strokeColor);
|
|
15297
|
+
function getGIFLoopAmount(gif) {
|
|
15298
|
+
for (const extension of gif.applicationExtensions) {
|
|
15299
|
+
if (extension.identifier + extension.authenticationCode !== "NETSCAPE2.0") {
|
|
15300
|
+
continue;
|
|
15203
15301
|
}
|
|
15204
|
-
|
|
15205
|
-
loadProperty(this, "frequency", data.frequency);
|
|
15206
|
-
loadRangeProperty(this, "opacity", data.opacity);
|
|
15302
|
+
return extension.data[1] + (extension.data[2] << 8);
|
|
15207
15303
|
}
|
|
15304
|
+
return Number.NaN;
|
|
15208
15305
|
}
|
|
15209
|
-
|
|
15210
|
-
|
|
15211
|
-
|
|
15212
|
-
|
|
15213
|
-
|
|
15214
|
-
if (isNull(data)) {
|
|
15215
|
-
return;
|
|
15216
|
-
}
|
|
15217
|
-
this.links.load(data.links);
|
|
15218
|
-
this.particles.load(data.particles);
|
|
15306
|
+
async function decodeGIF(gifURL, canvasSettings, progressCallback, avgAlpha) {
|
|
15307
|
+
avgAlpha ??= false;
|
|
15308
|
+
const res = await fetch(gifURL);
|
|
15309
|
+
if (!res.ok && res.status === 404) {
|
|
15310
|
+
throw new EvalError("file not found");
|
|
15219
15311
|
}
|
|
15220
|
-
|
|
15221
|
-
|
|
15222
|
-
|
|
15223
|
-
|
|
15224
|
-
|
|
15225
|
-
|
|
15226
|
-
|
|
15227
|
-
|
|
15312
|
+
const buffer = await res.arrayBuffer(), gif = {
|
|
15313
|
+
width: 0,
|
|
15314
|
+
height: 0,
|
|
15315
|
+
totalTime: 0,
|
|
15316
|
+
colorRes: 0,
|
|
15317
|
+
pixelAspectRatio: 0,
|
|
15318
|
+
frames: [],
|
|
15319
|
+
sortFlag: false,
|
|
15320
|
+
globalColorTable: [],
|
|
15321
|
+
backgroundImage: new ImageData(1, 1, canvasSettings),
|
|
15322
|
+
comments: [],
|
|
15323
|
+
applicationExtensions: [],
|
|
15324
|
+
}, byteStream = new ByteStream(new Uint8ClampedArray(buffer));
|
|
15325
|
+
if (byteStream.getString(6) !== "GIF89a") {
|
|
15326
|
+
throw new Error("not a supported GIF file");
|
|
15228
15327
|
}
|
|
15229
|
-
|
|
15230
|
-
|
|
15231
|
-
|
|
15232
|
-
|
|
15233
|
-
|
|
15234
|
-
|
|
15235
|
-
|
|
15236
|
-
|
|
15237
|
-
|
|
15238
|
-
return getStyleFromHsl(twinkleFillRgb, container.hdr, twinklingOpacity);
|
|
15239
|
-
}, getTwinkleStrokeStyle = () => {
|
|
15240
|
-
if (!twinkleStrokeRgb) {
|
|
15241
|
-
return undefined;
|
|
15242
|
-
}
|
|
15243
|
-
return getStyleFromHsl(twinkleStrokeRgb, container.hdr, twinklingOpacity);
|
|
15244
|
-
}, twinkleFillStyle = getTwinkleFillStyle(), twinkleStrokeStyle = getTwinkleStrokeStyle(), res = {}, needsTwinkle = twinkling && (!!twinkleFillStyle || !!twinkleStrokeStyle);
|
|
15245
|
-
res.fill = needsTwinkle ? twinkleFillStyle : undefined;
|
|
15246
|
-
res.stroke = needsTwinkle ? twinkleStrokeStyle : undefined;
|
|
15247
|
-
return res;
|
|
15328
|
+
gif.width = byteStream.nextTwoBytes();
|
|
15329
|
+
gif.height = byteStream.nextTwoBytes();
|
|
15330
|
+
const packedByte = byteStream.nextByte(), globalColorTableFlag = (packedByte & 0x80) === 0x80;
|
|
15331
|
+
gif.colorRes = (packedByte & 0x70) >>> 4;
|
|
15332
|
+
gif.sortFlag = (packedByte & 8) === 8;
|
|
15333
|
+
const globalColorCount = 1 << ((packedByte & 7) + 1), backgroundColorIndex = byteStream.nextByte();
|
|
15334
|
+
gif.pixelAspectRatio = byteStream.nextByte();
|
|
15335
|
+
if (gif.pixelAspectRatio !== 0) {
|
|
15336
|
+
gif.pixelAspectRatio = (gif.pixelAspectRatio + 0xf) / 0x40;
|
|
15248
15337
|
}
|
|
15249
|
-
|
|
15338
|
+
if (globalColorTableFlag) {
|
|
15339
|
+
gif.globalColorTable = parseColorTable(byteStream, globalColorCount);
|
|
15250
15340
|
}
|
|
15251
|
-
|
|
15252
|
-
|
|
15253
|
-
|
|
15254
|
-
return false;
|
|
15341
|
+
const backgroundImage = (() => {
|
|
15342
|
+
try {
|
|
15343
|
+
return new ImageData(gif.width, gif.height, canvasSettings);
|
|
15255
15344
|
}
|
|
15256
|
-
|
|
15257
|
-
|
|
15258
|
-
|
|
15259
|
-
|
|
15345
|
+
catch (error) {
|
|
15346
|
+
if (error instanceof DOMException && error.name === "IndexSizeError") {
|
|
15347
|
+
return null;
|
|
15348
|
+
}
|
|
15349
|
+
throw error;
|
|
15350
|
+
}
|
|
15351
|
+
})();
|
|
15352
|
+
if (backgroundImage == null) {
|
|
15353
|
+
throw new Error("GIF frame size is to large");
|
|
15260
15354
|
}
|
|
15261
|
-
|
|
15355
|
+
const { r, g, b } = gif.globalColorTable[backgroundColorIndex];
|
|
15356
|
+
backgroundImage.data.set(globalColorTableFlag ? [r, g, b, 255] : [0, 0, 0, 0]);
|
|
15357
|
+
for (let i = 4; i < backgroundImage.data.length; i *= 2) {
|
|
15358
|
+
backgroundImage.data.copyWithin(i, 0, i);
|
|
15262
15359
|
}
|
|
15263
|
-
|
|
15264
|
-
|
|
15265
|
-
|
|
15266
|
-
|
|
15267
|
-
|
|
15268
|
-
e.pluginManager.addParticleUpdater("twinkle", container => {
|
|
15269
|
-
return Promise.resolve(new TwinkleUpdater(e.pluginManager, container));
|
|
15270
|
-
});
|
|
15271
|
-
});
|
|
15272
|
-
}
|
|
15273
|
-
|
|
15274
|
-
class WobbleSpeed {
|
|
15275
|
-
angle = 50;
|
|
15276
|
-
move = 10;
|
|
15277
|
-
load(data) {
|
|
15278
|
-
if (isNull(data)) {
|
|
15279
|
-
return;
|
|
15360
|
+
gif.backgroundImage = backgroundImage;
|
|
15361
|
+
let frameIndex = -1, incrementFrameIndex = true, transparencyIndex = -1;
|
|
15362
|
+
const getframeIndex = (increment) => {
|
|
15363
|
+
if (increment) {
|
|
15364
|
+
incrementFrameIndex = true;
|
|
15280
15365
|
}
|
|
15281
|
-
|
|
15282
|
-
|
|
15283
|
-
|
|
15284
|
-
|
|
15285
|
-
|
|
15286
|
-
class Wobble {
|
|
15287
|
-
distance = 5;
|
|
15288
|
-
enable = false;
|
|
15289
|
-
speed = new WobbleSpeed();
|
|
15290
|
-
load(data) {
|
|
15291
|
-
if (isNull(data)) {
|
|
15292
|
-
return;
|
|
15366
|
+
return frameIndex;
|
|
15367
|
+
}, getTransparencyIndex = (newValue) => {
|
|
15368
|
+
if (newValue != null) {
|
|
15369
|
+
transparencyIndex = newValue;
|
|
15293
15370
|
}
|
|
15294
|
-
|
|
15295
|
-
|
|
15296
|
-
|
|
15297
|
-
|
|
15298
|
-
|
|
15371
|
+
return transparencyIndex;
|
|
15372
|
+
};
|
|
15373
|
+
try {
|
|
15374
|
+
do {
|
|
15375
|
+
if (incrementFrameIndex) {
|
|
15376
|
+
gif.frames.push({
|
|
15377
|
+
left: 0,
|
|
15378
|
+
top: 0,
|
|
15379
|
+
width: 0,
|
|
15380
|
+
height: 0,
|
|
15381
|
+
disposalMethod: DisposalMethod.Replace,
|
|
15382
|
+
image: new ImageData(1, 1, canvasSettings),
|
|
15383
|
+
plainTextData: null,
|
|
15384
|
+
userInputDelayFlag: false,
|
|
15385
|
+
delayTime: 0,
|
|
15386
|
+
sortFlag: false,
|
|
15387
|
+
localColorTable: [],
|
|
15388
|
+
reserved: 0,
|
|
15389
|
+
GCreserved: 0,
|
|
15390
|
+
});
|
|
15391
|
+
frameIndex++;
|
|
15392
|
+
transparencyIndex = -1;
|
|
15393
|
+
incrementFrameIndex = false;
|
|
15299
15394
|
}
|
|
15300
|
-
|
|
15301
|
-
|
|
15302
|
-
|
|
15303
|
-
|
|
15304
|
-
|
|
15305
|
-
|
|
15306
|
-
this.speed.load(data.speed);
|
|
15307
|
-
}
|
|
15395
|
+
} while (!(await parseBlock(byteStream, gif, avgAlpha, getframeIndex, getTransparencyIndex, canvasSettings, progressCallback)));
|
|
15396
|
+
gif.frames.length--;
|
|
15397
|
+
for (const frame of gif.frames) {
|
|
15398
|
+
if (frame.userInputDelayFlag && frame.delayTime === 0) {
|
|
15399
|
+
gif.totalTime = Infinity;
|
|
15400
|
+
break;
|
|
15308
15401
|
}
|
|
15402
|
+
gif.totalTime += frame.delayTime;
|
|
15403
|
+
}
|
|
15404
|
+
return gif;
|
|
15405
|
+
}
|
|
15406
|
+
catch (error) {
|
|
15407
|
+
if (error instanceof EvalError) {
|
|
15408
|
+
throw new Error(`error while parsing frame ${frameIndex.toString()} "${error.message}"`, { cause: error });
|
|
15309
15409
|
}
|
|
15410
|
+
throw error;
|
|
15310
15411
|
}
|
|
15311
15412
|
}
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
|
|
15315
|
-
const { wobble: wobbleOptions } = particle.options, { wobble } = particle;
|
|
15316
|
-
if (!wobbleOptions?.enable || !wobble) {
|
|
15413
|
+
function drawGif(data, canvasSettings) {
|
|
15414
|
+
const { context, radius, particle, delta } = data, gifData = particle.gifData;
|
|
15415
|
+
if (!gifData) {
|
|
15317
15416
|
return;
|
|
15318
15417
|
}
|
|
15319
|
-
const
|
|
15320
|
-
|
|
15321
|
-
|
|
15322
|
-
wobble.angle -= max;
|
|
15418
|
+
const offscreenCanvas = new OffscreenCanvas(gifData.width, gifData.height), offscreenContext = offscreenCanvas.getContext("2d", canvasSettings);
|
|
15419
|
+
if (!offscreenContext) {
|
|
15420
|
+
throw new Error("could not create offscreen canvas context");
|
|
15323
15421
|
}
|
|
15324
|
-
|
|
15325
|
-
|
|
15422
|
+
offscreenContext.imageSmoothingQuality = "low";
|
|
15423
|
+
offscreenContext.imageSmoothingEnabled = false;
|
|
15424
|
+
offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
15425
|
+
let frameIndex = particle.gifFrame ?? defaultFrame;
|
|
15426
|
+
const pos = { x: -gifData.width * half$2, y: -gifData.height * half$2 }, frame = gifData.frames[frameIndex];
|
|
15427
|
+
particle.gifTime ??= initialTime;
|
|
15428
|
+
if (!frame.bitmap) {
|
|
15429
|
+
return;
|
|
15430
|
+
}
|
|
15431
|
+
context.scale(radius / gifData.width, radius / gifData.height);
|
|
15432
|
+
switch (frame.disposalMethod) {
|
|
15433
|
+
case DisposalMethod.UndefinedA:
|
|
15434
|
+
case DisposalMethod.UndefinedB:
|
|
15435
|
+
case DisposalMethod.UndefinedC:
|
|
15436
|
+
case DisposalMethod.UndefinedD:
|
|
15437
|
+
case DisposalMethod.Replace:
|
|
15438
|
+
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
15439
|
+
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
15440
|
+
offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
15441
|
+
break;
|
|
15442
|
+
case DisposalMethod.Combine:
|
|
15443
|
+
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
15444
|
+
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
15445
|
+
break;
|
|
15446
|
+
case DisposalMethod.RestoreBackground:
|
|
15447
|
+
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
15448
|
+
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
15449
|
+
offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
15450
|
+
if (!gifData.globalColorTable.length) {
|
|
15451
|
+
offscreenContext.putImageData(gifData.frames[firstIndex$1].image, pos.x + frame.left, pos.y + frame.top);
|
|
15452
|
+
}
|
|
15453
|
+
else {
|
|
15454
|
+
offscreenContext.putImageData(gifData.backgroundImage, pos.x, pos.y);
|
|
15455
|
+
}
|
|
15456
|
+
break;
|
|
15457
|
+
case DisposalMethod.RestorePrevious:
|
|
15458
|
+
{
|
|
15459
|
+
const previousImageData = offscreenContext.getImageData(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
15460
|
+
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
15461
|
+
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
15462
|
+
offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
15463
|
+
offscreenContext.putImageData(previousImageData, originPoint.x, originPoint.y);
|
|
15464
|
+
}
|
|
15465
|
+
break;
|
|
15466
|
+
}
|
|
15467
|
+
particle.gifTime += delta.value;
|
|
15468
|
+
if (particle.gifTime > frame.delayTime) {
|
|
15469
|
+
particle.gifTime -= frame.delayTime;
|
|
15470
|
+
if (++frameIndex >= gifData.frames.length) {
|
|
15471
|
+
if (particle.gifLoopCount == null || --particle.gifLoopCount <= defaultLoopCount) {
|
|
15472
|
+
return;
|
|
15473
|
+
}
|
|
15474
|
+
frameIndex = firstIndex$1;
|
|
15475
|
+
offscreenContext.clearRect(originPoint.x, originPoint.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
15476
|
+
}
|
|
15477
|
+
particle.gifFrame = frameIndex;
|
|
15478
|
+
}
|
|
15479
|
+
context.scale(gifData.width / radius, gifData.height / radius);
|
|
15326
15480
|
}
|
|
15327
15481
|
|
|
15328
|
-
|
|
15329
|
-
class WobbleUpdater {
|
|
15482
|
+
class GifDrawer {
|
|
15330
15483
|
#container;
|
|
15484
|
+
#gifCache;
|
|
15331
15485
|
constructor(container) {
|
|
15332
15486
|
this.#container = container;
|
|
15487
|
+
this.#gifCache = new Map();
|
|
15333
15488
|
}
|
|
15334
|
-
|
|
15335
|
-
|
|
15336
|
-
if (wobbleOpt?.enable) {
|
|
15337
|
-
particle.wobble = {
|
|
15338
|
-
angle: getRandom() * doublePI,
|
|
15339
|
-
angleSpeed: getRangeValue(wobbleOpt.speed.angle) / maxAngle$1,
|
|
15340
|
-
moveSpeed: getRangeValue(wobbleOpt.speed.move) / moveSpeedFactor$1,
|
|
15341
|
-
};
|
|
15342
|
-
}
|
|
15343
|
-
else {
|
|
15344
|
-
particle.wobble = {
|
|
15345
|
-
angle: 0,
|
|
15346
|
-
angleSpeed: 0,
|
|
15347
|
-
moveSpeed: 0,
|
|
15348
|
-
};
|
|
15349
|
-
}
|
|
15350
|
-
particle.retina.wobbleDistance =
|
|
15351
|
-
getRangeValue(wobbleOpt?.distance ?? defaultDistance) * this.#container.retina.pixelRatio;
|
|
15489
|
+
destroy() {
|
|
15490
|
+
this.#gifCache.clear();
|
|
15352
15491
|
}
|
|
15353
|
-
|
|
15354
|
-
|
|
15492
|
+
draw(data) {
|
|
15493
|
+
const { context, opacity } = data;
|
|
15494
|
+
if (!data.particle.gifData)
|
|
15495
|
+
return;
|
|
15496
|
+
context.globalAlpha = opacity;
|
|
15497
|
+
drawGif(data, this.#container.canvas.render.settings);
|
|
15498
|
+
context.globalAlpha = 1;
|
|
15355
15499
|
}
|
|
15356
|
-
|
|
15357
|
-
|
|
15500
|
+
loadShape(particle) {
|
|
15501
|
+
const shapeData = particle.shapeData;
|
|
15502
|
+
if (!shapeData?.src)
|
|
15503
|
+
return;
|
|
15504
|
+
if (this.#gifCache.has(shapeData.src))
|
|
15505
|
+
return;
|
|
15506
|
+
void decodeGIF(shapeData.src, { colorSpace: "srgb" }).then(gifData => {
|
|
15507
|
+
this.#gifCache.set(shapeData.src, gifData);
|
|
15508
|
+
});
|
|
15358
15509
|
}
|
|
15359
|
-
|
|
15360
|
-
|
|
15510
|
+
particleInit(container, particle) {
|
|
15511
|
+
const shapeData = particle.shapeData;
|
|
15512
|
+
if (!shapeData?.src)
|
|
15513
|
+
return;
|
|
15514
|
+
const gifData = this.#gifCache.get(shapeData.src);
|
|
15515
|
+
if (!gifData) {
|
|
15516
|
+
setTimeout(() => {
|
|
15517
|
+
this.particleInit(container, particle);
|
|
15518
|
+
});
|
|
15361
15519
|
return;
|
|
15362
15520
|
}
|
|
15363
|
-
|
|
15521
|
+
particle.gifData = gifData;
|
|
15522
|
+
particle.gifFrame = 0;
|
|
15523
|
+
particle.gifTime = 0;
|
|
15524
|
+
particle.gifLoopCount = getGIFLoopAmount(gifData);
|
|
15525
|
+
if (particle.gifLoopCount === 0) {
|
|
15526
|
+
particle.gifLoopCount = Number.POSITIVE_INFINITY;
|
|
15527
|
+
}
|
|
15528
|
+
if (shapeData.loopCount !== undefined) {
|
|
15529
|
+
particle.gifLoopCount = shapeData.loopCount;
|
|
15530
|
+
}
|
|
15364
15531
|
}
|
|
15365
15532
|
}
|
|
15366
15533
|
|
|
15367
|
-
async function
|
|
15368
|
-
engine.checkVersion("4.
|
|
15534
|
+
async function loadGifShape(engine) {
|
|
15535
|
+
engine.checkVersion("4.3.0");
|
|
15369
15536
|
await engine.pluginManager.register(e => {
|
|
15370
|
-
e.pluginManager.
|
|
15371
|
-
return Promise.resolve(new WobbleUpdater(container));
|
|
15372
|
-
});
|
|
15373
|
-
});
|
|
15374
|
-
}
|
|
15375
|
-
|
|
15376
|
-
async function loadFull(engine) {
|
|
15377
|
-
engine.checkVersion("4.2.1");
|
|
15378
|
-
await engine.pluginManager.register(async (e) => {
|
|
15379
|
-
const loadEmittersPluginBundle = async (e) => {
|
|
15380
|
-
await loadEmittersPlugin(e);
|
|
15381
|
-
await Promise.all([
|
|
15382
|
-
loadEmittersShapeCircle(e),
|
|
15383
|
-
loadEmittersShapeSquare(e),
|
|
15384
|
-
]);
|
|
15385
|
-
}, loadInteractivityForFull = async (e) => {
|
|
15386
|
-
await loadSlim(e);
|
|
15387
|
-
await Promise.all([
|
|
15388
|
-
loadExternalDragInteraction(e),
|
|
15389
|
-
loadExternalTrailInteraction(e),
|
|
15390
|
-
loadAbsorbersPlugin(e),
|
|
15391
|
-
loadEmittersPluginBundle(e),
|
|
15392
|
-
]);
|
|
15393
|
-
};
|
|
15394
|
-
await Promise.all([
|
|
15395
|
-
loadInteractivityForFull(e),
|
|
15396
|
-
loadDestroyUpdater(e),
|
|
15397
|
-
loadRollUpdater(e),
|
|
15398
|
-
loadTiltUpdater(e),
|
|
15399
|
-
loadTwinkleUpdater(e),
|
|
15400
|
-
loadWobbleUpdater(e),
|
|
15401
|
-
loadTextShape(e),
|
|
15402
|
-
]);
|
|
15537
|
+
e.pluginManager.addShape(["gif", "gifs"], container => Promise.resolve(new GifDrawer(container)));
|
|
15403
15538
|
});
|
|
15404
15539
|
}
|
|
15405
15540
|
|
|
@@ -15513,14 +15648,14 @@
|
|
|
15513
15648
|
}
|
|
15514
15649
|
}
|
|
15515
15650
|
|
|
15516
|
-
function updateGradient(particle, delta) {
|
|
15651
|
+
function updateGradient(particle, delta, hdr) {
|
|
15517
15652
|
const { gradient } = particle;
|
|
15518
15653
|
if (!gradient) {
|
|
15519
15654
|
return;
|
|
15520
15655
|
}
|
|
15521
15656
|
updateAnimation(particle, gradient.angle, false, exports.DestroyType.none, delta);
|
|
15522
15657
|
for (const color of gradient.colors) {
|
|
15523
|
-
updateColor(color.value, delta);
|
|
15658
|
+
updateColor(color.value, delta, hdr);
|
|
15524
15659
|
if (color.opacity) {
|
|
15525
15660
|
updateAnimation(particle, color.opacity, true, exports.DestroyType.none, delta);
|
|
15526
15661
|
}
|
|
@@ -15652,7 +15787,7 @@
|
|
|
15652
15787
|
}
|
|
15653
15788
|
}
|
|
15654
15789
|
update(particle, delta) {
|
|
15655
|
-
updateGradient(particle, delta);
|
|
15790
|
+
updateGradient(particle, delta, this.#container.hdr);
|
|
15656
15791
|
}
|
|
15657
15792
|
}
|
|
15658
15793
|
|
|
@@ -20050,7 +20185,7 @@
|
|
|
20050
20185
|
}
|
|
20051
20186
|
|
|
20052
20187
|
async function loadAll(engine) {
|
|
20053
|
-
engine.checkVersion("4.
|
|
20188
|
+
engine.checkVersion("4.3.0");
|
|
20054
20189
|
await engine.pluginManager.register(async (e) => {
|
|
20055
20190
|
const loadInteractionsForAll = async (e) => {
|
|
20056
20191
|
await loadFull(e);
|
|
@@ -20126,6 +20261,7 @@
|
|
|
20126
20261
|
loadArrowShape(e),
|
|
20127
20262
|
loadCardsShape(e),
|
|
20128
20263
|
loadCogShape(e),
|
|
20264
|
+
loadGifShape(e),
|
|
20129
20265
|
loadHeartShape(e),
|
|
20130
20266
|
loadInfinityShape(e),
|
|
20131
20267
|
loadMatrixShape(e),
|
|
@@ -20151,10 +20287,10 @@
|
|
|
20151
20287
|
}
|
|
20152
20288
|
}
|
|
20153
20289
|
class RenderManager {
|
|
20290
|
+
#backgroundElement;
|
|
20291
|
+
#backgroundWarnings;
|
|
20154
20292
|
#canvasClearPlugins;
|
|
20155
20293
|
#canvasManager;
|
|
20156
|
-
#canvasPaintPlugins;
|
|
20157
|
-
#clearDrawPlugins;
|
|
20158
20294
|
#colorPlugins;
|
|
20159
20295
|
#container;
|
|
20160
20296
|
#context;
|
|
@@ -20162,9 +20298,7 @@
|
|
|
20162
20298
|
#drawParticlePlugins;
|
|
20163
20299
|
#drawParticlesCleanupPlugins;
|
|
20164
20300
|
#drawParticlesSetupPlugins;
|
|
20165
|
-
#
|
|
20166
|
-
#drawSettingsCleanupPlugins;
|
|
20167
|
-
#drawSettingsSetupPlugins;
|
|
20301
|
+
#layers;
|
|
20168
20302
|
#pluginManager;
|
|
20169
20303
|
#postDrawUpdaters;
|
|
20170
20304
|
#preDrawUpdaters;
|
|
@@ -20176,18 +20310,25 @@
|
|
|
20176
20310
|
this.#container = container;
|
|
20177
20311
|
this.#canvasManager = canvasManager;
|
|
20178
20312
|
this.#context = null;
|
|
20313
|
+
this.#backgroundElement = null;
|
|
20314
|
+
this.#backgroundWarnings = new Set();
|
|
20179
20315
|
this.#preDrawUpdaters = [];
|
|
20180
20316
|
this.#postDrawUpdaters = [];
|
|
20181
|
-
this.#colorPlugins = [];
|
|
20182
20317
|
this.#canvasClearPlugins = [];
|
|
20183
|
-
this.#
|
|
20184
|
-
this.#clearDrawPlugins = [];
|
|
20318
|
+
this.#colorPlugins = [];
|
|
20185
20319
|
this.#drawParticlePlugins = [];
|
|
20186
20320
|
this.#drawParticlesCleanupPlugins = [];
|
|
20187
20321
|
this.#drawParticlesSetupPlugins = [];
|
|
20188
|
-
this.#
|
|
20189
|
-
|
|
20190
|
-
|
|
20322
|
+
this.#layers = {
|
|
20323
|
+
0: [],
|
|
20324
|
+
1: [],
|
|
20325
|
+
2: [],
|
|
20326
|
+
3: [],
|
|
20327
|
+
4: [],
|
|
20328
|
+
5: [],
|
|
20329
|
+
6: [],
|
|
20330
|
+
7: [],
|
|
20331
|
+
};
|
|
20191
20332
|
}
|
|
20192
20333
|
get settings() {
|
|
20193
20334
|
return this.#contextSettings;
|
|
@@ -20201,32 +20342,38 @@
|
|
|
20201
20342
|
});
|
|
20202
20343
|
}
|
|
20203
20344
|
clear() {
|
|
20204
|
-
let pluginHandled = false;
|
|
20205
20345
|
for (const plugin of this.#canvasClearPlugins) {
|
|
20206
|
-
|
|
20207
|
-
|
|
20208
|
-
break;
|
|
20346
|
+
if (plugin.canvasClear?.() ?? false) {
|
|
20347
|
+
return;
|
|
20209
20348
|
}
|
|
20210
20349
|
}
|
|
20211
|
-
|
|
20212
|
-
|
|
20350
|
+
for (const layer of Object.values(exports.DrawLayer)) {
|
|
20351
|
+
if (typeof layer === "number") {
|
|
20352
|
+
for (const plugin of this.#getLayerPlugins(layer)) {
|
|
20353
|
+
if (plugin.canvasClear?.() ?? false) {
|
|
20354
|
+
return;
|
|
20355
|
+
}
|
|
20356
|
+
}
|
|
20357
|
+
}
|
|
20213
20358
|
}
|
|
20214
20359
|
this.canvasClear();
|
|
20215
20360
|
}
|
|
20216
20361
|
destroy() {
|
|
20217
20362
|
this.stop();
|
|
20363
|
+
this.#backgroundElement = null;
|
|
20364
|
+
this.#backgroundWarnings.clear();
|
|
20218
20365
|
this.#preDrawUpdaters = [];
|
|
20219
20366
|
this.#postDrawUpdaters = [];
|
|
20220
|
-
this.#colorPlugins = [];
|
|
20221
20367
|
this.#canvasClearPlugins = [];
|
|
20222
|
-
this.#
|
|
20223
|
-
this.#clearDrawPlugins = [];
|
|
20368
|
+
this.#colorPlugins = [];
|
|
20224
20369
|
this.#drawParticlePlugins = [];
|
|
20225
20370
|
this.#drawParticlesCleanupPlugins = [];
|
|
20226
20371
|
this.#drawParticlesSetupPlugins = [];
|
|
20227
|
-
|
|
20228
|
-
|
|
20229
|
-
|
|
20372
|
+
for (const layer of Object.values(exports.DrawLayer)) {
|
|
20373
|
+
if (typeof layer === "number") {
|
|
20374
|
+
this.#layers[layer] = [];
|
|
20375
|
+
}
|
|
20376
|
+
}
|
|
20230
20377
|
}
|
|
20231
20378
|
draw(cb) {
|
|
20232
20379
|
const ctx = this.#context;
|
|
@@ -20283,21 +20430,40 @@
|
|
|
20283
20430
|
});
|
|
20284
20431
|
}
|
|
20285
20432
|
drawParticles(delta) {
|
|
20286
|
-
const { particles } = this.#container;
|
|
20433
|
+
const { particles, actualOptions } = this.#container;
|
|
20287
20434
|
this.clear();
|
|
20288
20435
|
particles.update(delta);
|
|
20289
20436
|
this.draw(ctx => {
|
|
20290
|
-
|
|
20437
|
+
const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
|
|
20438
|
+
if (this.#backgroundElement) {
|
|
20439
|
+
try {
|
|
20440
|
+
ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
|
|
20441
|
+
}
|
|
20442
|
+
catch {
|
|
20443
|
+
this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
|
|
20444
|
+
}
|
|
20445
|
+
}
|
|
20446
|
+
const background = actualOptions.background;
|
|
20447
|
+
if (background.draw) {
|
|
20448
|
+
try {
|
|
20449
|
+
background.draw(ctx, delta);
|
|
20450
|
+
}
|
|
20451
|
+
catch {
|
|
20452
|
+
this.#warnOnce("background-draw-error", "Error in background.draw callback");
|
|
20453
|
+
}
|
|
20454
|
+
}
|
|
20455
|
+
for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
|
|
20456
|
+
plugin.canvasPaint?.();
|
|
20457
|
+
}
|
|
20458
|
+
for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasSetup)) {
|
|
20291
20459
|
plugin.drawSettingsSetup?.(ctx, delta);
|
|
20292
20460
|
}
|
|
20293
|
-
for (const plugin of this.#
|
|
20461
|
+
for (const plugin of this.#getLayerPlugins(exports.DrawLayer.PluginContent)) {
|
|
20294
20462
|
plugin.draw?.(ctx, delta);
|
|
20295
20463
|
}
|
|
20296
20464
|
particles.drawParticles(delta);
|
|
20297
|
-
for (const plugin of this.#
|
|
20465
|
+
for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup)) {
|
|
20298
20466
|
plugin.clearDraw?.(ctx, delta);
|
|
20299
|
-
}
|
|
20300
|
-
for (const plugin of this.#drawSettingsCleanupPlugins) {
|
|
20301
20467
|
plugin.drawSettingsCleanup?.(ctx, delta);
|
|
20302
20468
|
}
|
|
20303
20469
|
});
|
|
@@ -20305,29 +20471,24 @@
|
|
|
20305
20471
|
init() {
|
|
20306
20472
|
this.initUpdaters();
|
|
20307
20473
|
this.initPlugins();
|
|
20474
|
+
this.#resolveBackgroundElement();
|
|
20308
20475
|
this.paint();
|
|
20309
20476
|
}
|
|
20310
20477
|
initPlugins() {
|
|
20311
|
-
this.#colorPlugins = [];
|
|
20312
20478
|
this.#canvasClearPlugins = [];
|
|
20313
|
-
this.#
|
|
20314
|
-
this.#clearDrawPlugins = [];
|
|
20479
|
+
this.#colorPlugins = [];
|
|
20315
20480
|
this.#drawParticlePlugins = [];
|
|
20316
20481
|
this.#drawParticlesSetupPlugins = [];
|
|
20317
20482
|
this.#drawParticlesCleanupPlugins = [];
|
|
20318
|
-
|
|
20319
|
-
|
|
20320
|
-
|
|
20483
|
+
for (const layer of Object.values(exports.DrawLayer)) {
|
|
20484
|
+
if (typeof layer === "number") {
|
|
20485
|
+
this.#layers[layer] = [];
|
|
20486
|
+
}
|
|
20487
|
+
}
|
|
20321
20488
|
for (const plugin of this.#container.plugins) {
|
|
20322
20489
|
if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
|
|
20323
20490
|
this.#colorPlugins.push(plugin);
|
|
20324
20491
|
}
|
|
20325
|
-
if (plugin.canvasClear) {
|
|
20326
|
-
this.#canvasClearPlugins.push(plugin);
|
|
20327
|
-
}
|
|
20328
|
-
if (plugin.canvasPaint) {
|
|
20329
|
-
this.#canvasPaintPlugins.push(plugin);
|
|
20330
|
-
}
|
|
20331
20492
|
if (plugin.drawParticle) {
|
|
20332
20493
|
this.#drawParticlePlugins.push(plugin);
|
|
20333
20494
|
}
|
|
@@ -20337,17 +20498,20 @@
|
|
|
20337
20498
|
if (plugin.drawParticleCleanup) {
|
|
20338
20499
|
this.#drawParticlesCleanupPlugins.push(plugin);
|
|
20339
20500
|
}
|
|
20340
|
-
if (plugin.
|
|
20341
|
-
this.#
|
|
20501
|
+
if (plugin.canvasClear) {
|
|
20502
|
+
this.#canvasClearPlugins.push(plugin);
|
|
20503
|
+
}
|
|
20504
|
+
if (plugin.canvasPaint) {
|
|
20505
|
+
this.#getLayerPlugins(exports.DrawLayer.BackgroundMask).push(plugin);
|
|
20342
20506
|
}
|
|
20343
20507
|
if (plugin.drawSettingsSetup) {
|
|
20344
|
-
this.#
|
|
20508
|
+
this.#getLayerPlugins(exports.DrawLayer.CanvasSetup).push(plugin);
|
|
20345
20509
|
}
|
|
20346
|
-
if (plugin.
|
|
20347
|
-
this.#
|
|
20510
|
+
if (plugin.draw) {
|
|
20511
|
+
this.#getLayerPlugins(exports.DrawLayer.PluginContent).push(plugin);
|
|
20348
20512
|
}
|
|
20349
|
-
if (plugin.clearDraw) {
|
|
20350
|
-
this.#
|
|
20513
|
+
if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
|
|
20514
|
+
this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup).push(plugin);
|
|
20351
20515
|
}
|
|
20352
20516
|
}
|
|
20353
20517
|
}
|
|
@@ -20365,7 +20529,7 @@
|
|
|
20365
20529
|
}
|
|
20366
20530
|
paint() {
|
|
20367
20531
|
let handled = false;
|
|
20368
|
-
for (const plugin of this.#
|
|
20532
|
+
for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
|
|
20369
20533
|
handled = plugin.canvasPaint?.() ?? false;
|
|
20370
20534
|
if (handled) {
|
|
20371
20535
|
break;
|
|
@@ -20538,6 +20702,9 @@
|
|
|
20538
20702
|
}
|
|
20539
20703
|
drawer.beforeDraw(data);
|
|
20540
20704
|
}
|
|
20705
|
+
#getLayerPlugins(layer) {
|
|
20706
|
+
return this.#layers[layer];
|
|
20707
|
+
}
|
|
20541
20708
|
#getPluginParticleColors(particle) {
|
|
20542
20709
|
let fColor, sColor;
|
|
20543
20710
|
for (const plugin of this.#colorPlugins) {
|
|
@@ -20555,6 +20722,39 @@
|
|
|
20555
20722
|
this.#reusablePluginColors[sColorIndex] = sColor;
|
|
20556
20723
|
return this.#reusablePluginColors;
|
|
20557
20724
|
}
|
|
20725
|
+
#resolveBackgroundElement() {
|
|
20726
|
+
const background = this.#container.actualOptions.background;
|
|
20727
|
+
this.#backgroundElement = null;
|
|
20728
|
+
if (!background.element) {
|
|
20729
|
+
return;
|
|
20730
|
+
}
|
|
20731
|
+
if (typeof background.element === "string") {
|
|
20732
|
+
if (typeof document !== "undefined") {
|
|
20733
|
+
const node = document.querySelector(background.element);
|
|
20734
|
+
if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
|
|
20735
|
+
this.#backgroundElement = node;
|
|
20736
|
+
}
|
|
20737
|
+
else if (node) {
|
|
20738
|
+
this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
|
|
20739
|
+
}
|
|
20740
|
+
else {
|
|
20741
|
+
this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
|
|
20742
|
+
}
|
|
20743
|
+
}
|
|
20744
|
+
}
|
|
20745
|
+
else if (background.element instanceof HTMLCanvasElement ||
|
|
20746
|
+
background.element instanceof OffscreenCanvas ||
|
|
20747
|
+
background.element instanceof HTMLVideoElement ||
|
|
20748
|
+
background.element instanceof HTMLImageElement) {
|
|
20749
|
+
this.#backgroundElement = background.element;
|
|
20750
|
+
}
|
|
20751
|
+
}
|
|
20752
|
+
#warnOnce(key, message) {
|
|
20753
|
+
if (!this.#backgroundWarnings.has(key)) {
|
|
20754
|
+
this.#backgroundWarnings.add(key);
|
|
20755
|
+
getLogger().warning(message);
|
|
20756
|
+
}
|
|
20757
|
+
}
|
|
20558
20758
|
}
|
|
20559
20759
|
|
|
20560
20760
|
const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
|
|
@@ -21131,7 +21331,6 @@
|
|
|
21131
21331
|
}
|
|
21132
21332
|
class Particle {
|
|
21133
21333
|
backColor;
|
|
21134
|
-
bubble;
|
|
21135
21334
|
destroyed;
|
|
21136
21335
|
direction;
|
|
21137
21336
|
effect;
|
|
@@ -21165,7 +21364,6 @@
|
|
|
21165
21364
|
shapeData;
|
|
21166
21365
|
sides;
|
|
21167
21366
|
size;
|
|
21168
|
-
slow;
|
|
21169
21367
|
spawning;
|
|
21170
21368
|
strokeColor;
|
|
21171
21369
|
strokeOpacity;
|
|
@@ -21187,18 +21385,25 @@
|
|
|
21187
21385
|
d: 1,
|
|
21188
21386
|
};
|
|
21189
21387
|
#container;
|
|
21388
|
+
#modifiers = [];
|
|
21190
21389
|
#pluginManager;
|
|
21191
21390
|
constructor(pluginManager, container) {
|
|
21192
21391
|
this.#pluginManager = pluginManager;
|
|
21193
21392
|
this.#container = container;
|
|
21194
21393
|
}
|
|
21394
|
+
addModifier(modifier) {
|
|
21395
|
+
this.#modifiers.push(modifier);
|
|
21396
|
+
this.#modifiers.sort((a, b) => a.priority - b.priority);
|
|
21397
|
+
}
|
|
21398
|
+
clearModifiers() {
|
|
21399
|
+
this.#modifiers.length = 0;
|
|
21400
|
+
}
|
|
21195
21401
|
destroy(override) {
|
|
21196
21402
|
if (this.unbreakable || this.destroyed) {
|
|
21197
21403
|
return;
|
|
21198
21404
|
}
|
|
21199
21405
|
this.destroyed = true;
|
|
21200
|
-
this.
|
|
21201
|
-
this.slow.inRange = false;
|
|
21406
|
+
this.clearModifiers();
|
|
21202
21407
|
const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
|
|
21203
21408
|
shapeDrawer?.particleDestroy?.(this);
|
|
21204
21409
|
for (const plugin of container.particleDestroyedPlugins) {
|
|
@@ -21220,13 +21425,16 @@
|
|
|
21220
21425
|
return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle$1);
|
|
21221
21426
|
}
|
|
21222
21427
|
getFillColor() {
|
|
21223
|
-
return this.#getRollColor(this
|
|
21428
|
+
return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
|
|
21224
21429
|
}
|
|
21225
21430
|
getMass() {
|
|
21226
21431
|
return this.getRadius() ** squareExp * Math.PI * half$2;
|
|
21227
21432
|
}
|
|
21433
|
+
getModifier(id) {
|
|
21434
|
+
return this.#modifiers.find(m => m.id === id);
|
|
21435
|
+
}
|
|
21228
21436
|
getOpacity() {
|
|
21229
|
-
const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate,
|
|
21437
|
+
const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$3), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity, fillOpacity = this.fillOpacity ?? defaultOpacity$3, strokeOpacity = this.strokeOpacity ?? defaultOpacity$3;
|
|
21230
21438
|
this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
|
|
21231
21439
|
this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
|
|
21232
21440
|
this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
|
|
@@ -21239,7 +21447,7 @@
|
|
|
21239
21447
|
return this.#cachedPosition;
|
|
21240
21448
|
}
|
|
21241
21449
|
getRadius() {
|
|
21242
|
-
return this.
|
|
21450
|
+
return this.#applyModifiers(this.size.value, m => m.radius);
|
|
21243
21451
|
}
|
|
21244
21452
|
getRotateData() {
|
|
21245
21453
|
const angle = this.getAngle();
|
|
@@ -21248,7 +21456,7 @@
|
|
|
21248
21456
|
return this.#cachedRotateData;
|
|
21249
21457
|
}
|
|
21250
21458
|
getStrokeColor() {
|
|
21251
|
-
return this.#getRollColor(this
|
|
21459
|
+
return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
|
|
21252
21460
|
}
|
|
21253
21461
|
getTransformData(externalTransform) {
|
|
21254
21462
|
const rotateData = this.getRotateData(), rotating = this.isRotating;
|
|
@@ -21268,13 +21476,6 @@
|
|
|
21268
21476
|
this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
|
|
21269
21477
|
container.retina.initParticle(this);
|
|
21270
21478
|
runUpdaterPreInit(container.particleUpdaters, this);
|
|
21271
|
-
this.bubble = {
|
|
21272
|
-
inRange: false,
|
|
21273
|
-
};
|
|
21274
|
-
this.slow = {
|
|
21275
|
-
inRange: false,
|
|
21276
|
-
factor: 1,
|
|
21277
|
-
};
|
|
21278
21479
|
this.#initPosition(position);
|
|
21279
21480
|
this.initialVelocity = this.#calculateVelocity();
|
|
21280
21481
|
this.velocity = this.initialVelocity.copy();
|
|
@@ -21314,11 +21515,29 @@
|
|
|
21314
21515
|
isVisible() {
|
|
21315
21516
|
return !this.destroyed && !this.spawning && this.isInsideCanvas();
|
|
21316
21517
|
}
|
|
21518
|
+
removeModifier(id) {
|
|
21519
|
+
const idx = this.#modifiers.findIndex(m => m.id === id);
|
|
21520
|
+
if (idx >= defaultAngle$1) {
|
|
21521
|
+
this.#modifiers.splice(idx, identity$3);
|
|
21522
|
+
}
|
|
21523
|
+
}
|
|
21317
21524
|
reset() {
|
|
21318
21525
|
for (const updater of this.#container.particleUpdaters) {
|
|
21319
21526
|
updater.reset?.(this);
|
|
21320
21527
|
}
|
|
21321
21528
|
}
|
|
21529
|
+
#applyModifiers(base, getter) {
|
|
21530
|
+
let value = base;
|
|
21531
|
+
for (const mod of this.#modifiers) {
|
|
21532
|
+
if (mod.enabled) {
|
|
21533
|
+
const override = getter(mod);
|
|
21534
|
+
if (override !== undefined) {
|
|
21535
|
+
value = override;
|
|
21536
|
+
}
|
|
21537
|
+
}
|
|
21538
|
+
}
|
|
21539
|
+
return value;
|
|
21540
|
+
}
|
|
21322
21541
|
#calcPosition(position, zIndex) {
|
|
21323
21542
|
let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
|
|
21324
21543
|
const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
|
|
@@ -22420,10 +22639,13 @@
|
|
|
22420
22639
|
});
|
|
22421
22640
|
|
|
22422
22641
|
class BackgroundMaskPluginInstance {
|
|
22642
|
+
layer = exports.DrawLayer.BackgroundMask;
|
|
22423
22643
|
#container;
|
|
22424
22644
|
#coverColorStyle;
|
|
22425
22645
|
#coverImage;
|
|
22426
22646
|
#defaultCompositeValue;
|
|
22647
|
+
#maskElement;
|
|
22648
|
+
#maskWarnings = new Set();
|
|
22427
22649
|
#pluginManager;
|
|
22428
22650
|
constructor(pluginManager, container) {
|
|
22429
22651
|
this.#pluginManager = pluginManager;
|
|
@@ -22437,19 +22659,52 @@
|
|
|
22437
22659
|
return this.canvasPaint();
|
|
22438
22660
|
}
|
|
22439
22661
|
canvasPaint() {
|
|
22440
|
-
|
|
22662
|
+
const { backgroundMask } = this.#container.actualOptions;
|
|
22663
|
+
if (!backgroundMask?.enable) {
|
|
22441
22664
|
return false;
|
|
22442
22665
|
}
|
|
22443
22666
|
const canvas = this.#container.canvas;
|
|
22444
22667
|
canvas.render.canvasClear();
|
|
22445
|
-
|
|
22446
|
-
|
|
22668
|
+
const cover = backgroundMask.cover;
|
|
22669
|
+
let dynamicUsed = false;
|
|
22670
|
+
const maskElement = this.#maskElement;
|
|
22671
|
+
if (maskElement) {
|
|
22672
|
+
dynamicUsed = true;
|
|
22673
|
+
canvas.render.draw(ctx => {
|
|
22674
|
+
try {
|
|
22675
|
+
ctx.drawImage(maskElement, originPoint.x, originPoint.y, canvas.size.width, canvas.size.height);
|
|
22676
|
+
}
|
|
22677
|
+
catch {
|
|
22678
|
+
this.#maskWarnOnce("mask-element-draw-error", "Error drawing background mask cover element onto canvas");
|
|
22679
|
+
}
|
|
22680
|
+
});
|
|
22447
22681
|
}
|
|
22448
|
-
|
|
22449
|
-
|
|
22682
|
+
if (cover.draw) {
|
|
22683
|
+
dynamicUsed = true;
|
|
22684
|
+
const drawFn = cover.draw;
|
|
22685
|
+
canvas.render.draw(ctx => {
|
|
22686
|
+
try {
|
|
22687
|
+
drawFn(ctx, { value: 0, factor: 1 });
|
|
22688
|
+
}
|
|
22689
|
+
catch {
|
|
22690
|
+
this.#maskWarnOnce("mask-draw-error", "Error in mask cover.draw callback");
|
|
22691
|
+
}
|
|
22692
|
+
});
|
|
22693
|
+
}
|
|
22694
|
+
if (!dynamicUsed) {
|
|
22695
|
+
if (this.#coverImage) {
|
|
22696
|
+
canvas.render.paintImage(this.#coverImage.image, this.#coverImage.opacity);
|
|
22697
|
+
}
|
|
22698
|
+
else {
|
|
22699
|
+
canvas.render.paintBase(this.#coverColorStyle);
|
|
22700
|
+
}
|
|
22450
22701
|
}
|
|
22451
22702
|
return true;
|
|
22452
22703
|
}
|
|
22704
|
+
destroy() {
|
|
22705
|
+
this.#maskElement = null;
|
|
22706
|
+
this.#maskWarnings.clear();
|
|
22707
|
+
}
|
|
22453
22708
|
drawSettingsCleanup(context) {
|
|
22454
22709
|
if (!this.#defaultCompositeValue) {
|
|
22455
22710
|
return;
|
|
@@ -22462,7 +22717,9 @@
|
|
|
22462
22717
|
context.globalCompositeOperation = backgroundMask?.enable ? backgroundMask.composite : previousComposite;
|
|
22463
22718
|
}
|
|
22464
22719
|
async init() {
|
|
22720
|
+
this.#maskWarnings.clear();
|
|
22465
22721
|
await this.#initCover();
|
|
22722
|
+
this.#resolveMaskElement();
|
|
22466
22723
|
}
|
|
22467
22724
|
#initCover = async () => {
|
|
22468
22725
|
const options = this.#container.actualOptions, cover = options.backgroundMask?.cover, color = cover?.color;
|
|
@@ -22476,11 +22733,9 @@
|
|
|
22476
22733
|
this.#coverColorStyle = getStyleFromRgb(coverColor, this.#container.hdr, coverColor.a);
|
|
22477
22734
|
}
|
|
22478
22735
|
}
|
|
22479
|
-
else {
|
|
22736
|
+
else if (cover?.image) {
|
|
22737
|
+
const coverImage = cover.image;
|
|
22480
22738
|
await new Promise((resolve, reject) => {
|
|
22481
|
-
if (!cover?.image) {
|
|
22482
|
-
return;
|
|
22483
|
-
}
|
|
22484
22739
|
const img = safeDocument().createElement("img");
|
|
22485
22740
|
img.addEventListener("load", () => {
|
|
22486
22741
|
this.#coverImage = {
|
|
@@ -22492,10 +22747,44 @@
|
|
|
22492
22747
|
img.addEventListener("error", () => {
|
|
22493
22748
|
reject(new Error("Error loading image"));
|
|
22494
22749
|
});
|
|
22495
|
-
img.src =
|
|
22750
|
+
img.src = coverImage;
|
|
22496
22751
|
});
|
|
22497
22752
|
}
|
|
22498
22753
|
};
|
|
22754
|
+
#maskWarnOnce = (key, message) => {
|
|
22755
|
+
if (this.#maskWarnings.has(key)) {
|
|
22756
|
+
return;
|
|
22757
|
+
}
|
|
22758
|
+
this.#maskWarnings.add(key);
|
|
22759
|
+
getLogger().warning(`[tsParticles BackgroundMask] ${message}`);
|
|
22760
|
+
};
|
|
22761
|
+
#resolveMaskElement = () => {
|
|
22762
|
+
const cover = this.#container.actualOptions.backgroundMask?.cover;
|
|
22763
|
+
this.#maskElement = null;
|
|
22764
|
+
if (!cover?.element) {
|
|
22765
|
+
return;
|
|
22766
|
+
}
|
|
22767
|
+
if (typeof cover.element === "string") {
|
|
22768
|
+
if (typeof document !== "undefined") {
|
|
22769
|
+
const node = document.querySelector(cover.element);
|
|
22770
|
+
if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
|
|
22771
|
+
this.#maskElement = node;
|
|
22772
|
+
}
|
|
22773
|
+
else if (node) {
|
|
22774
|
+
this.#maskWarnOnce("mask-element-not-supported", `Mask cover element "${cover.element}" matched a non-drawable element (expected canvas, video, or img)`);
|
|
22775
|
+
}
|
|
22776
|
+
else {
|
|
22777
|
+
this.#maskWarnOnce("mask-element-not-found", `Mask cover element selector "${cover.element}" not found in the DOM`);
|
|
22778
|
+
}
|
|
22779
|
+
}
|
|
22780
|
+
}
|
|
22781
|
+
else if (cover.element instanceof HTMLCanvasElement ||
|
|
22782
|
+
cover.element instanceof OffscreenCanvas ||
|
|
22783
|
+
cover.element instanceof HTMLVideoElement ||
|
|
22784
|
+
cover.element instanceof HTMLImageElement) {
|
|
22785
|
+
this.#maskElement = cover.element;
|
|
22786
|
+
}
|
|
22787
|
+
};
|
|
22499
22788
|
}
|
|
22500
22789
|
|
|
22501
22790
|
var BackgroundMaskPluginInstance$1 = /*#__PURE__*/Object.freeze({
|
|
@@ -22611,7 +22900,8 @@
|
|
|
22611
22900
|
particle.lastPathTime -= pathDelay;
|
|
22612
22901
|
}
|
|
22613
22902
|
function getProximitySpeedFactor(particle) {
|
|
22614
|
-
|
|
22903
|
+
const mod = particle.getModifier("slow");
|
|
22904
|
+
return mod?.enabled ? (mod.speedFactor ?? identity$3) : identity$3;
|
|
22615
22905
|
}
|
|
22616
22906
|
function initSpin(container, particle) {
|
|
22617
22907
|
const options = particle.options, spinOptions = options.move.spin;
|
|
@@ -23775,6 +24065,7 @@
|
|
|
23775
24065
|
});
|
|
23776
24066
|
|
|
23777
24067
|
class BlendPluginInstance {
|
|
24068
|
+
layer = exports.DrawLayer.CanvasSetup;
|
|
23778
24069
|
#container;
|
|
23779
24070
|
#defaultCompositeValue;
|
|
23780
24071
|
constructor(container) {
|
|
@@ -26880,6 +27171,7 @@
|
|
|
26880
27171
|
|
|
26881
27172
|
const minimumLength = 0;
|
|
26882
27173
|
class TrailPluginInstance {
|
|
27174
|
+
layer = exports.DrawLayer.PluginContent;
|
|
26883
27175
|
#container;
|
|
26884
27176
|
#pluginManager;
|
|
26885
27177
|
#trailFill;
|
|
@@ -27133,6 +27425,7 @@
|
|
|
27133
27425
|
}
|
|
27134
27426
|
|
|
27135
27427
|
class ZoomPluginInstance {
|
|
27428
|
+
layer = exports.DrawLayer.CanvasSetup;
|
|
27136
27429
|
#container;
|
|
27137
27430
|
#listeners;
|
|
27138
27431
|
constructor(container) {
|
|
@@ -28044,6 +28337,7 @@
|
|
|
28044
28337
|
exports.hPhase = hPhase;
|
|
28045
28338
|
exports.half = half$2;
|
|
28046
28339
|
exports.hslToRgb = hslToRgb;
|
|
28340
|
+
exports.hslToRgbFloat = hslToRgbFloat;
|
|
28047
28341
|
exports.hslaToRgba = hslaToRgba;
|
|
28048
28342
|
exports.identity = identity$3;
|
|
28049
28343
|
exports.inverseFactorNumerator = inverseFactorNumerator;
|