Add Star Wars feature: implement CSS and JavaScript for hyperspace effect and visibility toggle
This commit is contained in:
60
Jellyfin.Plugin.Seasonals/Web/starwars.css
Normal file
60
Jellyfin.Plugin.Seasonals/Web/starwars.css
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
.starwars-container {
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 5;
|
||||||
|
contain: strict;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.starwars-center {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.starwars-streak {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 2px;
|
||||||
|
height: 100vh;
|
||||||
|
transform-origin: top center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.starwars-streak::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 2px;
|
||||||
|
height: 15vh;
|
||||||
|
background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, rgba(200, 230, 255, 0.8) 70%, rgba(255, 255, 255, 1) 100%);
|
||||||
|
box-shadow: 0 0 8px #88ccff;
|
||||||
|
border-radius: 2px;
|
||||||
|
animation: warp-streak cubic-bezier(0.7, 0, 1, 1) infinite;
|
||||||
|
animation-duration: inherit;
|
||||||
|
animation-delay: inherit;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
will-change: transform, opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes warp-streak {
|
||||||
|
0% {
|
||||||
|
transform: translateY(2vh) scaleY(0.1);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
20% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(150vh) scaleY(3);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
78
Jellyfin.Plugin.Seasonals/Web/starwars.js
Normal file
78
Jellyfin.Plugin.Seasonals/Web/starwars.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
const config = window.SeasonalsPluginConfig?.StarWars || {};
|
||||||
|
const starwars = config.EnableStarWars !== undefined ? config.EnableStarWars : true;
|
||||||
|
|
||||||
|
let msgPrinted = false;
|
||||||
|
|
||||||
|
function toggleStarWars() {
|
||||||
|
const container = document.querySelector('.starwars-container');
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
const videoPlayer = document.querySelector('.videoPlayerContainer');
|
||||||
|
const trailerPlayer = document.querySelector('.youtubePlayerContainer');
|
||||||
|
const isDashboard = document.body.classList.contains('dashboardDocument');
|
||||||
|
const hasUserMenu = document.querySelector('#app-user-menu');
|
||||||
|
|
||||||
|
if (videoPlayer || trailerPlayer || isDashboard || hasUserMenu) {
|
||||||
|
container.style.display = 'none';
|
||||||
|
if (!msgPrinted) {
|
||||||
|
console.log('StarWars hidden');
|
||||||
|
msgPrinted = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
container.style.display = 'block';
|
||||||
|
if (msgPrinted) {
|
||||||
|
console.log('StarWars visible');
|
||||||
|
msgPrinted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new MutationObserver(toggleStarWars);
|
||||||
|
observer.observe(document.body, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true,
|
||||||
|
attributes: true
|
||||||
|
});
|
||||||
|
|
||||||
|
function createStarWars(container) {
|
||||||
|
const center = document.createElement('div');
|
||||||
|
center.className = 'starwars-center';
|
||||||
|
container.appendChild(center);
|
||||||
|
|
||||||
|
// Create hyperspace streaks
|
||||||
|
for (let i = 0; i < 60; i++) {
|
||||||
|
const streak = document.createElement('div');
|
||||||
|
streak.className = 'starwars-streak';
|
||||||
|
|
||||||
|
// Random angle to radiate outward from center
|
||||||
|
const angle = Math.random() * 360;
|
||||||
|
streak.style.transform = `rotate(${angle}deg)`;
|
||||||
|
|
||||||
|
// Random delay
|
||||||
|
const delay = Math.random() * 2;
|
||||||
|
streak.style.animationDelay = `${delay}s`;
|
||||||
|
|
||||||
|
// Random animation duration for variety
|
||||||
|
const duration = 0.8 + Math.random() * 1.5;
|
||||||
|
streak.style.animationDuration = `${duration}s`;
|
||||||
|
|
||||||
|
center.appendChild(streak);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeStarWars() {
|
||||||
|
if (!starwars) return;
|
||||||
|
|
||||||
|
const container = document.querySelector('.starwars-container') || document.createElement("div");
|
||||||
|
|
||||||
|
if (!document.querySelector('.starwars-container')) {
|
||||||
|
container.className = "starwars-container";
|
||||||
|
container.setAttribute("aria-hidden", "true");
|
||||||
|
document.body.appendChild(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
createStarWars(container);
|
||||||
|
toggleStarWars();
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeStarWars();
|
||||||
Reference in New Issue
Block a user