Mediawiki:common.js
| Строка 2222: | Строка 2222: | ||
var AprilFoolsCubeTransitionModule = { | var AprilFoolsCubeTransitionModule = { | ||
FORCE_FOR_ALL: false, | |||
ENABLE_APRIL_FIRST: false, | |||
DURATION_BEFORE_TRANSITION: 6500, | |||
overlay: null, | overlay: null, | ||
cube: null, | |||
frontImage: null, | |||
rightFrame: null, | |||
clockAudio: null, | |||
lampAudio: null, | |||
started: false, | started: false, | ||
init: function () { | init: function () { | ||
| Строка 2239: | Строка 2242: | ||
} | } | ||
var | var url = new URL(window.location.href); | ||
var | var isPreview = url.searchParams.get('prank_preview') === '1'; | ||
if (isPreview) { | |||
return; | |||
} | |||
var isPrankFlag = url.searchParams.get('prank') === '1'; | |||
var now = new Date(); | var now = new Date(); | ||
var isAprilFirst = now.getMonth() === 3 && now.getDate() === 1; | var isAprilFirst = now.getMonth() === 3 && now.getDate() === 1; | ||
var | var shouldRun = isPrankFlag || this.FORCE_FOR_ALL || (this.ENABLE_APRIL_FIRST && isAprilFirst); | ||
if (!shouldRun) { | if (!shouldRun) { | ||
return; | return; | ||
} | } | ||
this.injectStyles(); | this.injectStyles(); | ||
this. | this.createDom(); | ||
this. | this.createAudio(); | ||
this. | this.show(); | ||
var self = this; | var self = this; | ||
this.tryPlayClockNow(); | |||
this.bindAudioUnlock(); | |||
setTimeout(function () { | setTimeout(function () { | ||
self. | self.startCubeTransition(); | ||
}, | }, this.DURATION_BEFORE_TRANSITION); | ||
}, | }, | ||
injectStyles: function () { | injectStyles: function () { | ||
if (document.getElementById('april- | if (document.getElementById('april-cube-prank-styles')) return; | ||
var style = document.createElement('style'); | var style = document.createElement('style'); | ||
style.id = 'april- | style.id = 'april-cube-prank-styles'; | ||
style.textContent = | style.textContent = | ||
'#april- | '#april-cube-prank-overlay{' + | ||
'position:fixed;' + | 'position:fixed;' + | ||
'inset:0;' + | 'inset:0;' + | ||
'z-index:2147483647;' + | 'z-index:2147483647;' + | ||
'background:#000;' + | 'background:#000;' + | ||
'opacity:0;' + | 'opacity:0;' + | ||
'visibility:hidden;' + | 'visibility:hidden;' + | ||
'overflow:hidden;' + | 'overflow:hidden;' + | ||
' | 'transition:opacity .2s linear;' + | ||
'}' + | '}' + | ||
'#april- | '#april-cube-prank-overlay.active{' + | ||
'opacity:1;' + | 'opacity:1;' + | ||
'visibility:visible;' + | 'visibility:visible;' + | ||
'}' + | '}' + | ||
'#april- | '#april-cube-prank-scene{' + | ||
' | 'position:absolute;' + | ||
' | 'inset:0;' + | ||
' | 'perspective:1800px;' + | ||
' | 'perspective-origin:50% 50%;' + | ||
' | '--cube-depth:50vw;' + | ||
' | '}' + | ||
'- | '#april-cube-prank-cube{' + | ||
' | 'position:absolute;' + | ||
'inset:0;' + | |||
'transform-style:preserve-3d;' + | |||
'transform:translateZ(calc(-1 * var(--cube-depth))) rotateY(0deg);' + | |||
'will-change:transform,opacity;' + | |||
'}' + | '}' + | ||
'#april- | '#april-cube-prank-cube.exiting{' + | ||
'animation:aprilCubeRotateOut 1100ms cubic-bezier(.2,.8,.2,1) forwards;' + | |||
'animation: | |||
'}' + | '}' + | ||
'@keyframes | '@keyframes aprilCubeRotateOut{' + | ||
'0%{' + | '0%{' + | ||
'transform: | 'transform:translateZ(calc(-1 * var(--cube-depth))) rotateY(0deg);' + | ||
'opacity:1;' + | 'opacity:1;' + | ||
'}' + | '}' + | ||
'100%{' + | '100%{' + | ||
'transform: | 'transform:translateZ(calc(-1 * var(--cube-depth))) rotateY(-90deg);' + | ||
'opacity: | 'opacity:1;' + | ||
'}' + | '}' + | ||
'}' + | |||
'.april-cube-face{' + | |||
'position:absolute;' + | |||
'inset:0;' + | |||
'backface-visibility:hidden;' + | |||
'overflow:hidden;' + | |||
'background:#000;' + | |||
'}' + | |||
'.april-cube-face.front{' + | |||
'transform:translateZ(var(--cube-depth));' + | |||
'}' + | |||
'.april-cube-face.right{' + | |||
'transform:rotateY(90deg) translateZ(var(--cube-depth));' + | |||
'}' + | |||
'.april-cube-face.front img{' + | |||
'width:100%;' + | |||
'height:100%;' + | |||
'object-fit:cover;' + | |||
'object-position:center center;' + | |||
'display:block;' + | |||
'user-select:none;' + | |||
'-webkit-user-drag:none;' + | |||
'pointer-events:none;' + | |||
'}' + | |||
'.april-cube-face.right iframe{' + | |||
'width:100%;' + | |||
'height:100%;' + | |||
'border:0;' + | |||
'display:block;' + | |||
'background:#111;' + | |||
'}'; | '}'; | ||
document.head.appendChild(style); | document.head.appendChild(style); | ||
}, | }, | ||
createDom: function () { | |||
var overlay = document.createElement('div'); | var overlay = document.createElement('div'); | ||
overlay.id = 'april- | overlay.id = 'april-cube-prank-overlay'; | ||
var | var scene = document.createElement('div'); | ||
scene.id = 'april-cube-prank-scene'; | |||
var cube = document.createElement('div'); | |||
cube.id = 'april-cube-prank-cube'; | |||
var front = document.createElement('div'); | |||
front.className = 'april-cube-face front'; | |||
var img = document.createElement('img'); | |||
img.src = 'https://upload.wikimedia.org/wikipedia/commons/d/d4/2019_Screenshot_of_English_Wikipedia_homepage.png'; | |||
img.alt = 'Wikipedia home'; | |||
front.appendChild(img); | |||
var right = document.createElement('div'); | |||
right.className = 'april-cube-face right'; | |||
var | var iframe = document.createElement('iframe'); | ||
iframe.setAttribute('loading', 'eager'); | |||
iframe.setAttribute('referrerpolicy', 'no-referrer-when-downgrade'); | |||
iframe.src = this.buildPreviewUrl(); | |||
right.appendChild(iframe); | |||
cube.appendChild(front); | |||
cube.appendChild(right); | |||
scene.appendChild(cube); | |||
overlay.appendChild(scene); | |||
document.body.appendChild(overlay); | |||
this.overlay = overlay; | |||
this.cube = cube; | |||
this.frontImage = img; | |||
this.rightFrame = iframe; | |||
}, | }, | ||
buildPreviewUrl: function () { | |||
var url = new URL(window.location.href); | |||
url.searchParams.delete('prank'); | |||
url.searchParams.set('prank_preview', '1'); | |||
return url.toString(); | |||
}, | |||
createAudio: function () { | |||
this.clockAudio = new Audio('https://zvukogram.com/mp3/34/the-ticking-of-a-quartz-clock.mp3'); | |||
this.clockAudio.loop = true; | |||
this.clockAudio.preload = 'auto'; | |||
this.clockAudio.volume = 0.45; | |||
this.lampAudio = new Audio('https://zvukitop.com/wp-content/uploads/2021/04/luminesc-lampa-r4fh.mp3'); | |||
this.lampAudio.loop = false; | |||
this.lampAudio.preload = 'auto'; | |||
this.lampAudio.volume = 0.9; | |||
}, | |||
show: function () { | |||
if (!this.overlay) return; | |||
this.overlay.classList.add('active'); | |||
}, | |||
tryPlayClockNow: function () { | |||
if (!this.clockAudio) return; | |||
this.clockAudio.currentTime = 0; | |||
this. | |||
var playPromise = this.clockAudio.play(); | |||
if ( | if (playPromise && typeof playPromise.catch === 'function') { | ||
playPromise.catch(function () {}); | |||
} | } | ||
}, | }, | ||
bindAudioUnlock: function () { | |||
var self = this; | |||
function unlockAndPlay() { | |||
if (self.clockAudio) { | |||
self.clockAudio.play().catch(function () {}); | |||
} | |||
document.removeEventListener('pointerdown', unlockAndPlay); | |||
document.removeEventListener('keydown', unlockAndPlay); | |||
document.removeEventListener('touchstart', unlockAndPlay); | |||
} | } | ||
document.addEventListener('pointerdown', unlockAndPlay, { once: true }); | |||
document.addEventListener('keydown', unlockAndPlay, { once: true }); | |||
document.addEventListener('touchstart', unlockAndPlay, { once: true }); | |||
}, | }, | ||
startCubeTransition: function () { | |||
if (!this.cube || !this.overlay) return; | |||
if (!this. | |||
if (this.clockAudio) { | |||
this.clockAudio.pause(); | |||
this.clockAudio.currentTime = 0; | |||
} | |||
if (this.lampAudio) { | |||
this.lampAudio.currentTime = 0; | |||
this.lampAudio.play().catch(function () {}); | |||
} | } | ||
var | var self = this; | ||
this.cube.classList.add('exiting'); | |||
this.cube.addEventListener('animationend', function handleEnd() { | |||
self.cube.removeEventListener('animationend', handleEnd); | |||
if (self.overlay && self.overlay.parentNode) { | |||
self.overlay.parentNode.removeChild(self.overlay); | |||
} | |||
if (self.lampAudio) { | |||
self.lampAudio.pause(); | |||
self.lampAudio.currentTime = 0; | |||
} | |||
self.overlay = null; | |||
self.cube = null; | |||
self.frontImage = null; | |||
self.rightFrame = null; | |||
}); | |||
} | } | ||
}; | }; | ||