Updates to the particle system
This commit is contained in:
@@ -31,6 +31,8 @@
|
||||
glowIntensity: 0.6,
|
||||
logoSpin: false,
|
||||
logoSpinSpeed: 5,
|
||||
particleImage: "",
|
||||
particleSize: 1.0,
|
||||
titlePosition: "top",
|
||||
};
|
||||
|
||||
@@ -71,6 +73,8 @@
|
||||
let glowIntensity = saved.glowIntensity;
|
||||
let logoSpin = saved.logoSpin;
|
||||
let logoSpinSpeed = saved.logoSpinSpeed;
|
||||
let particleImage = saved.particleImage;
|
||||
let particleSize = saved.particleSize;
|
||||
let titlePosition = saved.titlePosition;
|
||||
let visualizerComponent;
|
||||
let toggleHidden = false;
|
||||
@@ -126,6 +130,8 @@
|
||||
glowIntensity,
|
||||
logoSpin,
|
||||
logoSpinSpeed,
|
||||
particleImage,
|
||||
particleSize,
|
||||
titlePosition,
|
||||
};
|
||||
try {
|
||||
@@ -183,6 +189,8 @@
|
||||
glowIntensity = defaults.glowIntensity;
|
||||
logoSpin = defaults.logoSpin;
|
||||
logoSpinSpeed = defaults.logoSpinSpeed;
|
||||
particleImage = defaults.particleImage;
|
||||
particleSize = defaults.particleSize;
|
||||
titlePosition = defaults.titlePosition;
|
||||
}
|
||||
|
||||
@@ -311,6 +319,8 @@
|
||||
{glowIntensity}
|
||||
{logoSpin}
|
||||
{logoSpinSpeed}
|
||||
{particleImage}
|
||||
{particleSize}
|
||||
bind:isListening
|
||||
bind:fileCurrentTime
|
||||
bind:fileDuration
|
||||
@@ -381,6 +391,8 @@
|
||||
bind:glowIntensity
|
||||
bind:logoSpin
|
||||
bind:logoSpinSpeed
|
||||
bind:particleImage
|
||||
bind:particleSize
|
||||
bind:titlePosition
|
||||
{isListening}
|
||||
{colorPresets}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
export let glowIntensity = 0.6;
|
||||
export let logoSpin = false;
|
||||
export let logoSpinSpeed = 5;
|
||||
export let particleImage = "";
|
||||
export let particleSize = 1.0;
|
||||
|
||||
const DEFAULT_SIZE = 250;
|
||||
const LINE_LIFT = 8;
|
||||
@@ -55,6 +57,16 @@
|
||||
let visualizerWrapper;
|
||||
let blobPhase = 0;
|
||||
|
||||
// Particle image cache
|
||||
let pImg = null;
|
||||
$: if (particleImage) {
|
||||
const img = new Image();
|
||||
img.src = particleImage;
|
||||
pImg = img;
|
||||
} else {
|
||||
pImg = null;
|
||||
}
|
||||
|
||||
// Particle system
|
||||
let particles = [];
|
||||
|
||||
@@ -100,7 +112,7 @@
|
||||
vy: -(1.5 + Math.random() * 4 * loudness),
|
||||
life: 1.0,
|
||||
decay: 0.008 + Math.random() * 0.02,
|
||||
radius: 2 + Math.random() * 5,
|
||||
radius: (2 + Math.random() * 5) * particleSize,
|
||||
};
|
||||
break;
|
||||
}
|
||||
@@ -124,7 +136,7 @@
|
||||
vy: -(0.8 + Math.random() * 3 * loudness),
|
||||
life: 1.0,
|
||||
decay: 0.006 + Math.random() * 0.012,
|
||||
radius: 2 + Math.random() * 4,
|
||||
radius: (2 + Math.random() * 4) * particleSize,
|
||||
};
|
||||
break;
|
||||
}
|
||||
@@ -147,7 +159,7 @@
|
||||
vy: Math.sin(tangent) * speed + Math.sin(angle) * speed * 0.3,
|
||||
life: 1.0,
|
||||
decay: 0.006 + Math.random() * 0.015,
|
||||
radius: 2 + Math.random() * 6,
|
||||
radius: (2 + Math.random() * 6) * particleSize,
|
||||
};
|
||||
break;
|
||||
}
|
||||
@@ -164,7 +176,7 @@
|
||||
vy: Math.sin(angle) * speed,
|
||||
life: 1.0,
|
||||
decay: 0.005 + Math.random() * 0.015,
|
||||
radius: 3 + Math.random() * 7,
|
||||
radius: (3 + Math.random() * 7) * particleSize,
|
||||
};
|
||||
break;
|
||||
}
|
||||
@@ -193,15 +205,24 @@
|
||||
particles.pop();
|
||||
continue;
|
||||
}
|
||||
const alpha = Math.floor(p.life * 200)
|
||||
.toString(16)
|
||||
.padStart(2, "0");
|
||||
const color =
|
||||
useSecondary && Math.random() > 0.5 ? colors.secondary : colors.primary;
|
||||
ctx.beginPath();
|
||||
ctx.arc(p.x, p.y, p.radius * p.life, 0, Math.PI * 2);
|
||||
ctx.fillStyle = color + alpha;
|
||||
ctx.fill();
|
||||
if (pImg && pImg.complete) {
|
||||
const sz = p.radius * p.life * 3;
|
||||
ctx.globalAlpha = p.life;
|
||||
ctx.drawImage(pImg, p.x - sz / 2, p.y - sz / 2, sz, sz);
|
||||
ctx.globalAlpha = 1;
|
||||
} else {
|
||||
const alpha = Math.floor(p.life * 200)
|
||||
.toString(16)
|
||||
.padStart(2, "0");
|
||||
const color =
|
||||
useSecondary && Math.random() > 0.5
|
||||
? colors.secondary
|
||||
: colors.primary;
|
||||
ctx.beginPath();
|
||||
ctx.arc(p.x, p.y, p.radius * p.life, 0, Math.PI * 2);
|
||||
ctx.fillStyle = color + alpha;
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
export let glowIntensity = 0.6;
|
||||
export let logoSpin = false;
|
||||
export let logoSpinSpeed = 5;
|
||||
export let particleImage = "";
|
||||
export let particleSize = 1.0;
|
||||
export let titlePosition = "top";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
@@ -89,6 +91,13 @@
|
||||
if (file) readFileAsDataUrl(file, (url) => (logoUrl = url));
|
||||
}
|
||||
|
||||
let particleImgInput;
|
||||
|
||||
function handleParticleImgUpload(e) {
|
||||
const file = e.target.files[0];
|
||||
if (file) readFileAsDataUrl(file, (url) => (particleImage = url));
|
||||
}
|
||||
|
||||
function handleBgUpload(e) {
|
||||
const file = e.target.files[0];
|
||||
if (file) readFileAsDataUrl(file, (url) => (bgImage = url));
|
||||
@@ -553,6 +562,42 @@
|
||||
bind:value={particleDensity}
|
||||
/>
|
||||
</div>
|
||||
<div class="slider-row">
|
||||
<label for="slider-psize"
|
||||
>Size <span class="slider-val">{particleSize.toFixed(1)}</span></label
|
||||
>
|
||||
<input
|
||||
id="slider-psize"
|
||||
type="range"
|
||||
min="0.3"
|
||||
max="5.0"
|
||||
step="0.1"
|
||||
bind:value={particleSize}
|
||||
/>
|
||||
</div>
|
||||
<div class="inline-row" style="margin-top: 0.5rem; gap: 0.4rem">
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
on:change={handleParticleImgUpload}
|
||||
bind:this={particleImgInput}
|
||||
id="particle-img-upload"
|
||||
style="display: none"
|
||||
/>
|
||||
<label for="particle-img-upload" class="upload-btn"
|
||||
>Particle Image</label
|
||||
>
|
||||
{#if particleImage}
|
||||
<img
|
||||
src={particleImage}
|
||||
alt="particle"
|
||||
style="width: 22px; height: 22px; object-fit: cover; border-radius: 4px"
|
||||
/>
|
||||
<button class="clear-btn" on:click={() => (particleImage = "")}
|
||||
>Clear</button
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
<div class="slider-row">
|
||||
<label for="slider-shake"
|
||||
|
||||
Reference in New Issue
Block a user