viewer_sgos / fullscreen_playcanvas.js
MikaFil's picture
Update fullscreen_playcanvas.js
fa92696 verified
// fullscreen.js
(function () {
// ─── 1. Localiser la balise <script> ────────────────────────────────────────
const scriptTag = document.currentScript || (function () {
const all = document.getElementsByTagName('script');
for (let i = all.length - 1; i >= 0; i--) {
if (all[i].src && all[i].src.includes('fullscreen.js')) return all[i];
}
return all[all.length - 1];
})();
const playcanvasUrl = scriptTag.getAttribute('data-src');
if (!playcanvasUrl) return;
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
const id = Math.random().toString(36).substr(2, 8);
// ─── 4. Calcul des ratios (Desktop & Mobile Portrait) ────────────────────────
function computeAspectPadding(aspectStr) {
if (!aspectStr) return null;
if (aspectStr.includes(':')) {
const [w, h] = aspectStr.split(':').map(Number);
return (w > 0 && h > 0) ? (h / w) * 100 + '%' : null;
}
const v = parseFloat(aspectStr);
return (v > 0) ? (100 / v) + '%' : null;
}
const desktopPadding = computeAspectPadding(scriptTag.getAttribute('data-aspect')) || '56.25%';
const mobilePadding = computeAspectPadding(scriptTag.getAttribute('data-aspect-mobile')) || desktopPadding;
// ─── 5. Injection du CSS avec Media Queries ──────────────────────────────────
const style = document.createElement('style');
style.textContent = `
.pc-embed-wrapper-${id} {
position: relative;
width: 100%;
height: 0;
overflow: hidden;
background: #000;
box-sizing: border-box;
/* Ratio par dΓ©faut (Paysage / Desktop) */
padding-bottom: ${desktopPadding};
}
/* Ratio Mobile Portrait : appliquΓ© uniquement si l'Γ©cran est plus haut que large */
@media (orientation: portrait) and (max-width: 768px) {
.pc-embed-wrapper-${id} {
padding-bottom: ${mobilePadding};
}
}
.pc-embed-wrapper-${id}.fake-fullscreen {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100vw !important;
height: 100vh !important;
height: 100dvh !important;
max-width: 100vw !important;
max-height: 100dvh !important;
padding-bottom: 0 !important;
margin: 0 !important;
z-index: 99999;
}
.pc-embed-inner-${id} {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
}
.pc-embed-inner-${id} iframe {
width: 100%; height: 100%;
border: none;
display: block;
}
.pc-fs-btn-${id} {
position: absolute;
top: 10px;
right: 10px;
z-index: 10;
width: 36px;
height: 36px;
border-radius: 50%;
border: none;
background: #2E2E2EB3;
color: #fff;
font-size: 18px;
line-height: 36px;
text-align: center;
cursor: pointer;
user-select: none;
}
`;
document.head.appendChild(style);
// ─── 6. Construction du DOM ──────────────────────────────────────────────────
const wrapper = document.createElement('div');
wrapper.className = `pc-embed-wrapper-${id}`;
const inner = document.createElement('div');
inner.className = `pc-embed-inner-${id}`;
const iframe = document.createElement('iframe');
const urlObj = new URL(playcanvasUrl);
urlObj.searchParams.set('overlay', 'false');
iframe.src = urlObj.href;
iframe.setAttribute('allowfullscreen', '');
iframe.setAttribute('allow', 'autoplay; fullscreen');
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-pointer-lock allow-popups allow-forms');
const fsBtn = document.createElement('button');
fsBtn.className = `pc-fs-btn-${id}`;
fsBtn.textContent = '⇱';
inner.appendChild(iframe);
wrapper.appendChild(inner);
wrapper.appendChild(fsBtn);
scriptTag.parentNode.insertBefore(wrapper, scriptTag.nextSibling);
// ─── 7. Γ‰tat & Helper ────────────────────────────────────────────────────────
let isFullscreen = false;
let savedParent = null;
let savedNextSibling = null;
function getHeightUnit() {
return (CSS && CSS.supports && CSS.supports('height', '100dvh')) ? '100dvh' : '100vh';
}
// ─── 8. Styles Plein Γ‰cran ───────────────────────────────────────────────────
function applyFullscreenStyles() {
const h = isIOS ? getHeightUnit() : '100vh';
wrapper.style.position = 'fixed';
wrapper.style.top = '0';
wrapper.style.left = '0';
wrapper.style.width = '100vw';
wrapper.style.height = h;
wrapper.style.maxHeight = h;
wrapper.style.paddingBottom = '0';
wrapper.style.margin = '0';
wrapper.style.zIndex = '99999';
wrapper.classList.add('fake-fullscreen');
fsBtn.textContent = '⇲';
isFullscreen = true;
}
function applyFakeFullscreenStyles() {
savedParent = wrapper.parentNode;
savedNextSibling = wrapper.nextSibling;
document.body.appendChild(wrapper);
applyFullscreenStyles();
}
function restoreStyles() {
wrapper.style.cssText = '';
// Le CSS via les Media Queries reprendra le dessus automatiquement ici
wrapper.classList.remove('fake-fullscreen');
fsBtn.textContent = '⇱';
isFullscreen = false;
if (savedParent) {
savedParent.insertBefore(wrapper, savedNextSibling);
savedParent = null;
savedNextSibling = null;
}
}
// ─── 9. Gestionnaires d'Γ©vΓ©nements ───────────────────────────────────────────
function enterFullscreen() {
if (isIOS) {
applyFakeFullscreenStyles();
document.body.style.overflow = 'hidden';
} else {
const el = wrapper;
const req = el.requestFullscreen || el.webkitRequestFullscreen || el.mozRequestFullScreen || el.msRequestFullscreen;
if (req) {
req.call(el).catch(() => {
applyFakeFullscreenStyles();
document.body.style.overflow = 'hidden';
});
} else {
applyFakeFullscreenStyles();
document.body.style.overflow = 'hidden';
}
}
}
function exitFullscreen() {
if (document.fullscreenElement || document.webkitFullscreenElement) {
(document.exitFullscreen || document.webkitExitFullscreen || function(){}).call(document);
}
restoreStyles();
document.body.style.overflow = '';
}
fsBtn.addEventListener('click', (e) => {
e.stopPropagation();
isFullscreen ? exitFullscreen() : enterFullscreen();
});
document.addEventListener('fullscreenchange', () => {
const fsEl = document.fullscreenElement || document.webkitFullscreenElement;
if (!fsEl && isFullscreen) exitFullscreen();
else if (fsEl === wrapper && !isFullscreen) applyFullscreenStyles();
});
window.addEventListener('resize', () => {
if (isFullscreen) {
const h = isIOS ? getHeightUnit() : '100vh';
wrapper.style.height = h;
wrapper.style.maxHeight = h;
}
});
})();