mirror of
https://github.com/arthur-pbty/syncfilm.git
synced 2026-06-03 15:07:40 +02:00
260 lines
7.7 KiB
JavaScript
260 lines
7.7 KiB
JavaScript
// Configuration du mode Madame
|
|
const config = {
|
|
maxHearts: 30,
|
|
heartColors: ["#ff69b4", "#ff1493", "#ff69b4"],
|
|
heartSizes: {
|
|
min: 15,
|
|
max: 30,
|
|
},
|
|
heartOpacity: {
|
|
min: 0.2,
|
|
max: 0.6,
|
|
},
|
|
animationDuration: {
|
|
min: 3,
|
|
max: 6,
|
|
},
|
|
explosionParticles: 8,
|
|
explosionDistance: 100,
|
|
};
|
|
|
|
// État du mode Madame
|
|
const state = {
|
|
isActive: localStorage.getItem("madameMode") === "true",
|
|
activeHearts: 0,
|
|
cursorHeart: null,
|
|
heartInterval: null,
|
|
};
|
|
|
|
// Création du cœur du curseur
|
|
function createCursorHeart() {
|
|
const heart = document.createElement("div");
|
|
heart.className = "cursor-heart";
|
|
heart.innerHTML = "❤";
|
|
heart.style.display = "none";
|
|
document.body.appendChild(heart);
|
|
return heart;
|
|
}
|
|
|
|
// Création d'un cœur avec des propriétés aléatoires
|
|
function createHeart(x, y) {
|
|
const heart = document.createElement("div");
|
|
heart.className = "floating-heart";
|
|
heart.innerHTML = "❤";
|
|
heart.style.position = "fixed";
|
|
heart.style.color =
|
|
config.heartColors[Math.floor(Math.random() * config.heartColors.length)];
|
|
heart.style.fontSize = `${
|
|
Math.random() * (config.heartSizes.max - config.heartSizes.min) +
|
|
config.heartSizes.min
|
|
}px`;
|
|
heart.style.opacity =
|
|
Math.random() * (config.heartOpacity.max - config.heartOpacity.min) +
|
|
config.heartOpacity.min;
|
|
heart.style.pointerEvents = "none";
|
|
|
|
if (x && y) {
|
|
heart.style.left = `${x}px`;
|
|
heart.style.top = `${y}px`;
|
|
} else {
|
|
heart.style.left = `${Math.random() * window.innerWidth}px`;
|
|
heart.style.top = `${Math.random() * window.innerHeight}px`;
|
|
}
|
|
|
|
const duration =
|
|
Math.random() *
|
|
(config.animationDuration.max - config.animationDuration.min) +
|
|
config.animationDuration.min;
|
|
const delay = Math.random() * 2;
|
|
heart.style.animation = `float ${duration}s infinite`;
|
|
heart.style.animationDelay = `${delay}s`;
|
|
|
|
return heart;
|
|
}
|
|
|
|
// Création des particules d'explosion
|
|
function createExplosionParticles(heart) {
|
|
for (let i = 0; i < config.explosionParticles; i++) {
|
|
const particle = document.createElement("div");
|
|
particle.innerHTML = "❤";
|
|
particle.style.position = "fixed";
|
|
particle.style.color =
|
|
config.heartColors[Math.floor(Math.random() * config.heartColors.length)];
|
|
particle.style.fontSize = "12px";
|
|
particle.style.opacity = "0.8";
|
|
particle.style.pointerEvents = "none";
|
|
particle.style.left = heart.style.left;
|
|
particle.style.top = heart.style.top;
|
|
|
|
const angle = (i / config.explosionParticles) * Math.PI * 2;
|
|
const x = Math.cos(angle) * config.explosionDistance;
|
|
const y = Math.sin(angle) * config.explosionDistance;
|
|
|
|
particle.style.animation = `explode 0.5s ease-out forwards`;
|
|
particle.style.setProperty("--x", `${x}px`);
|
|
particle.style.setProperty("--y", `${y}px`);
|
|
|
|
document.body.appendChild(particle);
|
|
setTimeout(() => particle.remove(), 500);
|
|
}
|
|
}
|
|
|
|
// Explosion d'un cœur
|
|
function explodeHeart(heart) {
|
|
createExplosionParticles(heart);
|
|
heart.remove();
|
|
}
|
|
|
|
// Création de cœurs flottants
|
|
function createFloatingHearts() {
|
|
const hearts = Array.from(document.querySelectorAll(".floating-heart"));
|
|
|
|
if (hearts.length >= config.maxHearts) {
|
|
// Calculer combien de cœurs sont en trop
|
|
const heartsToRemove = hearts.length - config.maxHearts;
|
|
|
|
// Mélanger le tableau des cœurs
|
|
for (let i = hearts.length - 1; i > 0; i--) {
|
|
const j = Math.floor(Math.random() * (i + 1));
|
|
[hearts[i], hearts[j]] = [hearts[j], hearts[i]];
|
|
}
|
|
|
|
// Supprimer les cœurs en trop
|
|
for (let i = 0; i < heartsToRemove; i++) {
|
|
explodeHeart(hearts[i]);
|
|
state.activeHearts--;
|
|
}
|
|
}
|
|
|
|
for (let i = 0; i < 5; i++) {
|
|
if (state.activeHearts >= config.maxHearts) break;
|
|
|
|
const heart = createHeart();
|
|
document.body.appendChild(heart);
|
|
state.activeHearts++;
|
|
|
|
heart.addEventListener("animationend", () => {
|
|
heart.remove();
|
|
state.activeHearts--;
|
|
if (state.isActive) {
|
|
createFloatingHearts();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// Création de cœurs au clic
|
|
function createClickHearts(e) {
|
|
if (!state.isActive) return;
|
|
|
|
// Cœur principal au point de clic
|
|
const mainHeart = createHeart(e.clientX, e.clientY);
|
|
document.body.appendChild(mainHeart);
|
|
state.activeHearts++;
|
|
|
|
// Cœurs supplémentaires dans un rayon
|
|
for (let i = 0; i < 5; i++) {
|
|
if (state.activeHearts >= config.maxHearts) break;
|
|
|
|
const angle = Math.random() * Math.PI * 2;
|
|
const radius = Math.random() * 100;
|
|
const x = e.clientX + Math.cos(angle) * radius;
|
|
const y = e.clientY + Math.sin(angle) * radius;
|
|
|
|
const heart = createHeart(x, y);
|
|
document.body.appendChild(heart);
|
|
state.activeHearts++;
|
|
}
|
|
|
|
// Gestion de la limite de cœurs
|
|
const hearts = Array.from(document.querySelectorAll(".floating-heart"));
|
|
if (hearts.length > config.maxHearts) {
|
|
const heartsToRemove = hearts.length - config.maxHearts;
|
|
|
|
// Mélanger le tableau des cœurs
|
|
for (let i = hearts.length - 1; i > 0; i--) {
|
|
const j = Math.floor(Math.random() * (i + 1));
|
|
[hearts[i], hearts[j]] = [hearts[j], hearts[i]];
|
|
}
|
|
|
|
// Supprimer les cœurs en trop
|
|
for (let i = 0; i < heartsToRemove; i++) {
|
|
explodeHeart(hearts[i]);
|
|
state.activeHearts--;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Mise à jour de la position du cœur du curseur
|
|
function updateCursorHeart(e) {
|
|
if (state.isActive) {
|
|
state.cursorHeart.style.display = "block";
|
|
state.cursorHeart.style.left = `${e.clientX}px`;
|
|
state.cursorHeart.style.top = `${e.clientY}px`;
|
|
} else {
|
|
state.cursorHeart.style.display = "none";
|
|
}
|
|
}
|
|
|
|
// Activation/désactivation du mode Madame
|
|
function toggleMadameMode() {
|
|
state.isActive = !state.isActive;
|
|
document.body.classList.toggle("madame-mode", state.isActive);
|
|
localStorage.setItem("madameMode", state.isActive);
|
|
|
|
state.cursorHeart.style.display = state.isActive ? "block" : "none";
|
|
|
|
if (state.isActive) {
|
|
state.heartInterval = setInterval(createFloatingHearts, 2000);
|
|
createFloatingHearts();
|
|
} else {
|
|
clearInterval(state.heartInterval);
|
|
// Supprimer tous les cœurs existants avec effet d'explosion
|
|
const hearts = document.querySelectorAll(".floating-heart");
|
|
hearts.forEach(explodeHeart);
|
|
state.activeHearts = 0;
|
|
}
|
|
}
|
|
|
|
// Initialisation du mode Madame
|
|
function initMadameMode() {
|
|
state.cursorHeart = createCursorHeart();
|
|
|
|
if (state.isActive) {
|
|
document.body.classList.add("madame-mode");
|
|
state.cursorHeart.style.display = "block";
|
|
createFloatingHearts();
|
|
}
|
|
|
|
// Événements
|
|
document.addEventListener("mousemove", updateCursorHeart);
|
|
document.addEventListener("click", createClickHearts);
|
|
document
|
|
.getElementById("madame-mode")
|
|
.addEventListener("click", toggleMadameMode);
|
|
}
|
|
|
|
// Gestion du mode plein écran
|
|
function handleFullscreenChange() {
|
|
const isFullscreen =
|
|
document.fullscreenElement ||
|
|
document.mozFullScreenElement ||
|
|
document.webkitFullscreenElement ||
|
|
document.msFullscreenElement;
|
|
|
|
if (isFullscreen) {
|
|
document.getElementById("video-player").appendChild(state.cursorHeart);
|
|
} else {
|
|
document.body.appendChild(state.cursorHeart);
|
|
}
|
|
}
|
|
|
|
// Initialisation
|
|
document.addEventListener("DOMContentLoaded", initMadameMode);
|
|
|
|
// Événements de plein écran
|
|
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
document.addEventListener("mozfullscreenchange", handleFullscreenChange);
|
|
document.addEventListener("webkitfullscreenchange", handleFullscreenChange);
|
|
document.addEventListener("MSFullscreenChange", handleFullscreenChange);
|