feat(jeu): bloc Kirby iframe + logique click-to-play dans Article.svelte
- site/blueprints/blocks/jeu.yml : champ URL pour l'iframe - site/snippets/blocks/jeu.php : rendu HTML statique (container + overlay + bouton désactivation) - Article.svelte : $effect pour attacher les handlers clic sur .iframe-game-container et onMount pour écouter postMessage GameReleaseFocus depuis impact.games Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ef992708fc
commit
5b9b190b35
3 changed files with 87 additions and 0 deletions
9
site/blueprints/blocks/jeu.yml
Normal file
9
site/blueprints/blocks/jeu.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
name: Jeu (iframe)
|
||||||
|
icon: preview
|
||||||
|
|
||||||
|
fields:
|
||||||
|
url:
|
||||||
|
label: URL de l'iframe
|
||||||
|
type: url
|
||||||
|
required: true
|
||||||
|
help: "URL complète de l'iframe (ex: https://impact.games/...)"
|
||||||
19
site/snippets/blocks/jeu.php
Normal file
19
site/snippets/blocks/jeu.php
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php if ($block->url()->isNotEmpty()): ?>
|
||||||
|
<div class="iframe-game-container">
|
||||||
|
<iframe
|
||||||
|
loading="eager"
|
||||||
|
importance="high"
|
||||||
|
width="400"
|
||||||
|
height="650"
|
||||||
|
style="float: right; border: medium; overflow: hidden; margin: 10px; pointer-events: none;"
|
||||||
|
src="<?= $block->url()->html() ?>"
|
||||||
|
></iframe>
|
||||||
|
<div class="iframe-click-overlay">
|
||||||
|
<div class="overlay-content">
|
||||||
|
<div class="play-icon">▶</div>
|
||||||
|
<p>Cliquez pour jouer</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="iframe-deactivate-btn" title="Deactivate game (restore scrolling)">✕</button>
|
||||||
|
</div>
|
||||||
|
<?php endif ?>
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { t } from '@i18n'
|
import { t } from '@i18n'
|
||||||
|
import { onMount } from 'svelte'
|
||||||
import Footer from '@components/layout/Footer.svelte'
|
import Footer from '@components/layout/Footer.svelte'
|
||||||
|
|
||||||
let { data, onBack } = $props()
|
let { data, onBack } = $props()
|
||||||
|
|
@ -12,6 +13,64 @@
|
||||||
let copySuccess = $state(false)
|
let copySuccess = $state(false)
|
||||||
let copyTimer = null
|
let copyTimer = null
|
||||||
|
|
||||||
|
// Setup click-to-play iframes après le rendu du body HTML
|
||||||
|
$effect(() => {
|
||||||
|
if (!data.body) return
|
||||||
|
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
document.querySelectorAll('.iframe-game-container').forEach(container => {
|
||||||
|
if (container.dataset.initialized) return
|
||||||
|
container.dataset.initialized = 'true'
|
||||||
|
|
||||||
|
const overlay = container.querySelector('.iframe-click-overlay')
|
||||||
|
const iframe = container.querySelector('iframe')
|
||||||
|
const deactivateBtn = container.querySelector('.iframe-deactivate-btn')
|
||||||
|
|
||||||
|
overlay?.addEventListener('click', () => {
|
||||||
|
overlay.style.display = 'none'
|
||||||
|
iframe.style.pointerEvents = 'auto'
|
||||||
|
container.classList.add('game-active')
|
||||||
|
overlay.setAttribute('data-state', 'played')
|
||||||
|
})
|
||||||
|
|
||||||
|
deactivateBtn?.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
overlay.style.display = 'flex'
|
||||||
|
iframe.style.pointerEvents = 'none'
|
||||||
|
container.classList.remove('game-active')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}, 300)
|
||||||
|
|
||||||
|
return () => clearTimeout(timer)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Écoute les messages postMessage depuis l'iframe du jeu
|
||||||
|
onMount(() => {
|
||||||
|
const handleIframeMessage = (event) => {
|
||||||
|
if (!event.origin.includes('impact.games')) return
|
||||||
|
if (event.data.type !== 'GameReleaseFocus') return
|
||||||
|
|
||||||
|
document.querySelectorAll('.iframe-click-overlay').forEach(overlay => {
|
||||||
|
if (overlay.getAttribute('data-state') === 'played') {
|
||||||
|
overlay.setAttribute('data-state', 'ended')
|
||||||
|
overlay.innerHTML = '<div class="overlay-content"></div>'
|
||||||
|
overlay.style.cursor = 'default'
|
||||||
|
overlay.style.pointerEvents = 'none'
|
||||||
|
}
|
||||||
|
overlay.style.display = 'flex'
|
||||||
|
})
|
||||||
|
|
||||||
|
document.querySelectorAll('.iframe-game-container').forEach(container => {
|
||||||
|
container.querySelector('iframe').style.pointerEvents = 'none'
|
||||||
|
container.classList.remove('game-active')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('message', handleIframeMessage)
|
||||||
|
return () => window.removeEventListener('message', handleIframeMessage)
|
||||||
|
})
|
||||||
|
|
||||||
function copyLink() {
|
function copyLink() {
|
||||||
navigator.clipboard.writeText(window.location.href)
|
navigator.clipboard.writeText(window.location.href)
|
||||||
copySuccess = true
|
copySuccess = true
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue