@newkrok/three-particles 2.14.0 → 2.15.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/README.md +14 -6
- package/dist/index.d.ts +33 -0
- package/dist/index.js +65 -22
- package/dist/index.js.map +1 -1
- package/dist/three-particles.min.js +1 -1
- package/dist/three-particles.min.js.map +1 -1
- package/llms-full.txt +2 -1
- package/llms.txt +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
# THREE Particles
|
|
6
|
-
[](https://www.npmjs.com/package/@newkrok/three-particles)
|
|
7
|
+
[](https://www.npmjs.com/package/@newkrok/three-particles)
|
|
8
|
+
[](https://github.com/NewKrok/three-particles/actions/workflows/ci.yml)
|
|
9
|
+
[](https://bundlephobia.com/package/@newkrok/three-particles)
|
|
10
|
+
[](https://github.com/NewKrok/three-particles/blob/master/LICENSE)
|
|
11
|
+
[](https://newkrok.github.io/three-particles/api/)
|
|
10
12
|
|
|
11
13
|
Particle system for ThreeJS.
|
|
12
14
|
|
|
@@ -62,12 +64,18 @@ const effect = {
|
|
|
62
64
|
// Your effect configuration here
|
|
63
65
|
// It can be empty to use default settings
|
|
64
66
|
};
|
|
65
|
-
const
|
|
66
|
-
scene.add(instance);
|
|
67
|
+
const system = createParticleSystem(effect);
|
|
68
|
+
scene.add(system.instance);
|
|
67
69
|
|
|
68
70
|
// Update the particle system in your animation loop
|
|
69
71
|
// Pass the current time, delta time, and elapsed time
|
|
70
72
|
updateParticleSystems({now, delta, elapsed});
|
|
73
|
+
|
|
74
|
+
// Update configuration at runtime without recreating the system
|
|
75
|
+
system.updateConfig({
|
|
76
|
+
gravity: -9.8,
|
|
77
|
+
forceFields: [{ type: 'DIRECTIONAL', direction: { x: 1, y: 0, z: 0 }, strength: 5 }],
|
|
78
|
+
});
|
|
71
79
|
```
|
|
72
80
|
|
|
73
81
|
# Usage with React Three Fiber
|
package/dist/index.d.ts
CHANGED
|
@@ -1849,6 +1849,39 @@ type ParticleSystem = {
|
|
|
1849
1849
|
pauseEmitter: () => void;
|
|
1850
1850
|
dispose: () => void;
|
|
1851
1851
|
update: (cycleData: CycleData) => void;
|
|
1852
|
+
/**
|
|
1853
|
+
* Updates the particle system configuration at runtime without recreating the system.
|
|
1854
|
+
*
|
|
1855
|
+
* System-level properties (gravity, force fields, noise, emission rates, color/size/opacity
|
|
1856
|
+
* over lifetime curves) take effect immediately for all particles.
|
|
1857
|
+
* Per-particle spawn properties (startColor, startSize, startSpeed, startLifetime, etc.)
|
|
1858
|
+
* only affect newly emitted particles — already-alive particles retain their original values.
|
|
1859
|
+
*
|
|
1860
|
+
* @param config - A partial configuration object. Only the provided properties will be updated;
|
|
1861
|
+
* all other settings remain unchanged.
|
|
1862
|
+
*
|
|
1863
|
+
* @remarks
|
|
1864
|
+
* Structural properties that are set at creation time cannot be changed at runtime:
|
|
1865
|
+
* `maxParticles`, `renderer.rendererType`, `shape`, and `map` (texture).
|
|
1866
|
+
* Passing these will update the internal config but have no visible effect since the
|
|
1867
|
+
* geometry and material are pre-allocated.
|
|
1868
|
+
*
|
|
1869
|
+
* @example
|
|
1870
|
+
* ```typescript
|
|
1871
|
+
* const system = createParticleSystem(config);
|
|
1872
|
+
*
|
|
1873
|
+
* // Change wind direction in real time
|
|
1874
|
+
* system.updateConfig({
|
|
1875
|
+
* forceFields: [{ type: ForceFieldType.DIRECTIONAL, direction: { x: 1, y: 0, z: 0 }, strength: 5 }],
|
|
1876
|
+
* });
|
|
1877
|
+
*
|
|
1878
|
+
* // Gradually change color of new particles
|
|
1879
|
+
* system.updateConfig({
|
|
1880
|
+
* startColor: { min: { r: 1, g: 0, b: 0 }, max: { r: 1, g: 0.5, b: 0 } },
|
|
1881
|
+
* });
|
|
1882
|
+
* ```
|
|
1883
|
+
*/
|
|
1884
|
+
updateConfig: (config: Partial<ParticleSystemConfig>) => void;
|
|
1852
1885
|
};
|
|
1853
1886
|
/**
|
|
1854
1887
|
* Data representing the current cycle of the particle system's update loop.
|
package/dist/index.js
CHANGED
|
@@ -1184,6 +1184,16 @@ var _modifierParams = {
|
|
|
1184
1184
|
particleLifetimePercentage: 0,
|
|
1185
1185
|
particleIndex: 0
|
|
1186
1186
|
};
|
|
1187
|
+
var toVector3 = (v, fallback) => v ? new THREE4.Vector3(v.x ?? 0, v.y ?? 0, v.z ?? 0) : fallback.clone();
|
|
1188
|
+
var normalizeForceFields = (rawForceFields) => (rawForceFields ?? []).map((ff) => ({
|
|
1189
|
+
isActive: ff.isActive ?? true,
|
|
1190
|
+
type: ff.type ?? "POINT" /* POINT */,
|
|
1191
|
+
position: toVector3(ff.position, new THREE4.Vector3(0, 0, 0)),
|
|
1192
|
+
direction: toVector3(ff.direction, new THREE4.Vector3(0, 1, 0)).normalize(),
|
|
1193
|
+
strength: ff.strength ?? 1,
|
|
1194
|
+
range: Math.max(0, ff.range ?? Infinity),
|
|
1195
|
+
falloff: ff.falloff ?? "LINEAR" /* LINEAR */
|
|
1196
|
+
}));
|
|
1187
1197
|
var blendingMap = {
|
|
1188
1198
|
"THREE.NoBlending": THREE4.NoBlending,
|
|
1189
1199
|
"THREE.NormalBlending": THREE4.NormalBlending,
|
|
@@ -1507,16 +1517,7 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1507
1517
|
subEmitters,
|
|
1508
1518
|
forceFields: rawForceFields
|
|
1509
1519
|
} = normalizedConfig;
|
|
1510
|
-
const
|
|
1511
|
-
const normalizedForceFields = (rawForceFields ?? []).map((ff) => ({
|
|
1512
|
-
isActive: ff.isActive ?? true,
|
|
1513
|
-
type: ff.type ?? "POINT" /* POINT */,
|
|
1514
|
-
position: toVector3(ff.position, new THREE4.Vector3(0, 0, 0)),
|
|
1515
|
-
direction: toVector3(ff.direction, new THREE4.Vector3(0, 1, 0)).normalize(),
|
|
1516
|
-
strength: ff.strength ?? 1,
|
|
1517
|
-
range: Math.max(0, ff.range ?? Infinity),
|
|
1518
|
-
falloff: ff.falloff ?? "LINEAR" /* LINEAR */
|
|
1519
|
-
}));
|
|
1520
|
+
const normalizedForceFields = normalizeForceFields(rawForceFields);
|
|
1520
1521
|
if (typeof renderer?.blending === "string")
|
|
1521
1522
|
renderer.blending = blendingMap[renderer.blending];
|
|
1522
1523
|
const startPositions = Array.from(
|
|
@@ -1952,44 +1953,45 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
1952
1953
|
if (generalData.noise.offsets)
|
|
1953
1954
|
generalData.noise.offsets[particleIndex] = Math.random() * 100;
|
|
1954
1955
|
const colorRandomRatio2 = Math.random();
|
|
1955
|
-
|
|
1956
|
+
const cfgStartColor = normalizedConfig.startColor;
|
|
1957
|
+
aColorR.array[particleIndex] = cfgStartColor.min.r + colorRandomRatio2 * (cfgStartColor.max.r - cfgStartColor.min.r);
|
|
1956
1958
|
aColorR.needsUpdate = true;
|
|
1957
|
-
aColorG.array[particleIndex] =
|
|
1959
|
+
aColorG.array[particleIndex] = cfgStartColor.min.g + colorRandomRatio2 * (cfgStartColor.max.g - cfgStartColor.min.g);
|
|
1958
1960
|
aColorG.needsUpdate = true;
|
|
1959
|
-
aColorB.array[particleIndex] =
|
|
1961
|
+
aColorB.array[particleIndex] = cfgStartColor.min.b + colorRandomRatio2 * (cfgStartColor.max.b - cfgStartColor.min.b);
|
|
1960
1962
|
aColorB.needsUpdate = true;
|
|
1961
1963
|
generalData.startValues.startColorR[particleIndex] = aColorR.array[particleIndex];
|
|
1962
1964
|
generalData.startValues.startColorG[particleIndex] = aColorG.array[particleIndex];
|
|
1963
1965
|
generalData.startValues.startColorB[particleIndex] = aColorB.array[particleIndex];
|
|
1964
|
-
aStartFrame.array[particleIndex] = textureSheetAnimation.startFrame ? calculateValue(
|
|
1966
|
+
aStartFrame.array[particleIndex] = normalizedConfig.textureSheetAnimation.startFrame ? calculateValue(
|
|
1965
1967
|
generalData.particleSystemId,
|
|
1966
|
-
textureSheetAnimation.startFrame,
|
|
1968
|
+
normalizedConfig.textureSheetAnimation.startFrame,
|
|
1967
1969
|
0
|
|
1968
1970
|
) : 0;
|
|
1969
1971
|
aStartFrame.needsUpdate = true;
|
|
1970
1972
|
aStartLifetime.array[particleIndex] = calculateValue(
|
|
1971
1973
|
generalData.particleSystemId,
|
|
1972
|
-
startLifetime,
|
|
1974
|
+
normalizedConfig.startLifetime,
|
|
1973
1975
|
generalData.normalizedLifetimePercentage
|
|
1974
1976
|
) * 1e3;
|
|
1975
1977
|
aStartLifetime.needsUpdate = true;
|
|
1976
1978
|
generalData.startValues.startSize[particleIndex] = calculateValue(
|
|
1977
1979
|
generalData.particleSystemId,
|
|
1978
|
-
startSize,
|
|
1980
|
+
normalizedConfig.startSize,
|
|
1979
1981
|
generalData.normalizedLifetimePercentage
|
|
1980
1982
|
);
|
|
1981
1983
|
aSize.array[particleIndex] = generalData.startValues.startSize[particleIndex];
|
|
1982
1984
|
aSize.needsUpdate = true;
|
|
1983
1985
|
generalData.startValues.startOpacity[particleIndex] = calculateValue(
|
|
1984
1986
|
generalData.particleSystemId,
|
|
1985
|
-
startOpacity,
|
|
1987
|
+
normalizedConfig.startOpacity,
|
|
1986
1988
|
generalData.normalizedLifetimePercentage
|
|
1987
1989
|
);
|
|
1988
1990
|
aColorA.array[particleIndex] = generalData.startValues.startOpacity[particleIndex];
|
|
1989
1991
|
aColorA.needsUpdate = true;
|
|
1990
1992
|
aRotation.array[particleIndex] = calculateValue(
|
|
1991
1993
|
generalData.particleSystemId,
|
|
1992
|
-
startRotation,
|
|
1994
|
+
normalizedConfig.startRotation,
|
|
1993
1995
|
generalData.normalizedLifetimePercentage
|
|
1994
1996
|
);
|
|
1995
1997
|
aRotation.needsUpdate = true;
|
|
@@ -2010,8 +2012,8 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2010
2012
|
);
|
|
2011
2013
|
calculatePositionAndVelocity(
|
|
2012
2014
|
generalData,
|
|
2013
|
-
shape,
|
|
2014
|
-
startSpeed,
|
|
2015
|
+
normalizedConfig.shape,
|
|
2016
|
+
normalizedConfig.startSpeed,
|
|
2015
2017
|
startPositions[particleIndex],
|
|
2016
2018
|
velocities[particleIndex]
|
|
2017
2019
|
);
|
|
@@ -2406,12 +2408,53 @@ var createParticleSystem = (config = DEFAULT_PARTICLE_SYSTEM_CONFIG, externalNow
|
|
|
2406
2408
|
for (const sub of instances) sub.update(cycleData);
|
|
2407
2409
|
}
|
|
2408
2410
|
};
|
|
2411
|
+
const updateConfig = (partialConfig) => {
|
|
2412
|
+
ObjectUtils.deepMerge(instanceData.normalizedConfig, partialConfig, {
|
|
2413
|
+
applyToFirstObject: true,
|
|
2414
|
+
skippedProperties: []
|
|
2415
|
+
});
|
|
2416
|
+
const cfg = instanceData.normalizedConfig;
|
|
2417
|
+
if (partialConfig.gravity !== void 0) {
|
|
2418
|
+
instanceData.gravity = cfg.gravity;
|
|
2419
|
+
generalData.lastWorldQuaternion.x = -99999;
|
|
2420
|
+
}
|
|
2421
|
+
if (partialConfig.duration !== void 0)
|
|
2422
|
+
instanceData.duration = cfg.duration;
|
|
2423
|
+
if (partialConfig.looping !== void 0) instanceData.looping = cfg.looping;
|
|
2424
|
+
if (partialConfig.simulationSpace !== void 0)
|
|
2425
|
+
instanceData.simulationSpace = cfg.simulationSpace;
|
|
2426
|
+
if (partialConfig.emission !== void 0)
|
|
2427
|
+
instanceData.emission = cfg.emission;
|
|
2428
|
+
if (partialConfig.forceFields !== void 0) {
|
|
2429
|
+
instanceData.normalizedForceFields = normalizeForceFields(
|
|
2430
|
+
cfg.forceFields
|
|
2431
|
+
);
|
|
2432
|
+
}
|
|
2433
|
+
if (partialConfig.noise !== void 0) {
|
|
2434
|
+
const n = cfg.noise;
|
|
2435
|
+
generalData.noise = {
|
|
2436
|
+
isActive: n.isActive,
|
|
2437
|
+
strength: n.strength,
|
|
2438
|
+
noisePower: 0.15 * n.strength,
|
|
2439
|
+
positionAmount: n.positionAmount,
|
|
2440
|
+
rotationAmount: n.rotationAmount,
|
|
2441
|
+
sizeAmount: n.sizeAmount,
|
|
2442
|
+
sampler: n.isActive ? new FBM({
|
|
2443
|
+
seed: Math.random(),
|
|
2444
|
+
scale: n.frequency,
|
|
2445
|
+
octaves: n.octaves
|
|
2446
|
+
}) : void 0,
|
|
2447
|
+
offsets: n.useRandomOffset ? generalData.noise.offsets ?? Array.from({ length: maxParticles }, () => Math.random() * 100) : void 0
|
|
2448
|
+
};
|
|
2449
|
+
}
|
|
2450
|
+
};
|
|
2409
2451
|
return {
|
|
2410
2452
|
instance: wrapper || particleSystem,
|
|
2411
2453
|
resumeEmitter,
|
|
2412
2454
|
pauseEmitter,
|
|
2413
2455
|
dispose,
|
|
2414
|
-
update
|
|
2456
|
+
update,
|
|
2457
|
+
updateConfig
|
|
2415
2458
|
};
|
|
2416
2459
|
};
|
|
2417
2460
|
var updateParticleSystemInstance = (props, { now, delta, elapsed }) => {
|