Compare commits
42 Commits
492acb4052
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a67e3c5763 | ||
|
|
b810c9cbaf | ||
|
|
d55d52c538 | ||
|
|
faa867956a | ||
|
|
5b3e405b99 | ||
|
|
30e624fa64 | ||
|
|
41494785ca | ||
|
|
4196a72615 | ||
|
|
9a4ef773dc | ||
|
|
7e67233dea | ||
|
|
6ca3098432 | ||
|
|
1a3a5b7cff | ||
|
|
b40ee5eea6 | ||
|
|
c684651cef | ||
|
|
3dffd847de | ||
|
|
9f7ecd9cd0 | ||
|
|
25e678af8d | ||
|
|
cc2c5eb973 | ||
|
|
8c02a07b88 | ||
|
|
7da6549bf9 | ||
|
|
2e6c1534b1 | ||
|
|
0a301564ac | ||
|
|
85e69a0b34 | ||
|
|
5adaf202ae | ||
|
|
99ac46a384 | ||
|
|
3a2750388b | ||
|
|
33e89ec16b | ||
|
|
9adbe92e7c | ||
|
|
103d63f1b1 | ||
|
|
49bad2e880 | ||
|
|
04616c2ac4 | ||
|
|
3b73dd1728 | ||
|
|
d5df90a6ae | ||
|
|
494e475f42 | ||
|
|
4703ba48ed | ||
|
|
93d5686b77 | ||
|
|
71d07aa0f3 | ||
|
|
c43f031617 | ||
|
|
89ce903e8a | ||
|
|
cbf5d73629 | ||
|
|
8be17dae74 | ||
|
|
76006dc162 |
@@ -77,7 +77,32 @@ public class PluginConfiguration : BasePluginConfiguration
|
||||
/// <summary>
|
||||
/// Gets or sets the seasonal rules configuration as JSON.
|
||||
/// </summary>
|
||||
public string SeasonalRules { get; set; } = "[{\"Name\":\"New Year Fireworks\",\"StartDay\":28,\"StartMonth\":12,\"EndDay\":5,\"EndMonth\":1,\"Theme\":\"fireworks\"},{\"Name\":\"Carnival\",\"StartDay\":19,\"StartMonth\":2,\"EndDay\":28,\"EndMonth\":2,\"Theme\":\"carnival\"},{\"Name\":\"Valentine's Day\",\"StartDay\":10,\"StartMonth\":2,\"EndDay\":18,\"EndMonth\":2,\"Theme\":\"hearts\"},{\"Name\":\"Spring\",\"StartDay\":1,\"StartMonth\":3,\"EndDay\":31,\"EndMonth\":5,\"Theme\":\"spring\"},{\"Name\":\"Summer\",\"StartDay\":1,\"StartMonth\":6,\"EndDay\":31,\"EndMonth\":8,\"Theme\":\"summer\"},{\"Name\":\"Santa\",\"StartDay\":22,\"StartMonth\":12,\"EndDay\":27,\"EndMonth\":12,\"Theme\":\"santa\"},{\"Name\":\"Snowflakes (December)\",\"StartDay\":1,\"StartMonth\":12,\"EndDay\":31,\"EndMonth\":12,\"Theme\":\"snowflakes\"},{\"Name\":\"Snowfall (January)\",\"StartDay\":1,\"StartMonth\":1,\"EndDay\":31,\"EndMonth\":1,\"Theme\":\"snowfall\"},{\"Name\":\"Snowfall (February)\",\"StartDay\":1,\"StartMonth\":2,\"EndDay\":29,\"EndMonth\":2,\"Theme\":\"snowfall\"},{\"Name\":\"Easter\",\"StartDay\":25,\"StartMonth\":3,\"EndDay\":25,\"EndMonth\":4,\"Theme\":\"easter\"},{\"Name\":\"Halloween\",\"StartDay\":24,\"StartMonth\":10,\"EndDay\":5,\"EndMonth\":11,\"Theme\":\"halloween\"},{\"Name\":\"Autumn\",\"StartDay\":1,\"StartMonth\":9,\"EndDay\":30,\"EndMonth\":11,\"Theme\":\"autumn\"},{\"Name\":\"Cherry Blossom\",\"StartDay\":1,\"StartMonth\":4,\"EndDay\":30,\"EndMonth\":4,\"Theme\":\"cherryblossom\"}]";
|
||||
public string SeasonalRules { get; set; } = "[" +
|
||||
"{\"Name\":\"New Year Fireworks\",\"StartDay\":28,\"StartMonth\":12,\"EndDay\":5,\"EndMonth\":1,\"Theme\":\"fireworks\"}," +
|
||||
"{\"Name\":\"Snowfall (January)\",\"StartDay\":1,\"StartMonth\":1,\"EndDay\":31,\"EndMonth\":1,\"Theme\":\"snowfall\"}," +
|
||||
"{\"Name\":\"Snowfall (February)\",\"StartDay\":1,\"StartMonth\":2,\"EndDay\":29,\"EndMonth\":2,\"Theme\":\"snowfall\"}," +
|
||||
"{\"Name\":\"Valentine's Day\",\"StartDay\":10,\"StartMonth\":2,\"EndDay\":18,\"EndMonth\":2,\"Theme\":\"hearts\"}," +
|
||||
"{\"Name\":\"Carnival\",\"StartDay\":19,\"StartMonth\":2,\"EndDay\":28,\"EndMonth\":2,\"Theme\":\"carnival\"}," +
|
||||
"{\"Name\":\"Oscar Awards\",\"StartDay\":23,\"StartMonth\":2,\"EndDay\":5,\"EndMonth\":3,\"Theme\":\"oscar\"}," +
|
||||
"{\"Name\":\"Mario Day\",\"StartDay\":10,\"StartMonth\":3,\"EndDay\":10,\"EndMonth\":3,\"Theme\":\"marioday\"}," +
|
||||
"{\"Name\":\"Film Noir Day\",\"StartDay\":17,\"StartMonth\":3,\"EndDay\":17,\"EndMonth\":3,\"Theme\":\"filmnoir\"}," +
|
||||
"{\"Name\":\"Spring\",\"StartDay\":1,\"StartMonth\":3,\"EndDay\":31,\"EndMonth\":5,\"Theme\":\"spring\"}," +
|
||||
"{\"Name\":\"Cherry Blossom\",\"StartDay\":1,\"StartMonth\":4,\"EndDay\":30,\"EndMonth\":4,\"Theme\":\"cherryblossom\"}," +
|
||||
"{\"Name\":\"Easter\",\"StartDay\":25,\"StartMonth\":3,\"EndDay\":25,\"EndMonth\":4,\"Theme\":\"easter\"}," +
|
||||
"{\"Name\":\"Earth Day\",\"StartDay\":22,\"StartMonth\":4,\"EndDay\":22,\"EndMonth\":4,\"Theme\":\"earthday\"}," +
|
||||
"{\"Name\":\"Space Day\",\"StartDay\":12,\"StartMonth\":4,\"EndDay\":12,\"EndMonth\":4,\"Theme\":\"space\"}," +
|
||||
"{\"Name\":\"Star Wars Day\",\"StartDay\":4,\"StartMonth\":5,\"EndDay\":5,\"EndMonth\":5,\"Theme\":\"starwars\"}," +
|
||||
"{\"Name\":\"Eurovision\",\"StartDay\":6,\"StartMonth\":5,\"EndDay\":12,\"EndMonth\":5,\"Theme\":\"eurovision\"}," +
|
||||
"{\"Name\":\"Pride Month\",\"StartDay\":1,\"StartMonth\":6,\"EndDay\":30,\"EndMonth\":6,\"Theme\":\"pride\"}," +
|
||||
"{\"Name\":\"Summer\",\"StartDay\":1,\"StartMonth\":6,\"EndDay\":31,\"EndMonth\":8,\"Theme\":\"summer\"}," +
|
||||
"{\"Name\":\"Underwater\",\"StartDay\":1,\"StartMonth\":7,\"EndDay\":31,\"EndMonth\":8,\"Theme\":\"underwater\"}," +
|
||||
"{\"Name\":\"Autumn\",\"StartDay\":1,\"StartMonth\":9,\"EndDay\":30,\"EndMonth\":11,\"Theme\":\"autumn\"}," +
|
||||
"{\"Name\":\"Oktoberfest\",\"StartDay\":20,\"StartMonth\":9,\"EndDay\":5,\"EndMonth\":10,\"Theme\":\"oktoberfest\"}," +
|
||||
"{\"Name\":\"Halloween\",\"StartDay\":24,\"StartMonth\":10,\"EndDay\":5,\"EndMonth\":11,\"Theme\":\"halloween\"}," +
|
||||
"{\"Name\":\"Spooky (Pre-Halloween)\",\"StartDay\":1,\"StartMonth\":10,\"EndDay\":23,\"EndMonth\":10,\"Theme\":\"spooky\"}," +
|
||||
"{\"Name\":\"Snowflakes (December)\",\"StartDay\":1,\"StartMonth\":12,\"EndDay\":31,\"EndMonth\":12,\"Theme\":\"snowflakes\"}," +
|
||||
"{\"Name\":\"Santa\",\"StartDay\":22,\"StartMonth\":12,\"EndDay\":27,\"EndMonth\":12,\"Theme\":\"santa\"}" +
|
||||
"]";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Seasonals options.
|
||||
@@ -120,10 +145,9 @@ public class PluginConfiguration : BasePluginConfiguration
|
||||
}
|
||||
|
||||
public class AutumnOptions {
|
||||
public int LeafCount { get; set; } = 25;
|
||||
public bool EnableAutumn { get; set; } = true;
|
||||
public bool EnableRandomLeaves { get; set; } = true;
|
||||
public bool EnableRandomLeavesMobile { get; set; } = false;
|
||||
public int LeafCount { get; set; } = 35;
|
||||
public int LeafCountMobile { get; set; } = 10;
|
||||
public bool EnableDifferentDuration { get; set; } = true;
|
||||
public bool EnableRotation { get; set; } = false;
|
||||
}
|
||||
@@ -153,15 +177,15 @@ public class CherryBlossomOptions {
|
||||
|
||||
public class ChristmasOptions {
|
||||
public bool EnableChristmas { get; set; } = true;
|
||||
public bool EnableRandomChristmas { get; set; } = true;
|
||||
public bool EnableRandomChristmasMobile { get; set; } = false;
|
||||
public bool EnableDifferentDuration { get; set; } = true;
|
||||
public int SymbolCount { get; set; } = 25;
|
||||
public int SymbolCountMobile { get; set; } = 10;
|
||||
public bool EnableDifferentDuration { get; set; } = true;
|
||||
}
|
||||
|
||||
public class EarthDayOptions {
|
||||
public bool EnableEarthDay { get; set; } = true;
|
||||
public int VineCount { get; set; } = 4;
|
||||
public int FlowersCount { get; set; } = 60;
|
||||
public int FlowersCountMobile { get; set; } = 20;
|
||||
}
|
||||
|
||||
public class EasterOptions {
|
||||
@@ -210,20 +234,18 @@ public class FrostOptions {
|
||||
|
||||
public class HalloweenOptions {
|
||||
public bool EnableHalloween { get; set; } = true;
|
||||
public bool EnableRandomSymbols { get; set; } = true;
|
||||
public bool EnableRandomSymbolsMobile { get; set; } = false;
|
||||
public int SymbolCount { get; set; } = 25;
|
||||
public int SymbolCountMobile { get; set; } = 10;
|
||||
public bool EnableDifferentDuration { get; set; } = true;
|
||||
public bool EnableSpiders { get; set; } = true;
|
||||
public bool EnableMice { get; set; } = true;
|
||||
public int SymbolCount { get; set; } = 25;
|
||||
}
|
||||
|
||||
public class HeartsOptions {
|
||||
public bool EnableHearts { get; set; } = true;
|
||||
public bool EnableRandomSymbols { get; set; } = true;
|
||||
public bool EnableRandomSymbolsMobile { get; set; } = false;
|
||||
public bool EnableDifferentDuration { get; set; } = true;
|
||||
public int SymbolCount { get; set; } = 25;
|
||||
public int SymbolCountMobile { get; set; } = 10;
|
||||
public bool EnableDifferentDuration { get; set; } = true;
|
||||
}
|
||||
|
||||
public class MarioDayOptions {
|
||||
@@ -259,7 +281,7 @@ public class OscarOptions {
|
||||
public class PrideOptions {
|
||||
public bool EnablePride { get; set; } = true;
|
||||
public int HeartCount { get; set; } = 20;
|
||||
public int HeartSize { get; set; } = 1.5;
|
||||
public double HeartSize { get; set; } = 1.5;
|
||||
public bool ColorHeader { get; set; } = true;
|
||||
}
|
||||
|
||||
@@ -272,10 +294,9 @@ public class RainOptions {
|
||||
|
||||
public class ResurrectionOptions {
|
||||
public bool EnableResurrection { get; set; } = true;
|
||||
public bool EnableRandomSymbols { get; set; } = true;
|
||||
public bool EnableRandomSymbolsMobile { get; set; } = false;
|
||||
public bool EnableDifferentDuration { get; set; } = true;
|
||||
public int SymbolCount { get; set; } = 12;
|
||||
public int SymbolCountMobile { get; set; } = 5;
|
||||
public bool EnableDifferentDuration { get; set; } = true;
|
||||
}
|
||||
|
||||
public class SantaOptions {
|
||||
@@ -301,8 +322,7 @@ public class SnowfallOptions {
|
||||
public class SnowflakesOptions {
|
||||
public bool EnableSnowflakes { get; set; } = true;
|
||||
public int SnowflakeCount { get; set; } = 25;
|
||||
public bool EnableRandomSnowflakes { get; set; } = true;
|
||||
public bool EnableRandomSnowflakesMobile { get; set; } = false;
|
||||
public int SnowflakeCountMobile { get; set; } = 10;
|
||||
public bool EnableColoredSnowflakes { get; set; } = true;
|
||||
public bool EnableDifferentDuration { get; set; } = true;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@
|
||||
<!-- <TreatWarningsAsErrors>false</TreatWarningsAsErrors> -->
|
||||
<Title>Jellyfin Seasonals Plugin</Title>
|
||||
<Authors>CodeDevMLH</Authors>
|
||||
<Version>2.0.0.1</Version>
|
||||
<Version>2.0.0.8</Version>
|
||||
<RepositoryUrl>https://github.com/CodeDevMLH/Jellyfin-Seasonals</RepositoryUrl>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -1,139 +1,57 @@
|
||||
.autumn-container {
|
||||
display: block;
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
contain: layout paint;
|
||||
}
|
||||
|
||||
.leaf {
|
||||
position: fixed;
|
||||
z-index: 15;
|
||||
top: 0;
|
||||
will-change: transform;
|
||||
translate: 0 -10vh;
|
||||
font-size: 1em;
|
||||
color: #fff;
|
||||
font-family: Arial, sans-serif;
|
||||
text-shadow: 0 0 5px #000;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
animation-name: leaf-fall, leaf-shake;
|
||||
animation-duration: 7s, 4s;
|
||||
animation-timing-function: linear, ease-in-out;
|
||||
animation-iteration-count: infinite, infinite;
|
||||
}
|
||||
|
||||
/* Class to disable rotation */
|
||||
.no-rotation {
|
||||
--rotate-start: 0deg !important;
|
||||
--rotate-end: 0deg !important;
|
||||
}
|
||||
|
||||
|
||||
@keyframes leaf-fall {
|
||||
0% {
|
||||
translate: 0 -10vh;
|
||||
}
|
||||
|
||||
100% {
|
||||
translate: 0 100vh;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@keyframes leaf-shake {
|
||||
0%, 100% {
|
||||
transform: translateX(0) rotate(var(--rotate-start, -20deg));
|
||||
}
|
||||
50% {
|
||||
transform: translateX(80px) rotate(var(--rotate-end, 20deg));
|
||||
}
|
||||
}
|
||||
|
||||
.leaf:nth-of-type(0) {
|
||||
left: 0%;
|
||||
animation-delay: 0s, 0s;
|
||||
--rotate-start: -25deg;
|
||||
--rotate-end: 22deg;
|
||||
}
|
||||
|
||||
.leaf:nth-of-type(1) {
|
||||
left: 10%;
|
||||
animation-delay: 1s, 0.5s;
|
||||
--rotate-start: -32deg;
|
||||
--rotate-end: 35deg;
|
||||
}
|
||||
|
||||
.leaf:nth-of-type(2) {
|
||||
left: 20%;
|
||||
animation-delay: 6s, 1s;
|
||||
--rotate-start: -28deg;
|
||||
--rotate-end: 28deg;
|
||||
}
|
||||
|
||||
.leaf:nth-of-type(3) {
|
||||
left: 30%;
|
||||
animation-delay: 4s, 1.5s;
|
||||
--rotate-start: -38deg;
|
||||
--rotate-end: 32deg;
|
||||
}
|
||||
|
||||
.leaf:nth-of-type(4) {
|
||||
left: 40%;
|
||||
animation-delay: 2s, 0.8s;
|
||||
--rotate-start: -22deg;
|
||||
--rotate-end: 38deg;
|
||||
}
|
||||
|
||||
.leaf:nth-of-type(5) {
|
||||
left: 50%;
|
||||
animation-delay: 8s, 2s;
|
||||
--rotate-start: -35deg;
|
||||
--rotate-end: 25deg;
|
||||
}
|
||||
|
||||
.leaf:nth-of-type(6) {
|
||||
left: 60%;
|
||||
animation-delay: 6s, 1.2s;
|
||||
--rotate-start: -40deg;
|
||||
--rotate-end: 40deg;
|
||||
}
|
||||
|
||||
.leaf:nth-of-type(7) {
|
||||
left: 70%;
|
||||
animation-delay: 2.5s, 0.3s;
|
||||
--rotate-start: -30deg;
|
||||
--rotate-end: 30deg;
|
||||
}
|
||||
|
||||
.leaf:nth-of-type(8) {
|
||||
left: 80%;
|
||||
animation-delay: 1s, 1.8s;
|
||||
--rotate-start: -26deg;
|
||||
--rotate-end: 36deg;
|
||||
}
|
||||
|
||||
.leaf:nth-of-type(9) {
|
||||
left: 90%;
|
||||
animation-delay: 3s, 0.7s;
|
||||
--rotate-start: -34deg;
|
||||
--rotate-end: 24deg;
|
||||
}
|
||||
|
||||
.leaf:nth-of-type(10) {
|
||||
left: 25%;
|
||||
animation-delay: 2s, 2.3s;
|
||||
--rotate-start: -29deg;
|
||||
--rotate-end: 33deg;
|
||||
}
|
||||
|
||||
.leaf:nth-of-type(11) {
|
||||
left: 65%;
|
||||
animation-delay: 4s, 1.4s;
|
||||
--rotate-start: -37deg;
|
||||
.autumn-container {
|
||||
display: block;
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
contain: layout paint;
|
||||
}
|
||||
|
||||
.leaf {
|
||||
position: fixed;
|
||||
z-index: 15;
|
||||
top: 0;
|
||||
will-change: transform;
|
||||
translate: 0 -10vh;
|
||||
font-size: 1em;
|
||||
color: #fff;
|
||||
font-family: Arial, sans-serif;
|
||||
text-shadow: 0 0 5px #000;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
animation-name: leaf-fall, leaf-shake;
|
||||
animation-duration: 7s, 4s;
|
||||
animation-timing-function: linear, ease-in-out;
|
||||
animation-iteration-count: infinite, infinite;
|
||||
}
|
||||
|
||||
/* Class to disable rotation */
|
||||
.no-rotation {
|
||||
--rotate-start: 0deg !important;
|
||||
--rotate-end: 0deg !important;
|
||||
}
|
||||
|
||||
|
||||
@keyframes leaf-fall {
|
||||
0% {
|
||||
translate: 0 -10vh;
|
||||
}
|
||||
|
||||
100% {
|
||||
translate: 0 100vh;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@keyframes leaf-shake {
|
||||
0%, 100% {
|
||||
transform: translateX(0) rotate(var(--rotate-start, -20deg));
|
||||
}
|
||||
50% {
|
||||
transform: translateX(80px) rotate(var(--rotate-end, 20deg));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
const config = window.SeasonalsPluginConfig?.Autumn || {};
|
||||
|
||||
const leaves = config.EnableAutumn !== undefined ? config.EnableAutumn : true; // enable/disable autumn
|
||||
const randomLeaves = config.EnableRandomLeaves !== undefined ? config.EnableRandomLeaves : true; // enable random leaves
|
||||
const randomLeavesMobile = config.EnableRandomLeavesMobile !== undefined ? config.EnableRandomLeavesMobile : false; // enable random leaves on mobile
|
||||
const enableDiffrentDuration = config.EnableDifferentDuration !== undefined ? config.EnableDifferentDuration : true; // enable different durations
|
||||
const enableRotation = config.EnableRotation !== undefined ? config.EnableRotation : false; // enable/disable rotation
|
||||
const leafCount = config.LeafCount !== undefined ? config.LeafCount : 25; // count of random extra leaves
|
||||
const leafCount = config.LeafCount !== undefined ? config.LeafCount : 35; // count of random extra leaves
|
||||
const leafCountMobile = config.LeafCountMobile !== undefined ? config.LeafCountMobile : 10; // count of random extra leaves on mobile
|
||||
|
||||
const images = [
|
||||
"../Seasonals/Resources/autumn_images/acorn1.png",
|
||||
@@ -64,11 +63,16 @@ observer.observe(document.body, {
|
||||
});
|
||||
|
||||
|
||||
function addRandomLeaves(count) {
|
||||
const autumnContainer = document.querySelector('.autumn-container'); // get the leave container
|
||||
if (!autumnContainer) return; // exit if leave container is not found
|
||||
function initLeaves(count) {
|
||||
let autumnContainer = document.querySelector('.autumn-container'); // get the leave container
|
||||
if (!autumnContainer) {
|
||||
autumnContainer = document.createElement("div");
|
||||
autumnContainer.className = "autumn-container";
|
||||
autumnContainer.setAttribute("aria-hidden", "true");
|
||||
document.body.appendChild(autumnContainer);
|
||||
}
|
||||
|
||||
console.log('Adding random leaves');
|
||||
console.log('Adding leaves');
|
||||
|
||||
// Array of leave characters
|
||||
for (let i = 0; i < count; i++) {
|
||||
@@ -87,6 +91,8 @@ function addRandomLeaves(count) {
|
||||
// set random horizontal position, animation delay and size(uncomment lines to enable)
|
||||
const randomLeft = Math.random() * 100; // position (0% to 100%)
|
||||
const randomAnimationDelay = Math.random() * 12; // delay for fall (0s to 12s)
|
||||
// Display directly symbols on full screen (below) or let it build up (above)
|
||||
// const randomAnimationDelay = -(Math.random() * 16); // delay for fall (-16s to 0s)
|
||||
const randomAnimationDelay2 = -(Math.random() * 4); // delay for shake+rotate (-4s to 0s)
|
||||
|
||||
// apply styles
|
||||
@@ -115,60 +121,18 @@ function addRandomLeaves(count) {
|
||||
// add the leave to the container
|
||||
autumnContainer.appendChild(leaveDiv);
|
||||
}
|
||||
console.log('Random leaves added');
|
||||
console.log('Leaves added');
|
||||
}
|
||||
|
||||
// initialize standard leaves
|
||||
function initLeaves() {
|
||||
const container = document.querySelector('.autumn-container') || document.createElement("div");
|
||||
|
||||
if (!document.querySelector('.autumn-container')) {
|
||||
container.className = "autumn-container";
|
||||
container.setAttribute("aria-hidden", "true");
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 12; i++) {
|
||||
const leafDiv = document.createElement("div");
|
||||
leafDiv.className = enableRotation ? "leaf" : "leaf no-rotation";
|
||||
|
||||
const img = document.createElement("img");
|
||||
img.src = images[Math.floor(Math.random() * images.length)];
|
||||
|
||||
// set random animation duration
|
||||
if (enableDiffrentDuration) {
|
||||
const randomAnimationDuration = Math.random() * 10 + 6; // fall duration (6s to 16s)
|
||||
const randomAnimationDuration2 = Math.random() * 3 + 2; // shake+rotate duration (2s to 5s)
|
||||
leafDiv.style.animationDuration = `${randomAnimationDuration}s, ${randomAnimationDuration2}s`;
|
||||
}
|
||||
|
||||
// set random rotation angles for standard leaves too (only if rotation is enabled)
|
||||
if (enableRotation) {
|
||||
const randomRotateStart = -(Math.random() * 40 + 20); // -20deg to -60deg
|
||||
const randomRotateEnd = Math.random() * 40 + 20; // 20deg to 60deg
|
||||
leafDiv.style.setProperty('--rotate-start', `${randomRotateStart}deg`);
|
||||
leafDiv.style.setProperty('--rotate-end', `${randomRotateEnd}deg`);
|
||||
} else {
|
||||
// No rotation - set to 0 degrees
|
||||
leafDiv.style.setProperty('--rotate-start', '0deg');
|
||||
leafDiv.style.setProperty('--rotate-end', '0deg');
|
||||
}
|
||||
|
||||
leafDiv.appendChild(img);
|
||||
container.appendChild(leafDiv);
|
||||
}
|
||||
}
|
||||
|
||||
// initialize leaves and add random leaves
|
||||
// initialize leaves
|
||||
function initializeLeaves() {
|
||||
if (!leaves) return; // exit if leaves are disabled
|
||||
initLeaves();
|
||||
toggleAutumn();
|
||||
|
||||
const screenWidth = window.innerWidth; // get the screen width to detect mobile devices
|
||||
if (randomLeaves && (screenWidth > 768 || randomLeavesMobile)) { // add random leaves only on larger screens, unless enabled for mobile devices
|
||||
addRandomLeaves(leafCount);
|
||||
}
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const count = !isMobile ? leafCount : leafCountMobile;
|
||||
|
||||
initLeaves(count);
|
||||
toggleAutumn();
|
||||
}
|
||||
|
||||
initializeLeaves();
|
||||
@@ -1,11 +1,15 @@
|
||||
const config = window.SeasonalsPluginConfig?.Birthday || {};
|
||||
|
||||
const birthday = config.EnableBirthday !== undefined ? config.EnableBirthday : true; // enable/disable birthday symbols
|
||||
const symbolCount = config.SymbolCount !== undefined ? config.SymbolCount : 15; // count of balloons
|
||||
const symbolCount = config.SymbolCount !== undefined ? config.SymbolCount : 12; // count of balloons
|
||||
const enableDifferentDuration = config.EnableDifferentDuration !== undefined ? config.EnableDifferentDuration : true; // enable different duration for the symbols
|
||||
const symbolCountMobile = config.SymbolCountMobile !== undefined ? config.SymbolCountMobile : 5; // count of mobile balloons
|
||||
const baseConfettiCount = config.ConfettiCount !== undefined ? config.ConfettiCount : 60; // count of confetti
|
||||
|
||||
/**
|
||||
* Base ballon image: https://www.flaticon.com/de/kostenloses-icon/ballon_1512470
|
||||
* modified by CodeDevMLH
|
||||
*/
|
||||
const birthdayImages = [
|
||||
'../Seasonals/Resources/birthday_assets/balloon_blue.gif',
|
||||
'../Seasonals/Resources/birthday_assets/balloon_green.gif',
|
||||
|
||||
@@ -167,8 +167,8 @@ function initCarnivalObjects(count) {
|
||||
function initializeCarnival() {
|
||||
if (!carnival) return;
|
||||
|
||||
const screenWidth = window.innerWidth;
|
||||
const count = screenWidth > 768 ? carnivalCount : carnivalCountMobile;
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const count = !isMobile ? carnivalCount : carnivalCountMobile;
|
||||
|
||||
initCarnivalObjects(count);
|
||||
toggleCarnival();
|
||||
|
||||
@@ -84,8 +84,8 @@ function initObjects(count) {
|
||||
function initializeCherryBlossom() {
|
||||
if (!cherryBlossom) return;
|
||||
|
||||
const screenWidth = window.innerWidth;
|
||||
const count = screenWidth > 768 ? petalCount : petalCountMobile;
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const count = !isMobile ? petalCount : petalCountMobile;
|
||||
|
||||
initObjects(count);
|
||||
toggleCherryBlossom();
|
||||
|
||||
@@ -1,112 +1,53 @@
|
||||
.christmas-container {
|
||||
display: block;
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
contain: layout paint;
|
||||
}
|
||||
|
||||
.christmas {
|
||||
position: fixed;
|
||||
z-index: 15;
|
||||
top: 0;
|
||||
will-change: transform;
|
||||
translate: 0 -10vh;
|
||||
font-size: 1em;
|
||||
color: #fff;
|
||||
font-family: Arial, sans-serif;
|
||||
text-shadow: 0 0 5px #000;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
animation-name: christmas-fall, christmas-shake;
|
||||
animation-duration: 10s, 3s;
|
||||
animation-timing-function: linear, ease-in-out;
|
||||
animation-iteration-count: infinite, infinite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@keyframes christmas-fall {
|
||||
0% {
|
||||
translate: 0 -10vh;
|
||||
}
|
||||
|
||||
100% {
|
||||
translate: 0 110vh;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes christmas-shake {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateX(80px);
|
||||
}
|
||||
}
|
||||
|
||||
.christmas:nth-of-type(0) {
|
||||
left: 0%;
|
||||
animation-delay: 0s, 0s;
|
||||
}
|
||||
|
||||
.christmas:nth-of-type(1) {
|
||||
left: 10%;
|
||||
animation-delay: 1s, 1s;
|
||||
}
|
||||
|
||||
.christmas:nth-of-type(2) {
|
||||
left: 20%;
|
||||
animation-delay: 6s, 0.5s;
|
||||
}
|
||||
|
||||
.christmas:nth-of-type(3) {
|
||||
left: 30%;
|
||||
animation-delay: 4s, 2s;
|
||||
}
|
||||
|
||||
.christmas:nth-of-type(4) {
|
||||
left: 40%;
|
||||
animation-delay: 2s, 2s;
|
||||
}
|
||||
|
||||
.christmas:nth-of-type(5) {
|
||||
left: 50%;
|
||||
animation-delay: 8s, 3s;
|
||||
}
|
||||
|
||||
.christmas:nth-of-type(6) {
|
||||
left: 60%;
|
||||
animation-delay: 6s, 2s;
|
||||
}
|
||||
|
||||
.christmas:nth-of-type(7) {
|
||||
left: 70%;
|
||||
animation-delay: 2.5s, 1s;
|
||||
}
|
||||
|
||||
.christmas:nth-of-type(8) {
|
||||
left: 80%;
|
||||
animation-delay: 1s, 0s;
|
||||
}
|
||||
|
||||
.christmas:nth-of-type(9) {
|
||||
left: 90%;
|
||||
animation-delay: 3s, 1.5s;
|
||||
}
|
||||
|
||||
.christmas:nth-of-type(10) {
|
||||
left: 25%;
|
||||
animation-delay: 2s, 0s;
|
||||
}
|
||||
|
||||
.christmas:nth-of-type(11) {
|
||||
left: 65%;
|
||||
.christmas-container {
|
||||
display: block;
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
contain: layout paint;
|
||||
}
|
||||
|
||||
.christmas {
|
||||
position: fixed;
|
||||
z-index: 15;
|
||||
top: 0;
|
||||
will-change: transform;
|
||||
translate: 0 -10vh;
|
||||
font-size: 1em;
|
||||
color: #fff;
|
||||
font-family: Arial, sans-serif;
|
||||
text-shadow: 0 0 5px #000;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
animation-name: christmas-fall, christmas-shake;
|
||||
animation-duration: 10s, 3s;
|
||||
animation-timing-function: linear, ease-in-out;
|
||||
animation-iteration-count: infinite, infinite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@keyframes christmas-fall {
|
||||
0% {
|
||||
translate: 0 -10vh;
|
||||
}
|
||||
|
||||
100% {
|
||||
translate: 0 110vh;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes christmas-shake {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateX(80px);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
const config = window.SeasonalsPluginConfig?.Christmas || {};
|
||||
|
||||
const christmas = config.EnableChristmas !== undefined ? config.EnableChristmas : true; // enable/disable christmas
|
||||
const randomChristmas = config.EnableRandomChristmas !== undefined ? config.EnableRandomChristmas : true; // enable random christmas
|
||||
const randomChristmasMobile = config.EnableRandomChristmasMobile !== undefined ? config.EnableRandomChristmasMobile : false; // enable random christmas on mobile
|
||||
const enableDiffrentDuration = config.EnableDifferentDuration !== undefined ? config.EnableDifferentDuration : true; // enable different durations
|
||||
const christmasCount = config.SymbolCount !== undefined ? config.SymbolCount : 25; // count of symbol
|
||||
const christmasCountMobile = config.SymbolCountMobile !== undefined ? config.SymbolCountMobile : 10; // count of symbol on mobile
|
||||
|
||||
// Array of christmas characters
|
||||
const christmasSymbols = ['❆', '🎁', '❄️', '🎁', '🎅', '🎊', '🎁', '🎉'];
|
||||
@@ -45,11 +44,16 @@ observer.observe(document.body, {
|
||||
attributes: true
|
||||
});
|
||||
|
||||
function addRandomChristmas(count) {
|
||||
const christmasContainer = document.querySelector('.christmas-container'); // get the christmas container
|
||||
if (!christmasContainer) return; // exit if christmas container is not found
|
||||
function initChristmas(count) {
|
||||
let christmasContainer = document.querySelector('.christmas-container'); // get the christmas container
|
||||
if (!christmasContainer) {
|
||||
christmasContainer = document.createElement("div");
|
||||
christmasContainer.className = "christmas-container";
|
||||
christmasContainer.setAttribute("aria-hidden", "true");
|
||||
document.body.appendChild(christmasContainer);
|
||||
}
|
||||
|
||||
console.log('Adding random christmas');
|
||||
console.log('Adding christmas');
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
// create a new christmas element
|
||||
@@ -61,8 +65,8 @@ function addRandomChristmas(count) {
|
||||
|
||||
// set random horizontal position, animation delay and size(uncomment lines to enable)
|
||||
const randomLeft = Math.random() * 100; // position (0% to 100%)
|
||||
const randomAnimationDelay = Math.random() * 12 + 8; // delay (8s to 12s)
|
||||
const randomAnimationDelay2 = Math.random() * 5 + 3; // delay (0s to 5s)
|
||||
const randomAnimationDelay = -(Math.random() * 16); // delay (-16s to 0s)
|
||||
const randomAnimationDelay2 = -(Math.random() * 5); // delay (-5s to 0s)
|
||||
|
||||
// apply styles
|
||||
christmasDiv.style.left = `${randomLeft}%`;
|
||||
@@ -78,46 +82,18 @@ function addRandomChristmas(count) {
|
||||
// add the christmas to the container
|
||||
christmasContainer.appendChild(christmasDiv);
|
||||
}
|
||||
console.log('Random christmas added');
|
||||
console.log('Christmas added');
|
||||
}
|
||||
|
||||
// initialize standard christmas
|
||||
function initChristmas() {
|
||||
const christmasContainer = document.querySelector('.christmas-container') || document.createElement("div");
|
||||
|
||||
if (!document.querySelector('.christmas-container')) {
|
||||
christmasContainer.className = "christmas-container";
|
||||
christmasContainer.setAttribute("aria-hidden", "true");
|
||||
document.body.appendChild(christmasContainer);
|
||||
}
|
||||
|
||||
// create the 12 standard christmas
|
||||
for (let i = 0; i < 12; i++) {
|
||||
const christmasDiv = document.createElement('div');
|
||||
christmasDiv.className = 'christmas';
|
||||
christmasDiv.textContent = christmasSymbols[Math.floor(Math.random() * christmasSymbols.length)];
|
||||
|
||||
// set random animation duration
|
||||
if (enableDiffrentDuration) {
|
||||
const randomAnimationDuration = Math.random() * 10 + 6; // delay (6s to 10s)
|
||||
const randomAnimationDuration2 = Math.random() * 5 + 2; // delay (2s to 5s)
|
||||
christmasDiv.style.animationDuration = `${randomAnimationDuration}s, ${randomAnimationDuration2}s`;
|
||||
}
|
||||
|
||||
christmasContainer.appendChild(christmasDiv);
|
||||
}
|
||||
}
|
||||
|
||||
// initialize christmas and add random christmas symbols
|
||||
// initialize christmas
|
||||
function initializeChristmas() {
|
||||
if (!christmas) return; // exit if christmas is disabled
|
||||
initChristmas();
|
||||
toggleChristmas();
|
||||
|
||||
const screenWidth = window.innerWidth; // get the screen width to detect mobile devices
|
||||
if (randomChristmas && (screenWidth > 768 || randomChristmasMobile)) { // add random christmas only on larger screens, unless enabled for mobile devices
|
||||
addRandomChristmas(christmasCount);
|
||||
}
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const count = !isMobile ? christmasCount : christmasCountMobile;
|
||||
|
||||
initChristmas(count);
|
||||
toggleChristmas();
|
||||
}
|
||||
|
||||
initializeChristmas();
|
||||
@@ -1,7 +1,8 @@
|
||||
const config = window.SeasonalsPluginConfig?.EarthDay || {};
|
||||
|
||||
const enabled = config.EnableEarthDay !== undefined ? config.EnableEarthDay : true; // enable/disable earthday
|
||||
const vineCount = config.VineCount !== undefined ? config.VineCount : 4; // count of vine
|
||||
const flowersCount = config.FlowersCount !== undefined ? config.FlowersCount : 60; // count of flowers
|
||||
const flowersCountMobile = config.FlowersCountMobile !== undefined ? config.FlowersCountMobile : 20; // count of flowers on mobile
|
||||
|
||||
const flowerColors = ['#FF69B4', '#FFD700', '#87CEFA', '#FF4500', '#BA55D3', '#FFA500', '#FF1493'];
|
||||
|
||||
@@ -68,7 +69,8 @@ function createElements() {
|
||||
}
|
||||
|
||||
// Generate Flowers
|
||||
const flowerCount = Math.max(10, vineCount * 15);
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const flowerCount = Math.max(5, isMobile ? flowersCountMobile : flowersCount);
|
||||
for (let i = 0; i < flowerCount; i++) {
|
||||
const x = 10 + Math.random() * (w - 20);
|
||||
const y = hSVG * 0.1 + Math.random() * (hSVG * 0.5);
|
||||
|
||||
@@ -49,66 +49,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.halloween:nth-of-type(0) {
|
||||
left: 1%;
|
||||
animation-delay: 0s, 0s;
|
||||
}
|
||||
|
||||
.halloween:nth-of-type(1) {
|
||||
left: 10%;
|
||||
animation-delay: -1s, -1s;
|
||||
}
|
||||
|
||||
.halloween:nth-of-type(2) {
|
||||
left: 20%;
|
||||
animation-delay: -2s, -2s;
|
||||
}
|
||||
|
||||
.halloween:nth-of-type(3) {
|
||||
left: 30%;
|
||||
animation-delay: -3s, -3s;
|
||||
}
|
||||
|
||||
.halloween:nth-of-type(4) {
|
||||
left: 40%;
|
||||
animation-delay: -4s, -4s;
|
||||
}
|
||||
|
||||
.halloween:nth-of-type(5) {
|
||||
left: 50%;
|
||||
animation-delay: -5s, -5s;
|
||||
}
|
||||
|
||||
.halloween:nth-of-type(6) {
|
||||
left: 60%;
|
||||
animation-delay: -6s, -6s;
|
||||
}
|
||||
|
||||
.halloween:nth-of-type(7) {
|
||||
left: 70%;
|
||||
animation-delay: -7s, -7s;
|
||||
}
|
||||
|
||||
.halloween:nth-of-type(8) {
|
||||
left: 80%;
|
||||
animation-delay: -8s, -8s;
|
||||
}
|
||||
|
||||
.halloween:nth-of-type(9) {
|
||||
left: 90%;
|
||||
animation-delay: -9s, -9s;
|
||||
}
|
||||
|
||||
.halloween:nth-of-type(10) {
|
||||
left: 25%;
|
||||
animation-delay: -10s, -10s;
|
||||
}
|
||||
|
||||
.halloween:nth-of-type(11) {
|
||||
left: 65%;
|
||||
animation-delay: -11s, -11s;
|
||||
}
|
||||
|
||||
/* --- Fog Layer --- */
|
||||
.halloween-fog-layer {
|
||||
position: absolute;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
const config = window.SeasonalsPluginConfig?.Halloween || {};
|
||||
|
||||
const halloween = config.EnableHalloween !== undefined ? config.EnableHalloween : true; // enable/disable halloween
|
||||
const randomSymbols = config.EnableRandomSymbols !== undefined ? config.EnableRandomSymbols : true; // enable random symbols
|
||||
const randomSymbolsMobile = config.EnableRandomSymbolsMobile !== undefined ? config.EnableRandomSymbolsMobile : false; // enable random symbols on mobile
|
||||
const enableDiffrentDuration = config.EnableDifferentDuration !== undefined ? config.EnableDifferentDuration : true; // enable different durations
|
||||
const enableSpiders = config.EnableSpiders !== undefined ? config.EnableSpiders : true; // enable/disable spiders
|
||||
const enableMice = config.EnableMice !== undefined ? config.EnableMice : true; // enable/disable mice
|
||||
const halloweenCount = config.SymbolCount !== undefined ? config.SymbolCount : 25; // count of symbols
|
||||
const halloweenCountMobile = config.SymbolCountMobile !== undefined ? config.SymbolCountMobile : 10; // count of symbols on mobile
|
||||
|
||||
const images = [
|
||||
"../Seasonals/Resources/halloween_images/ghost_20x20.png",
|
||||
@@ -50,12 +49,16 @@ observer.observe(document.body, {
|
||||
});
|
||||
|
||||
|
||||
function addRandomSymbols(count) {
|
||||
const halloweenContainer = document.querySelector('.halloween-container');
|
||||
if (!halloweenContainer) return;
|
||||
|
||||
console.log('Adding random halloween symbols');
|
||||
function initHalloween(count) {
|
||||
let halloweenContainer = document.querySelector('.halloween-container');
|
||||
if (!halloweenContainer) {
|
||||
halloweenContainer = document.createElement("div");
|
||||
halloweenContainer.className = "halloween-container";
|
||||
halloweenContainer.setAttribute("aria-hidden", "true");
|
||||
document.body.appendChild(halloweenContainer);
|
||||
}
|
||||
|
||||
console.log('Adding halloween symbols');
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const halloweenDiv = document.createElement("div");
|
||||
@@ -69,6 +72,8 @@ function addRandomSymbols(count) {
|
||||
|
||||
const randomLeft = Math.random() * 100; // position (0% to 100%)
|
||||
const randomAnimationDelay = Math.random() * 10; // delay (0s to 10s)
|
||||
// Display directly symbols on full screen (below) or let it build up (above)
|
||||
// const randomAnimationDelay = -(Math.random() * 10); // delay (-10s to 0s)
|
||||
const randomAnimationDelay2 = -(Math.random() * 3); // delay (-3s to 0s)
|
||||
|
||||
// apply styles
|
||||
@@ -84,37 +89,7 @@ function addRandomSymbols(count) {
|
||||
|
||||
halloweenContainer.appendChild(halloweenDiv);
|
||||
}
|
||||
console.log('Random halloween symbols added');
|
||||
}
|
||||
|
||||
function createHalloween() {
|
||||
const container = document.querySelector('.halloween-container') || document.createElement("div");
|
||||
|
||||
if (!document.querySelector('.halloween-container')) {
|
||||
container.className = "halloween-container";
|
||||
container.setAttribute("aria-hidden", "true");
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
images.forEach(imageSrc => {
|
||||
const halloweenDiv = document.createElement("div");
|
||||
halloweenDiv.className = "halloween";
|
||||
|
||||
const img = document.createElement("img");
|
||||
img.src = imageSrc;
|
||||
|
||||
// set random animation duration
|
||||
if (enableDiffrentDuration) {
|
||||
const randomAnimationDuration = Math.random() * 10 + 6; // delay (6s to 10s)
|
||||
const randomAnimationDuration2 = Math.random() * 5 + 2; // delay (2s to 5s)
|
||||
halloweenDiv.style.animationDuration = `${randomAnimationDuration}s, ${randomAnimationDuration2}s`;
|
||||
}
|
||||
|
||||
halloweenDiv.appendChild(img);
|
||||
container.appendChild(halloweenDiv);
|
||||
});
|
||||
}
|
||||
console.log('Halloween symbols added');
|
||||
}
|
||||
|
||||
// create fog layer
|
||||
@@ -230,7 +205,11 @@ function createMouse(container) {
|
||||
|
||||
function initializeHalloween() {
|
||||
if (!halloween) return;
|
||||
createHalloween();
|
||||
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const count = !isMobile ? halloweenCount : halloweenCountMobile;
|
||||
|
||||
initHalloween(count);
|
||||
toggleHalloween();
|
||||
|
||||
const container = document.querySelector('.halloween-container');
|
||||
@@ -252,11 +231,6 @@ function initializeHalloween() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const screenWidth = window.innerWidth; // get the screen width to detect mobile devices
|
||||
if (randomSymbols && (screenWidth > 768 || randomSymbolsMobile)) {
|
||||
addRandomSymbols(halloweenCount);
|
||||
}
|
||||
}
|
||||
|
||||
initializeHalloween();
|
||||
@@ -49,63 +49,3 @@
|
||||
transform: translateX(80px)
|
||||
}
|
||||
}
|
||||
|
||||
.heart:nth-of-type(0) {
|
||||
left: 1%;
|
||||
animation-delay: 0s, 0s
|
||||
}
|
||||
|
||||
.heart:nth-of-type(1) {
|
||||
left: 10%;
|
||||
animation-delay: 1s, 1s
|
||||
}
|
||||
|
||||
.heart:nth-of-type(2) {
|
||||
left: 20%;
|
||||
animation-delay: 6s, .5s
|
||||
}
|
||||
|
||||
.heart:nth-of-type(3) {
|
||||
left: 30%;
|
||||
animation-delay: 4s, 2s
|
||||
}
|
||||
|
||||
.heart:nth-of-type(4) {
|
||||
left: 40%;
|
||||
animation-delay: 2s, 2s
|
||||
}
|
||||
|
||||
.heart:nth-of-type(5) {
|
||||
left: 50%;
|
||||
animation-delay: 8s, 3s
|
||||
}
|
||||
|
||||
.heart:nth-of-type(6) {
|
||||
left: 60%;
|
||||
animation-delay: 6s, 2s
|
||||
}
|
||||
|
||||
.heart:nth-of-type(7) {
|
||||
left: 70%;
|
||||
animation-delay: 2.5s, 1s
|
||||
}
|
||||
|
||||
.heart:nth-of-type(8) {
|
||||
left: 80%;
|
||||
animation-delay: 1s, 0s
|
||||
}
|
||||
|
||||
.heart:nth-of-type(9) {
|
||||
left: 90%;
|
||||
animation-delay: 3s, 1.5s
|
||||
}
|
||||
|
||||
.heart:nth-of-type(10) {
|
||||
left: 25%;
|
||||
animation-delay: 2s, 0s
|
||||
}
|
||||
|
||||
.heart:nth-of-type(11) {
|
||||
left: 65%;
|
||||
animation-delay: 4s, 2.5s
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
const config = window.SeasonalsPluginConfig?.Hearts || {};
|
||||
|
||||
const hearts = config.EnableHearts !== undefined ? config.EnableHearts : true; // enable/disable hearts
|
||||
const randomSymbols = config.EnableRandomSymbols !== undefined ? config.EnableRandomSymbols : true; // enable random symbols
|
||||
const randomSymbolsMobile = config.EnableRandomSymbolsMobile !== undefined ? config.EnableRandomSymbolsMobile : false; // enable random symbols on mobile
|
||||
const enableDiffrentDuration = config.EnableDifferentDuration !== undefined ? config.EnableDifferentDuration : true; // enable different durations
|
||||
const heartsCount = config.SymbolCount !== undefined ? config.SymbolCount : 25; // count of symbol
|
||||
const heartsCountMobile = config.SymbolCountMobile !== undefined ? config.SymbolCountMobile : 10; // count of symbol on mobile
|
||||
|
||||
// Array of hearts characters
|
||||
const heartSymbols = ['❤️', '💕', '💞', '💓', '💗', '💖'];
|
||||
@@ -46,11 +45,16 @@ observer.observe(document.body, {
|
||||
});
|
||||
|
||||
|
||||
function addRandomSymbols(count) {
|
||||
const heartsContainer = document.querySelector('.hearts-container'); // get the hearts container
|
||||
if (!heartsContainer) return; // exit if hearts container is not found
|
||||
function initHearts(count) {
|
||||
let heartsContainer = document.querySelector('.hearts-container'); // get the hearts container
|
||||
if (!heartsContainer) {
|
||||
heartsContainer = document.createElement("div");
|
||||
heartsContainer.className = "hearts-container";
|
||||
heartsContainer.setAttribute("aria-hidden", "true");
|
||||
document.body.appendChild(heartsContainer);
|
||||
}
|
||||
|
||||
console.log('Adding random heart symbols');
|
||||
console.log('Adding heart symbols');
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
// create a new hearts elements
|
||||
@@ -63,8 +67,8 @@ function addRandomSymbols(count) {
|
||||
|
||||
// set random horizontal position, animation delay and size(uncomment lines to enable)
|
||||
const randomLeft = Math.random() * 100; // position (0% to 100%)
|
||||
const randomAnimationDelay = Math.random() * 14; // delay (0s to 14s)
|
||||
const randomAnimationDelay2 = Math.random() * 5; // delay (0s to 5s)
|
||||
const randomAnimationDelay = -(Math.random() * 16); // delay (-16s to 0s)
|
||||
const randomAnimationDelay2 = -(Math.random() * 5); // delay (-5s to 0s)
|
||||
|
||||
// apply styles
|
||||
heartsDiv.style.left = `${randomLeft}%`;
|
||||
@@ -80,46 +84,18 @@ function addRandomSymbols(count) {
|
||||
// add the hearts to the container
|
||||
heartsContainer.appendChild(heartsDiv);
|
||||
}
|
||||
console.log('Random hearts symbols added');
|
||||
console.log('Heart symbols added');
|
||||
}
|
||||
|
||||
// create hearts objects
|
||||
function createHearts() {
|
||||
const container = document.querySelector('.hearts-container') || document.createElement("div");
|
||||
|
||||
if (!document.querySelector('.hearts-container')) {
|
||||
container.className = "hearts-container";
|
||||
container.setAttribute("aria-hidden", "true");
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 12; i++) {
|
||||
const heartsDiv = document.createElement("div");
|
||||
heartsDiv.className = "heart";
|
||||
heartsDiv.textContent = heartSymbols[i % heartSymbols.length];
|
||||
|
||||
// set random animation duration
|
||||
if (enableDiffrentDuration) {
|
||||
const randomAnimationDuration = Math.random() * 16 + 12; // delay (12s to 16s)
|
||||
const randomAnimationDuration2 = Math.random() * 7 + 3; // delay (3s to 7s)
|
||||
heartsDiv.style.animationDuration = `${randomAnimationDuration}s, ${randomAnimationDuration2}s`;
|
||||
}
|
||||
|
||||
container.appendChild(heartsDiv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// initialize hearts
|
||||
function initializeHearts() {
|
||||
if (!hearts) return; // exit if hearts is disabled
|
||||
createHearts();
|
||||
toggleHearts();
|
||||
|
||||
const screenWidth = window.innerWidth; // get the screen width to detect mobile devices
|
||||
if (randomSymbols && (screenWidth > 768 || randomSymbolsMobile)) { // add random heartss only on larger screens, unless enabled for mobile devices
|
||||
addRandomSymbols(heartsCount);
|
||||
}
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const count = !isMobile ? heartsCount : heartsCountMobile;
|
||||
|
||||
initHearts(count);
|
||||
toggleHearts();
|
||||
}
|
||||
|
||||
initializeHearts();
|
||||
@@ -67,8 +67,8 @@ function initializeOktoberfest() {
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
|
||||
const screenWidth = window.innerWidth;
|
||||
const count = screenWidth > 768 ? symbolCount : symbolCountMobile;
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const count = !isMobile ? symbolCount : symbolCountMobile;
|
||||
|
||||
createOktoberfest(container, count);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,34 @@
|
||||
const config = window.SeasonalsPluginConfig?.Olympia || {};
|
||||
|
||||
const olympia = config.EnableOlympia !== undefined ? config.EnableOlympia : true;
|
||||
const symbolCount = config.SymbolCount || 25;
|
||||
const useRandomSymbols = config.EnableRandomSymbols !== undefined ? config.EnableRandomSymbols : true;
|
||||
const enableRandomMobile = config.EnableRandomSymbolsMobile !== undefined ? config.EnableRandomSymbolsMobile : false;
|
||||
const enableDifferentDuration = config.EnableDifferentDuration !== undefined ? config.EnableDifferentDuration : true;
|
||||
const olympia = config.EnableOlympia !== undefined ? config.EnableOlympia : true; // enable/disable olympia theme
|
||||
const symbolCount = config.SymbolCount !== undefined ? config.SymbolCount : 25; // count of floating symbols
|
||||
const symbolCountMobile = config.SymbolCountMobile !== undefined ? config.SymbolCountMobile : 10; // count of floating symbols on mobile
|
||||
const enableDifferentDuration = config.EnableDifferentDuration !== undefined ? config.EnableDifferentDuration : true; // enable different durations
|
||||
|
||||
// Olympic Ring Colors (Carnival Config)
|
||||
const confettiColors = ['#0081C8', '#FCB131', '#000000', '#00A651', '#EE334E'];
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const confettiCount = isMobile ? 30 : 60;
|
||||
|
||||
/**
|
||||
* Credits:
|
||||
* https://lottiefiles.com/free-animation/gold-coin-5Spp5kJbLP
|
||||
* https://lottiefiles.com/free-animation/silver-coin-SIgIP59fII
|
||||
* https://lottiefiles.com/free-animation/bronze-coin-wWVCJMsOUq
|
||||
*/
|
||||
const olympicMedals = [
|
||||
"../Seasonals/Resources/olympic_assets/gold_coin.gif",
|
||||
"../Seasonals/Resources/olympic_assets/silver_coin.gif",
|
||||
"../Seasonals/Resources/olympic_assets/bronze_coin.gif"
|
||||
]
|
||||
|
||||
/**
|
||||
* Credits:
|
||||
* https://www.flaticon.com/de/kostenloses-icon/fackel_4683293
|
||||
* merged with:
|
||||
* https://lottiefiles.com/free-animation/abstract-flames-lottie-json-animation-oSb0IFoBrj
|
||||
*/
|
||||
const olympicTorch = "../Seasonals/Resources/olympic_assets/torch.gif";
|
||||
|
||||
let msgPrinted = false;
|
||||
|
||||
@@ -49,27 +73,23 @@ function createOlympia() {
|
||||
}
|
||||
|
||||
const standardCount = 15;
|
||||
const totalSymbols = symbolCount + standardCount;
|
||||
|
||||
let isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
let finalCount = totalSymbols;
|
||||
|
||||
if (isMobile) {
|
||||
finalCount = enableRandomMobile ? totalSymbols : standardCount;
|
||||
}
|
||||
let finalCount = isMobile ? symbolCountMobile : symbolCount;
|
||||
|
||||
const useRandomDuration = enableDifferentDuration !== false;
|
||||
|
||||
const activeItems = ['gold', 'silver', 'bronze', 'torch', 'rings_blue', 'rings_yellow', 'rings_black', 'rings_green', 'rings_red'];
|
||||
const olympicRings = ['ring_blue.css', 'ring_yellow.css', 'ring_black.css', 'ring_green.css', 'ring_red.css'];
|
||||
const activeItems = [...olympicMedals, ...olympicRings];
|
||||
|
||||
for (let i = 0; i < finalCount; i++) {
|
||||
let symbol = document.createElement('div');
|
||||
|
||||
const randomItem = activeItems[Math.floor(Math.random() * activeItems.length)];
|
||||
const isRing = randomItem.startsWith('rings');
|
||||
const isMedal = ['gold', 'silver', 'bronze'].includes(randomItem);
|
||||
const randomImgUrl = activeItems[Math.floor(Math.random() * activeItems.length)];
|
||||
const isRing = randomImgUrl.includes('ring_');
|
||||
const isMedal = randomImgUrl.includes('_coin');
|
||||
|
||||
symbol.className = `olympia-symbol olympia-${randomItem}`;
|
||||
symbol.className = `olympia-symbol`;
|
||||
|
||||
// Create inner div for sway/rotation
|
||||
let innerDiv = document.createElement('div');
|
||||
@@ -77,19 +97,20 @@ function createOlympia() {
|
||||
let img = null;
|
||||
|
||||
if (isRing) {
|
||||
const colorName = randomImgUrl.split('ring_')[1].split('.')[0];
|
||||
const ringColorMap = {
|
||||
'rings_blue': '#0081C8',
|
||||
'rings_yellow': '#FCB131',
|
||||
'rings_black': '#000000',
|
||||
'rings_green': '#00A651',
|
||||
'rings_red': '#EE334E'
|
||||
'blue': '#0081C8',
|
||||
'yellow': '#FCB131',
|
||||
'black': '#000000',
|
||||
'green': '#00A651',
|
||||
'red': '#EE334E'
|
||||
};
|
||||
let ringDiv = document.createElement('div');
|
||||
ringDiv.className = 'olympia-ring-css';
|
||||
ringDiv.style.setProperty('--ring-color', ringColorMap[randomItem]);
|
||||
ringDiv.style.setProperty('--ring-color', ringColorMap[colorName]);
|
||||
innerDiv.appendChild(ringDiv);
|
||||
|
||||
// Add a 3D flip animation for rings and medals
|
||||
// Add a 3D flip animation for rings
|
||||
const spinReverse = Math.random() > 0.5 ? 'reverse' : 'normal';
|
||||
innerDiv.style.animation = `olympia-tumble-3d ${Math.random() * 4 + 4}s linear infinite ${spinReverse}`;
|
||||
|
||||
@@ -99,13 +120,7 @@ function createOlympia() {
|
||||
innerDiv.style.setProperty('--rot-z', (Math.random() * 2 - 1).toFixed(2));
|
||||
} else {
|
||||
img = document.createElement('img');
|
||||
let imgName = randomItem;
|
||||
if (isMedal) {
|
||||
imgName = `${randomItem}_coin.gif`;
|
||||
} else {
|
||||
imgName = `${randomItem}.png`;
|
||||
}
|
||||
img.src = `../Seasonals/Resources/olympic_assets/${imgName}`;
|
||||
img.src = randomImgUrl;
|
||||
img.onerror = function() {
|
||||
symbol.remove();
|
||||
};
|
||||
@@ -181,10 +196,6 @@ function createOlympia() {
|
||||
|
||||
createTorch(true);
|
||||
createTorch(false);
|
||||
|
||||
// Olympic Ring Colors (Carnival Config)
|
||||
const confettiColors = ['#0081C8', '#FCB131', '#000000', '#00A651', '#EE334E'];
|
||||
const confettiCount = isMobile ? 30 : 60;
|
||||
|
||||
for (let i = 0; i < confettiCount; i++) {
|
||||
let wrapper = document.createElement('div');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const config = window.SeasonalsPluginConfig?.Rain || {};
|
||||
|
||||
const enabled = config.EnableRain !== undefined ? config.EnableRain : true; // enable/disable rain
|
||||
const isMobile = window.innerWidth <= 768;
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const elementCount = isMobile ? (config.RaindropCountMobile || 150) : (config.RaindropCount || 300); // count of raindrops
|
||||
const rainSpeed = config.RainSpeed !== undefined ? config.RainSpeed : 1.0; // speed of rain
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
const config = window.SeasonalsPluginConfig?.Resurrection || {};
|
||||
|
||||
const enableResurrection = config.EnableResurrection !== undefined ? config.EnableResurrection : true; // enable/disable resurrection
|
||||
const enableRandomSymbols = config.EnableRandomSymbols !== undefined ? config.EnableRandomSymbols : true; // enable random symbols
|
||||
const enableRandomSymbolsMobile = config.EnableRandomSymbolsMobile !== undefined ? config.EnableRandomSymbolsMobile : false; // enable random symbols on mobile
|
||||
const enableDifferentDuration = config.EnableDifferentDuration !== undefined ? config.EnableDifferentDuration : true; // enable different durations
|
||||
const symbolCount = config.SymbolCount !== undefined ? config.SymbolCount : 12; // count of symbols
|
||||
const symbolCountMobile = config.SymbolCountMobile !== undefined ? config.SymbolCountMobile : 5; // count of symbols on mobile
|
||||
|
||||
let animationEnabled = true;
|
||||
let statusLogged = false;
|
||||
@@ -78,20 +77,17 @@ function createSymbol(imageSrc, leftPercent, delaySeconds) {
|
||||
|
||||
function addSymbols(count) {
|
||||
const container = document.querySelector('.resurrection-container');
|
||||
if (!container || !enableRandomSymbols) return;
|
||||
|
||||
const isDesktop = window.innerWidth > 768;
|
||||
if (!isDesktop && !enableRandomSymbolsMobile) return;
|
||||
if (!container) return;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const imageSrc = images[Math.floor(Math.random() * images.length)];
|
||||
const left = Math.random() * 100;
|
||||
const delay = Math.random() * 12;
|
||||
const delay = -(Math.random() * 12);
|
||||
container.appendChild(createSymbol(imageSrc, left, delay));
|
||||
}
|
||||
}
|
||||
|
||||
function initResurrection() {
|
||||
function initResurrection(count) {
|
||||
let container = document.querySelector('.resurrection-container');
|
||||
if (!container) {
|
||||
container = document.createElement('div');
|
||||
@@ -103,17 +99,21 @@ function initResurrection() {
|
||||
// Place one of each of the 8 provided resurrection images first.
|
||||
images.forEach((imageSrc, index) => {
|
||||
const left = (index + 1) * (100 / (images.length + 1));
|
||||
const delay = Math.random() * 8;
|
||||
const delay = -(Math.random() * 8);
|
||||
container.appendChild(createSymbol(imageSrc, left, delay));
|
||||
});
|
||||
|
||||
const extraCount = Math.max(symbolCount - images.length, 0);
|
||||
const extraCount = Math.max(count - images.length, 0);
|
||||
addSymbols(extraCount);
|
||||
}
|
||||
|
||||
function initializeResurrection() {
|
||||
if (!enableResurrection) return;
|
||||
initResurrection();
|
||||
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const count = !isMobile ? symbolCount : symbolCountMobile;
|
||||
|
||||
initResurrection(count);
|
||||
toggleResurrection();
|
||||
}
|
||||
|
||||
|
||||
@@ -310,8 +310,8 @@ function initializeSanta() {
|
||||
}
|
||||
const container = document.querySelector('.santa-container');
|
||||
if (container) {
|
||||
const screenWidth = window.innerWidth; // get the screen width to detect mobile devices
|
||||
if (screenWidth < 768) { // lower count of snowflakes on mobile devices
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches; // check if mobile device
|
||||
if (isMobile) { // lower count of snowflakes on mobile devices
|
||||
isMobile = true;
|
||||
console.log('Mobile device detected. Reducing snowflakes count.');
|
||||
snowflakesCount = snowflakesCountMobile;
|
||||
|
||||
@@ -181,8 +181,8 @@ function initializeSnowfall() {
|
||||
}
|
||||
const container = document.querySelector('.snowfall-container');
|
||||
if (container) {
|
||||
const screenWidth = window.innerWidth; // get the screen width to detect mobile devices
|
||||
if (screenWidth < 768) { // lower count of snowflakes on mobile devices
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches; // check if mobile device
|
||||
if (isMobile) { // lower count of snowflakes on mobile devices
|
||||
console.log('Mobile device detected. Reducing snowflakes count.');
|
||||
snowflakesCount = snowflakesCountMobile;
|
||||
}
|
||||
|
||||
@@ -1,112 +1,54 @@
|
||||
.snowflakes {
|
||||
display: block;
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
contain: layout paint;
|
||||
}
|
||||
|
||||
.snowflake {
|
||||
position: fixed;
|
||||
z-index: 15;
|
||||
top: 0;
|
||||
will-change: transform;
|
||||
translate: 0 -10vh;
|
||||
font-size: 1em;
|
||||
color: #fff;
|
||||
font-family: Arial, sans-serif;
|
||||
text-shadow: 0 0 5px #000;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
animation-name: snowflakes-fall, snowflakes-shake;
|
||||
animation-duration: 12s, 3s;
|
||||
animation-timing-function: linear, ease-in-out;
|
||||
animation-iteration-count: infinite, infinite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@keyframes snowflakes-fall {
|
||||
0% {
|
||||
translate: 0 -10vh;
|
||||
}
|
||||
|
||||
100% {
|
||||
translate: 0 110vh;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes snowflakes-shake {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateX(80px);
|
||||
}
|
||||
}
|
||||
|
||||
.snowflake:nth-of-type(0) {
|
||||
left: 0%;
|
||||
animation-delay: 0s, 0s;
|
||||
}
|
||||
|
||||
.snowflake:nth-of-type(1) {
|
||||
left: 10%;
|
||||
animation-delay: 1s, 1s;
|
||||
}
|
||||
|
||||
.snowflake:nth-of-type(2) {
|
||||
left: 20%;
|
||||
animation-delay: 6s, 0.5s;
|
||||
}
|
||||
|
||||
.snowflake:nth-of-type(3) {
|
||||
left: 30%;
|
||||
animation-delay: 4s, 2s;
|
||||
}
|
||||
|
||||
.snowflake:nth-of-type(4) {
|
||||
left: 40%;
|
||||
animation-delay: 2s, 2s;
|
||||
}
|
||||
|
||||
.snowflake:nth-of-type(5) {
|
||||
left: 50%;
|
||||
animation-delay: 8s, 3s;
|
||||
}
|
||||
|
||||
.snowflake:nth-of-type(6) {
|
||||
left: 60%;
|
||||
animation-delay: 6s, 2s;
|
||||
}
|
||||
|
||||
.snowflake:nth-of-type(7) {
|
||||
left: 70%;
|
||||
animation-delay: 2.5s, 1s;
|
||||
}
|
||||
|
||||
.snowflake:nth-of-type(8) {
|
||||
left: 80%;
|
||||
animation-delay: 1s, 0s;
|
||||
}
|
||||
|
||||
.snowflake:nth-of-type(9) {
|
||||
left: 90%;
|
||||
animation-delay: 3s, 1.5s;
|
||||
}
|
||||
|
||||
.snowflake:nth-of-type(10) {
|
||||
left: 25%;
|
||||
animation-delay: 2s, 0s;
|
||||
}
|
||||
|
||||
.snowflake:nth-of-type(11) {
|
||||
.snowflakes {
|
||||
display: block;
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
contain: layout paint;
|
||||
}
|
||||
|
||||
.snowflake {
|
||||
position: fixed;
|
||||
z-index: 15;
|
||||
top: 0;
|
||||
will-change: transform;
|
||||
translate: 0 -10vh;
|
||||
font-size: 1em;
|
||||
color: #fff;
|
||||
font-family: Arial, sans-serif;
|
||||
text-shadow: 0 0 5px #000;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
animation-name: snowflakes-fall, snowflakes-shake;
|
||||
animation-duration: 12s, 3s;
|
||||
animation-timing-function: linear, ease-in-out;
|
||||
animation-iteration-count: infinite, infinite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@keyframes snowflakes-fall {
|
||||
0% {
|
||||
translate: 0 -10vh;
|
||||
}
|
||||
|
||||
100% {
|
||||
translate: 0 110vh;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes snowflakes-shake {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateX(80px);
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,7 @@ const config = window.SeasonalsPluginConfig?.Snowflakes || {};
|
||||
|
||||
const snowflakes = config.EnableSnowflakes !== undefined ? config.EnableSnowflakes : true; // enable/disable snowflakes
|
||||
const snowflakeCount = config.SnowflakeCount !== undefined ? config.SnowflakeCount : 25; // count of snowflakes
|
||||
const randomSnowflakes = config.EnableRandomSnowflakes !== undefined ? config.EnableRandomSnowflakes : true; // enable random snowflakes
|
||||
const randomSnowflakesMobile = config.EnableRandomSnowflakesMobile !== undefined ? config.EnableRandomSnowflakesMobile : false; // enable random snowflakes on mobile
|
||||
const snowflakeCountMobile = config.SnowflakeCountMobile !== undefined ? config.SnowflakeCountMobile : 10; // count of snowflakes on mobile
|
||||
const enableColoredSnowflakes = config.EnableColoredSnowflakes !== undefined ? config.EnableColoredSnowflakes : true; // enable/disable colored snowflakes
|
||||
const enableDiffrentDuration = config.EnableDifferentDuration !== undefined ? config.EnableDifferentDuration : true; // enable different durations
|
||||
|
||||
@@ -46,11 +45,16 @@ observer.observe(document.body, {
|
||||
attributes: true
|
||||
});
|
||||
|
||||
function addRandomSnowflakes(count) {
|
||||
const snowflakeContainer = document.querySelector('.snowflakes'); // get the snowflake container
|
||||
if (!snowflakeContainer) return; // exit if snowflake container is not found
|
||||
function initSnowflakes(count) {
|
||||
let snowflakeContainer = document.querySelector('.snowflakes'); // get the snowflake container
|
||||
if (!snowflakeContainer) {
|
||||
snowflakeContainer = document.createElement("div");
|
||||
snowflakeContainer.className = "snowflakes";
|
||||
snowflakeContainer.setAttribute("aria-hidden", "true");
|
||||
document.body.appendChild(snowflakeContainer);
|
||||
}
|
||||
|
||||
console.log('Adding random snowflakes');
|
||||
console.log('Adding snowflakes');
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
// create a new snowflake element
|
||||
@@ -66,7 +70,7 @@ function addRandomSnowflakes(count) {
|
||||
|
||||
// set random horizontal position, animation delay and size(uncomment lines to enable)
|
||||
const randomLeft = Math.random() * 100; // position (0% to 100%)
|
||||
const randomAnimationDelay = Math.random() * 8; // delay (0s to 8s)
|
||||
const randomAnimationDelay = -(Math.random() * 14); // delay (-14s to 0s)
|
||||
const randomAnimationDelay2 = -(Math.random() * 5); // delay (-5s to 0s)
|
||||
|
||||
// apply styles
|
||||
@@ -83,49 +87,18 @@ function addRandomSnowflakes(count) {
|
||||
// add the snowflake to the container
|
||||
snowflakeContainer.appendChild(snowflake);
|
||||
}
|
||||
console.log('Random snowflakes added');
|
||||
console.log('Snowflakes added');
|
||||
}
|
||||
|
||||
// initialize standard snowflakes
|
||||
function initSnowflakes() {
|
||||
const snowflakesContainer = document.querySelector('.snowflakes') || document.createElement("div");
|
||||
|
||||
if (!document.querySelector('.snowflakes')) {
|
||||
snowflakesContainer.className = "snowflakes";
|
||||
snowflakesContainer.setAttribute("aria-hidden", "true");
|
||||
document.body.appendChild(snowflakesContainer);
|
||||
}
|
||||
|
||||
// Array of snowflake characters
|
||||
const snowflakeSymbols = ['❅', '❆'];
|
||||
|
||||
// create the 12 standard snowflakes
|
||||
for (let i = 0; i < 12; i++) {
|
||||
const snowflake = document.createElement('div');
|
||||
snowflake.className = 'snowflake';
|
||||
snowflake.textContent = snowflakeSymbols[i % 2]; // change between ❅ and ❆
|
||||
|
||||
// set random animation duration
|
||||
if (enableDiffrentDuration) {
|
||||
const randomAnimationDuration = Math.random() * 14 + 10; // delay (10s to 14s)
|
||||
const randomAnimationDuration2 = Math.random() * 5 + 3; // delay (3s to 5s)
|
||||
snowflake.style.animationDuration = `${randomAnimationDuration}s, ${randomAnimationDuration2}s`;
|
||||
}
|
||||
|
||||
snowflakesContainer.appendChild(snowflake);
|
||||
}
|
||||
}
|
||||
|
||||
// initialize snowflakes and add random snowflakes
|
||||
// initialize snowflakes
|
||||
function initializeSnowflakes() {
|
||||
if (!snowflakes) return; // exit if snowflakes are disabled
|
||||
initSnowflakes();
|
||||
toggleSnowflakes();
|
||||
|
||||
const screenWidth = window.innerWidth; // get the screen width to detect mobile devices
|
||||
if (randomSnowflakes && (screenWidth > 768 || randomSnowflakesMobile)) { // add random snowflakes only on larger screens, unless enabled for mobile devices
|
||||
addRandomSnowflakes(snowflakeCount);
|
||||
}
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const count = !isMobile ? snowflakeCount : snowflakeCountMobile;
|
||||
|
||||
initSnowflakes(count);
|
||||
toggleSnowflakes();
|
||||
}
|
||||
|
||||
initializeSnowflakes();
|
||||
@@ -184,8 +184,8 @@ function initializeSnowstorm() {
|
||||
}
|
||||
const container = document.querySelector('.snowstorm-container');
|
||||
if (container) {
|
||||
const screenWidth = window.innerWidth; // get the screen width to detect mobile devices
|
||||
if (screenWidth < 768) { // lower count of snowflakes on mobile devices
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
if (isMobile) { // lower count of snowflakes on mobile devices
|
||||
console.log('Mobile device detected. Reducing snowflakes count.');
|
||||
snowflakesCount = snowflakesCountMobile;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const config = window.SeasonalsPluginConfig?.Storm || {};
|
||||
|
||||
const enabled = config.EnableStorm !== undefined ? config.EnableStorm : true; // enable/disable storm
|
||||
const isMobile = window.innerWidth <= 768;
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 768px)").matches;
|
||||
const elementCount = isMobile ? (config.RaindropCountMobile || 150) : (config.RaindropCount || 300); // count of raindrops
|
||||
const enableLightning = config.EnableLightning !== undefined ? config.EnableLightning : true; // enable/disable lightning
|
||||
const rainSpeed = config.RainSpeed !== undefined ? config.RainSpeed : 1.0; // speed of rain
|
||||
|
||||
@@ -235,41 +235,41 @@
|
||||
<label for="theme-select">Theme:</label>
|
||||
<select id="theme-select">
|
||||
<option value="" selected disabled>— Select a theme —</option>
|
||||
<option value="autumn">Autumn</option>
|
||||
<option value="birthday">Birthday</option>
|
||||
<option value="carnival">Carnival (Confetti)</option>
|
||||
<option value="cherryblossom">Cherryblossom</option>
|
||||
<option value="christmas">Christmas</option>
|
||||
<option value="earthday">Earth Day</option>
|
||||
<option value="easter">Easter</option>
|
||||
<option value="eid">Eid al-Fitr</option>
|
||||
<option value="eurovision">Eurovision</option>
|
||||
<option value="filmnoir">Film-Noir</option>
|
||||
<option value="fireworks">Fireworks</option>
|
||||
<option value="frost">Frost / Ice</option>
|
||||
<option value="friday13">Friday the 13th</option>
|
||||
<option value="halloween">Halloween</option>
|
||||
<option value="hearts">Hearts</option>
|
||||
<option value="marioday">Mario Day</option>
|
||||
<option value="matrix">Matrix</option>
|
||||
<option value="oktoberfest">Oktoberfest</option>
|
||||
<option value="olympia">Olympia</option>
|
||||
<option value="oscar">Oscar Awards</option>
|
||||
<option value="pride">Pride</option>
|
||||
<option value="rain">Rain</option>
|
||||
<option value="resurrection">Resurrection</option>
|
||||
<option value="santa">Santa</option>
|
||||
<option value="snowfall">Snowfall</option>
|
||||
<option value="snowflakes">Snowflakes</option>
|
||||
<option value="snowstorm">Snowstorm</option>
|
||||
<option value="fireworks">Fireworks</option>
|
||||
<option value="halloween">Halloween</option>
|
||||
<option value="spooky">Spooky</option>
|
||||
<option value="hearts">Hearts</option>
|
||||
<option value="christmas">Christmas</option>
|
||||
<option value="santa">Santa</option>
|
||||
<option value="autumn">Autumn</option>
|
||||
<option value="easter">Easter</option>
|
||||
<option value="resurrection">Resurrection</option>
|
||||
<option value="spring">Spring</option>
|
||||
<option value="summer">Summer (Bubbles)</option>
|
||||
<option value="carnival">Carnival (Confetti)</option>
|
||||
<option value="cherryblossom">Cherryblossom</option>
|
||||
<option value="earthday">Earth Day</option>
|
||||
<option value="eurovision">Eurovision</option>
|
||||
<option value="matrix">Matrix</option>
|
||||
<option value="pride">Pride</option>
|
||||
<option value="rain">Rain</option>
|
||||
<option value="storm">Storm (⚠️Epilepsy Warning⚠️)</option>
|
||||
<option value="frost">Frost / Ice</option>
|
||||
<option value="filmnoir">Film-Noir</option>
|
||||
<option value="oscar">Oscar Awards</option>
|
||||
<option value="marioday">Mario Day</option>
|
||||
<option value="starwars">Star Wars Day</option>
|
||||
<option value="oktoberfest">Oktoberfest</option>
|
||||
<option value="friday13">Friday the 13th</option>
|
||||
<option value="eid">Eid al-Fitr</option>
|
||||
<option value="sports">Sports</option>
|
||||
<option value="olympia">Olympia</option>
|
||||
<option value="space">Space / Sci-Fi</option>
|
||||
<option value="spooky">Spooky</option>
|
||||
<option value="sports">Sports</option>
|
||||
<option value="spring">Spring</option>
|
||||
<option value="starwars">Star Wars Day</option>
|
||||
<option value="storm">Storm (⚠️Epilepsy Warning⚠️)</option>
|
||||
<option value="summer">Summer (Bubbles)</option>
|
||||
<option value="underwater">Underwater</option>
|
||||
<option value="birthday">Birthday</option>
|
||||
<option value="custom">⚙ Custom (Local Files)</option>
|
||||
</select>
|
||||
|
||||
@@ -341,41 +341,41 @@
|
||||
|
||||
// ── Built-in theme map (local file paths for testing) ──
|
||||
const themes = {
|
||||
snowfall: { css: 'snowfall.css', js: 'snowfall.js', container: 'snowfall-container' },
|
||||
snowflakes: { css: 'snowflakes.css', js: 'snowflakes.js', container: 'snowflakes' },
|
||||
snowstorm: { css: 'snowstorm.css', js: 'snowstorm.js', container: 'snowstorm-container' },
|
||||
fireworks: { css: 'fireworks.css', js: 'fireworks.js', container: 'fireworks' },
|
||||
halloween: { css: 'halloween.css', js: 'halloween.js', container: 'halloween-container' },
|
||||
spooky: { css: 'spooky.css', js: 'spooky.js', container: 'spooky-container' },
|
||||
hearts: { css: 'hearts.css', js: 'hearts.js', container: 'hearts-container' },
|
||||
christmas: { css: 'christmas.css', js: 'christmas.js', container: 'christmas-container' },
|
||||
santa: { css: 'santa.css', js: 'santa.js', container: 'santa-container' },
|
||||
autumn: { css: 'autumn.css', js: 'autumn.js', container: 'autumn-container' },
|
||||
easter: { css: 'easter.css', js: 'easter.js', container: 'easter-container' },
|
||||
resurrection: { css: 'resurrection.css', js: 'resurrection.js', container: 'resurrection-container' },
|
||||
spring: { css: 'spring.css', js: 'spring.js', container: 'spring-container' },
|
||||
summer: { css: 'summer.css', js: 'summer.js', container: 'summer-container' },
|
||||
birthday: { css: 'birthday.css', js: 'birthday.js', container: 'birthday-container' },
|
||||
carnival: { css: 'carnival.css', js: 'carnival.js', container: 'carnival-container' },
|
||||
cherryblossom: { css: 'cherryblossom.css', js: 'cherryblossom.js', container: 'cherryblossom-container' },
|
||||
cherryblossom:{ css: 'cherryblossom.css', js: 'cherryblossom.js',container: 'cherryblossom-container' },
|
||||
christmas: { css: 'christmas.css', js: 'christmas.js', container: 'christmas-container' },
|
||||
earthday: { css: 'earthday.css', js: 'earthday.js', container: 'earthday-container' },
|
||||
easter: { css: 'easter.css', js: 'easter.js', container: 'easter-container' },
|
||||
eid: { css: 'eid.css', js: 'eid.js', container: 'eid-container' },
|
||||
eurovision: { css: 'eurovision.css', js: 'eurovision.js', container: 'eurovision-container' },
|
||||
matrix: { css: 'matrix.css', js: 'matrix.js', container: 'matrix-container' },
|
||||
filmnoir: { css: 'filmnoir.css', js: 'filmnoir.js', container: 'filmnoir-container' },
|
||||
fireworks: { css: 'fireworks.css', js: 'fireworks.js', container: 'fireworks' },
|
||||
frost: { css: 'frost.css', js: 'frost.js', container: 'frost-container' },
|
||||
friday13: { css: 'friday13.css', js: 'friday13.js', container: 'friday13-container' },
|
||||
halloween: { css: 'halloween.css', js: 'halloween.js', container: 'halloween-container' },
|
||||
hearts: { css: 'hearts.css', js: 'hearts.js', container: 'hearts-container' },
|
||||
marioday: { css: 'marioday.css', js: 'marioday.js', container: 'marioday-container' },
|
||||
matrix: { css: 'matrix.css', js: 'matrix.js', container: 'matrix-container' },
|
||||
oktoberfest: { css: 'oktoberfest.css', js: 'oktoberfest.js', container: 'oktoberfest-container' },
|
||||
olympia: { css: 'olympia.css', js: 'olympia.js', container: 'olympia-container' },
|
||||
oscar: { css: 'oscar.css', js: 'oscar.js', container: 'oscar-container' },
|
||||
pride: { css: 'pride.css', js: 'pride.js', container: 'pride-container' },
|
||||
rain: { css: 'rain.css', js: 'rain.js', container: 'rain-container' },
|
||||
storm: { css: 'storm.css', js: 'storm.js', container: 'storm-container' },
|
||||
frost: { css: 'frost.css', js: 'frost.js', container: 'frost-container' },
|
||||
filmnoir: { css: 'filmnoir.css', js: 'filmnoir.js', container: 'filmnoir-container' },
|
||||
oscar: { css: 'oscar.css', js: 'oscar.js', container: 'oscar-container' },
|
||||
marioday: { css: 'marioday.css', js: 'marioday.js', container: 'marioday-container' },
|
||||
starwars: { css: 'starwars.css', js: 'starwars.js', container: 'starwars-container' },
|
||||
oktoberfest: { css: 'oktoberfest.css', js: 'oktoberfest.js', container: 'oktoberfest-container' },
|
||||
friday13: { css: 'friday13.css', js: 'friday13.js', container: 'friday13-container' },
|
||||
eid: { css: 'eid.css', js: 'eid.js', container: 'eid-container' },
|
||||
sports: { css: 'sports.css', js: 'sports.js', container: 'sports-container' },
|
||||
olympia: { css: 'olympia.css', js: 'olympia.js', container: 'olympia-container' },
|
||||
resurrection: { css: 'resurrection.css', js: 'resurrection.js', container: 'resurrection-container' },
|
||||
santa: { css: 'santa.css', js: 'santa.js', container: 'santa-container' },
|
||||
snowfall: { css: 'snowfall.css', js: 'snowfall.js', container: 'snowfall-container' },
|
||||
snowflakes: { css: 'snowflakes.css', js: 'snowflakes.js', container: 'snowflakes' },
|
||||
snowstorm: { css: 'snowstorm.css', js: 'snowstorm.js', container: 'snowstorm-container' },
|
||||
space: { css: 'space.css', js: 'space.js', container: 'space-container' },
|
||||
underwater: { css: 'underwater.css', js: 'underwater.js', container: 'underwater-container' },
|
||||
birthday: { css: 'birthday.css', js: 'birthday.js', container: 'birthday-container' }
|
||||
spooky: { css: 'spooky.css', js: 'spooky.js', container: 'spooky-container' },
|
||||
sports: { css: 'sports.css', js: 'sports.js', container: 'sports-container' },
|
||||
spring: { css: 'spring.css', js: 'spring.js', container: 'spring-container' },
|
||||
starwars: { css: 'starwars.css', js: 'starwars.js', container: 'starwars-container' },
|
||||
storm: { css: 'storm.css', js: 'storm.js', container: 'storm-container' },
|
||||
summer: { css: 'summer.css', js: 'summer.js', container: 'summer-container' },
|
||||
underwater: { css: 'underwater.css', js: 'underwater.js', container: 'underwater-container' }
|
||||
};
|
||||
|
||||
const select = document.getElementById('theme-select');
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
"imageUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/Jellyfin-Seasonals-Plugin/raw/branch/main/logo.png",
|
||||
"versions": [
|
||||
{
|
||||
"version": "2.0.0.1",
|
||||
"changelog": "- feat: add many themes\n- fix: improve performance",
|
||||
"version": "2.0.0.8",
|
||||
"changelog": "feat: add new themes:\n- birthday (ballons, computer mouse interactive)\n- earthday\n- Eid al-Fitr (sugar feast/ramadan)\n- eurovision\n- Film Noir filter\n- Friday the 13\n- frost\n- Mario Day\n- Matrix\n- Oktoberfest\n- Olympia\n- Oscar Awards\n- Pride\n- Rain\n- Spooky\n- Sports (many selectable balls of ball games like handball, football (soccer) or tennis)\n- StarWars Day\n- Storm (Epilepsy Warning!!!, Thunderstorm)\n\n- refactored spring (new lawn with flowers), easter (new easter bunny, new lawn with flowers and ester eggs), halloween (add spiders (computer mouse sensitive), add mice, add fog) \n- fix: many improvements and bug fixes e.g. changed top to translate/transform for performance reasons",
|
||||
"targetAbi": "10.11.0.0",
|
||||
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/Jellyfin-Seasonals-Plugin/releases/download/v2.0.0.1/Jellyfin.Plugin.Seasonals.zip",
|
||||
"checksum": "2eb9ce92f3aa89d133ad09cd874b7c85",
|
||||
"timestamp": "2026-02-27T03:27:02Z"
|
||||
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/Jellyfin-Seasonals-Plugin/releases/download/v2.0.0.8/Jellyfin.Plugin.Seasonals.zip",
|
||||
"checksum": "da10c4e44858f796cae1b77d0b866480",
|
||||
"timestamp": "2026-02-28T15:28:11Z"
|
||||
},
|
||||
{
|
||||
"version": "1.7.2.0",
|
||||
|
||||
Reference in New Issue
Block a user