Bildergalerie extra für den Einbau in Mobirise

Anwendungen für Webseiten. Künstliche Intelligenz verwenden.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Tommy Herrmann »

warte - vielleicht habe ich es zur falschen Zeit runter geladen, denn jetzt sind die Bilder komplett unscharf :D

https://www.mobirise-tutorials.com/Tuto ... Upload.php
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Volker »

die sind ja total unscharf bei dir
Gruß Volker
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Tommy Herrmann »

Jetzt ist das mit der Lightbox am Smartphone gut und OK.

Die Bilder sind nun auch nach Bildnamen sortiert.

Dafür sind die Thumbs wieder da und noch unschärfer als je zuvor :eek:

https://www.mobirise-tutorials.com/Tuto ... Upload.php
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Volker »

Warum sind deine so groß ? Bei mir zeigt es doch auch die richtige Größe :confused:

Hast du was an der CSS geändert ?
Nimm doch mal die original galerie.php
Gruß Volker
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Tommy Herrmann »

Ich habe nichts außern das Passwort geändert.

Deine Thumbs sind zwar besser aber auch leicht unscharf - alle!

Vorhin hattest Du das doch schon im Griff :confused: Lasse die scheiß Thumbs doch einfach weg.
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Volker »

Du hast doch blauen hintergrund, in der original ist der weiß. Ich hab keine Ahnung was da schon wieder nicht richtig ist. hier der code der galerie.php:

Code: Alles auswählen

<?php
// Konfiguration - Pfade zur Bildergalerie
define('UPLOAD_DIR', 'uploads/');
define('THUMB_DIR', 'uploads/thumbs/');

// Funktion zum Abrufen der Bilder
function getGalleryImages() {
    $images = [];
    if (!is_dir(UPLOAD_DIR)) {
        return $images;
    }
    
    $files = glob(UPLOAD_DIR . '*.{jpg,jpeg,png,gif,webp}', GLOB_BRACE);
    foreach ($files as $file) {
        $filename = basename($file);
        $thumbPath = THUMB_DIR . $filename;
        
        $images[] = [
            'filename' => $filename,
            'full_path' => $file,
            'thumb_path' => file_exists($thumbPath) ? $thumbPath : $file,
            'size' => filesize($file),
            'modified' => filemtime($file)
        ];
    }
    
    // Sortiere nach Dateiname (aufsteigend, numerisch korrekt)
    usort($images, function($a, $b) {
        return strnatcmp($a['filename'], $b['filename']);
    });
    
    return $images;
}

$galleryImages = getGalleryImages();

// Parameter für Paginierung
$imagesPerPage = isset($_GET['per_page']) ? max(6, min(50, intval($_GET['per_page']))) : 12;
$currentPage = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$totalImages = count($galleryImages);
$totalPages = ceil($totalImages / $imagesPerPage);
$startIndex = ($currentPage - 1) * $imagesPerPage;
$currentImages = array_slice($galleryImages, $startIndex, $imagesPerPage);
?>


    <style>
	
	 body {
        background-color: white;
    }
        .gallery-container {
            max-width: 1400px;
            margin: 0 auto;
            padding: 20px;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        }

        .gallery-header {
            text-align: center;
            margin-bottom: 40px;
        }

        .gallery-title {
            font-size: 2.5rem;
            color: #333;
            margin-bottom: 10px;
            background: linear-gradient(45deg, #667eea, #764ba2);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }

        .gallery-stats {
            color: #666;
            font-size: 1.1rem;
            margin-bottom: 20px;
        }

        .gallery-controls {
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 20px;
            margin-bottom: 30px;
            flex-wrap: wrap;
        }

        .per-page-selector {
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .per-page-selector select {
            padding: 8px 12px;
            border: 2px solid #e1e5e9;
            border-radius: 8px;
            font-size: 14px;
            background: white;
            cursor: pointer;
        }

        .gallery-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
            gap: 25px;
            margin-bottom: 40px;
        }

        .gallery-item {
            background: white;
            border-radius: 15px;
            overflow: hidden;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
            transition: all 0.3s ease;
            cursor: pointer;
        }

        .gallery-item:hover {
            transform: translateY(-8px);
            box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
        }

        .gallery-item img {
            width: 100%;
            height: 250px;
            object-fit: cover;
            transition: transform 0.3s ease;
        }

        .gallery-item:hover img {
            transform: scale(1.1);
        }

        .gallery-item-info {
            padding: 15px;
            text-align: center;
        }

        .image-title {
            font-weight: 600;
            color: #333;
            font-size: 14px;
            margin-bottom: 5px;
            word-break: break-word;
        }

        .image-meta {
            font-size: 12px;
            color: #888;
        }

        .pagination {
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 10px;
            margin-top: 40px;
            flex-wrap: wrap;
        }

        .pagination a, .pagination span {
            padding: 10px 15px;
            text-decoration: none;
            border: 2px solid #e1e5e9;
            border-radius: 8px;
            color: #333;
            font-weight: 500;
            transition: all 0.3s ease;
            min-width: 45px;
            text-align: center;
        }

        .pagination a:hover {
            background: linear-gradient(45deg, #667eea, #764ba2);
            color: white;
            border-color: transparent;
        }

        .pagination .current {
            background: linear-gradient(45deg, #667eea, #764ba2);
            color: white;
            border-color: transparent;
        }

        .pagination .disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }

        .pagination .disabled:hover {
            background: white;
            color: #333;
            border-color: #e1e5e9;
        }

        .lightbox {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.95);
            z-index: 10000;
            cursor: pointer;
            justify-content: center;
            align-items: center;
        }
        
        .lightbox-content {
            display: flex;
            flex-direction: column;
            align-items: center;
            max-width: 95vw;
            max-height: 95vh;
            text-align: center;
        }

        .lightbox img {
            max-width: 100%;
            max-height: 100%;
            object-fit: contain;
            border-radius: 10px;
            box-shadow: 0 0 50px rgba(0, 0, 0, 0.5);
        }

        .lightbox-info {
            color: white;
            margin-top: 20px;
            font-size: 16px;
        }

        .lightbox-close {
            position: absolute;
            top: 20px;
            right: 30px;
            color: white;
            font-size: 40px;
            cursor: pointer;
            z-index: 10001;
            transition: opacity 0.3s ease;
        }

        .lightbox-close:hover {
            opacity: 0.7;
        }

        .lightbox-nav {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            color: white;
            font-size: 30px;
            cursor: pointer;
            background: rgba(0, 0, 0, 0.5);
            padding: 20px;
            border-radius: 50%;
            transition: all 0.3s ease;
            user-select: none;
        }

        .lightbox-nav:hover {
            background: rgba(0, 0, 0, 0.8);
        }

        .lightbox-prev {
            left: 30px;
        }

        .lightbox-next {
            right: 30px;
        }

        .empty-gallery {
            text-align: center;
            padding: 80px 20px;
            color: #666;
        }

        .empty-gallery h3 {
            font-size: 1.5rem;
            margin-bottom: 10px;
        }

        /* Responsive */
        @media (max-width: 768px) {
            .gallery-container {
                padding: 15px;
            }

            .gallery-title {
                font-size: 2rem;
            }

            .gallery-grid {
                grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
                gap: 20px;
            }

            .gallery-controls {
                flex-direction: column;
                gap: 15px;
            }

            .pagination {
                gap: 5px;
            }

            .pagination a, .pagination span {
                padding: 8px 12px;
                font-size: 14px;
            }

            .lightbox-nav {
                font-size: 24px;
                padding: 15px;
            }

            .lightbox-close {
                font-size: 30px;
                top: 15px;
                right: 20px;
            }
        }

        @media (max-width: 480px) {
            .gallery-grid {
                grid-template-columns: 1fr;
                gap: 15px;
            }

            .lightbox-nav {
                display: none;
            }
        }
        
        /* NEU: Bilder in der Lightbox auf größeren Bildschirmen verkleinern */
        @media (min-width: 769px) {
            .lightbox img {
                max-width: 80vw;
                max-height: 80vh;
            }
        }
    </style>

    <div id="galerie" class="gallery-container">
        <div class="gallery-header">
            <h1 class="gallery-title"> Bilder der Rehmühle</h1>
            <div class="gallery-stats">
                <?php echo $totalImages; ?> Bilder
                <?php if ($totalPages > 1): ?>
                    • Seite <?php echo $currentPage; ?> von <?php echo $totalPages; ?>
                <?php endif; ?>
            </div>
        </div>

        <?php if ($totalImages > 0): ?>
            <div class="gallery-controls">
                <div class="per-page-selector">
                    <label for="per-page">Bilder pro Seite:</label>
                    <select id="per-page" onchange="changePerPage(this.value)">
                        <option value="6" <?php echo $imagesPerPage == 6 ? 'selected' : ''; ?>>6</option>
                        <option value="12" <?php echo $imagesPerPage == 12 ? 'selected' : ''; ?>>12</option>
                        <option value="24" <?php echo $imagesPerPage == 24 ? 'selected' : ''; ?>>24</option>
                        <option value="48" <?php echo $imagesPerPage == 48 ? 'selected' : ''; ?>>48</option>
                    </select>
                </div>
            </div>

            <div class="gallery-grid">
                <?php foreach ($currentImages as $index => $image): ?>
                        <div class="gallery-item" onclick="openLightbox(event, <?php echo $startIndex + $index; ?>)">
                            <img 
                                src="<?php echo htmlspecialchars($image['thumb_path']); ?>" 
                                alt="<?php echo htmlspecialchars($image['filename']); ?>"
                                loading="lazy"
                            >
                            <div class="gallery-item-info">
                                <div class="image-title">
                                    <?php echo htmlspecialchars($image['filename']); ?>
                                </div>
                                <div class="image-meta">
                                    <?php echo date('d.m.Y', $image['modified']); ?> • 
                                    <?php echo number_format($image['size'] / 1024, 1); ?> KB
                                </div>
                            </div>
                        </div>
                <?php endforeach; ?>
            </div>

            <?php if ($totalPages > 1): ?>
                <div class="pagination">
                    <?php if ($currentPage > 1): ?>
                        <a href="?page=1&per_page=<?php echo $imagesPerPage; ?>">«</a>
                        <a href="?page=<?php echo $currentPage - 1; ?>&per_page=<?php echo $imagesPerPage; ?>">‹</a>
                    <?php else: ?>
                        <span class="disabled">«</span>
                        <span class="disabled">‹</span>
                    <?php endif; ?>

                    <?php
                    $start = max(1, $currentPage - 2);
                    $end = min($totalPages, $currentPage + 2);
                    
                    if ($start > 1) {
                        echo '<a href="?page=1&per_page=' . $imagesPerPage . '">1</a>';
                        if ($start > 2) echo '<span>...</span>';
                    }
                    
                    for ($i = $start; $i <= $end; $i++): ?>
                        <?php if ($i == $currentPage): ?>
                            <span class="current"><?php echo $i; ?></span>
                        <?php else: ?>
                            <a href="?page=<?php echo $i; ?>&per_page=<?php echo $imagesPerPage; ?>"><?php echo $i; ?></a>
                        <?php endif; ?>
                    <?php endfor;
                    
                    if ($end < $totalPages) {
                        if ($end < $totalPages - 1) echo '<span>...</span>';
                        echo '<a href="?page=' . $totalPages . '&per_page=' . $imagesPerPage . '">' . $totalPages . '</a>';
                    }
                    ?>

                    <?php if ($currentPage < $totalPages): ?>
                        <a href="?page=<?php echo $currentPage + 1; ?>&per_page=<?php echo $imagesPerPage; ?>">›</a>
                        <a href="?page=<?php echo $totalPages; ?>&per_page=<?php echo $imagesPerPage; ?>">»</a>
                    <?php else: ?>
                        <span class="disabled">›</span>
                        <span class="disabled">»</span>
                    <?php endif; ?>
                </div>
            <?php endif; ?>

        <?php else: ?>
            <div class="empty-gallery">
                <h3>Noch keine Bilder verfügbar</h3>
                <p>Die Galerie ist momentan leer.</p>
            </div>
        <?php endif; ?>
    </div>

    <div id="lightbox" class="lightbox" onclick="closeLightbox()">
        <span class="lightbox-close" onclick="closeLightbox()">&times;</span>
        <div class="lightbox-prev lightbox-nav" onclick="event.stopPropagation(); prevImage()">‹</div>
        <div class="lightbox-next lightbox-nav" onclick="event.stopPropagation(); nextImage()">›</div>
        <div class="lightbox-content">
            <img id="lightbox-img" src="" alt="">
            <div id="lightbox-info" class="lightbox-info"></div>
        </div>
    </div>

    <script>
        // Galerie-Daten für JavaScript
        const allImages = <?php echo json_encode($galleryImages); ?>;
        let currentLightboxIndex = 0;

        function openLightbox(event, index) {
            event.stopPropagation();
            currentLightboxIndex = index;
            updateLightboxContent();
            document.getElementById('lightbox').style.display = 'flex';
            document.body.style.overflow = 'hidden';
        }

        function closeLightbox() {
            document.getElementById('lightbox').style.display = 'none';
            document.body.style.overflow = 'auto';
        }

        function updateLightboxContent() {
            if (allImages[currentLightboxIndex]) {
                const image = allImages[currentLightboxIndex];
                document.getElementById('lightbox-img').src = image.full_path;
                document.getElementById('lightbox-info').innerHTML = 
                    '<strong>' + image.filename + '</strong><br>' +
                    new Date(image.modified * 1000).toLocaleDateString('de-DE') + ' • ' +
                    (image.size / 1024).toFixed(1) + ' KB';
            }
        }

        function nextImage() {
            if (currentLightboxIndex < allImages.length - 1) {
                currentLightboxIndex++;
                updateLightboxContent();
            }
        }

        function prevImage() {
            if (currentLightboxIndex > 0) {
                currentLightboxIndex--;
                updateLightboxContent();
            }
        }

        function changePerPage(value) {
            const url = new URL(window.location);
            url.searchParams.set('per_page', value);
            url.searchParams.set('page', '1');
            window.location = url;
        }

        // Fix für unerwartetes Popup beim Neuladen
        window.onload = function() {
            document.getElementById('lightbox').style.display = 'none';
        }

        // Keyboard Navigation
        document.addEventListener('keydown', function(e) {
            const lightbox = document.getElementById('lightbox');
            if (lightbox.style.display === 'flex') {
                switch(e.key) {
                    case 'Escape':
                        closeLightbox();
                        break;
                    case 'ArrowLeft':
                        prevImage();
                        break;
                    case 'ArrowRight':
                        nextImage();
                        break;
                }
            }
        });

        // Touch/Swipe Support für Mobile
        let touchStartX = 0;
        let touchEndX = 0;

        document.getElementById('lightbox').addEventListener('touchstart', function(e) {
            touchStartX = e.changedTouches[0].screenX;
        });

        document.getElementById('lightbox').addEventListener('touchend', function(e) {
            touchEndX = e.changedTouches[0].screenX;
            handleSwipe();
        });

        function handleSwipe() {
            const swipeDistance = touchEndX - touchStartX;
            const minSwipeDistance = 50;

            if (Math.abs(swipeDistance) > minSwipeDistance) {
                if (swipeDistance > 0) {
                    prevImage(); // Swipe right = previous image
                } else {
                    nextImage(); // Swipe left = next image
                }
            }
        }

        // Lazy Loading für bessere Performance
        if ('IntersectionObserver' in window) {
            const imageObserver = new IntersectionObserver((entries, observer) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        const img = entry.target;
                        img.src = img.dataset.src;
                        img.classList.remove('lazy');
                        observer.unobserve(img);
                    }
                });
            });

            document.querySelectorAll('img[data-src]').forEach(img => {
                imageObserver.observe(img);
            });
        }
    </script>
Gruß Volker
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Volker »

Tommy schau hier : https://www.niederastroth.de/bilder

wo ist da was unscharf ? Das sind die original bilder nur verkleinert. Tumbs nur für den Admin
Gruß Volker
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Volker »

Ich vermute das stört irgend etwas von Mobirise ... wohl in der CSS ??

Ich muss das mal testen

Ich hab ja nur die galerie.php in den articel Block eingefügt ohne sonstige Dinge von Mobirise ich vermute da liegt das Problem
Gruß Volker
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Tommy Herrmann »

So darfst Du Mobirise natürlich nicht testen, denn Mobirise hat doch Hunderte von Bootstrap-Klassen abgeändert und mit eigenen überschrieben. :angst:
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Volker »

Jetzt sehe ich den Mist auch :crying:

https://www.niederastroth.de/page8.html

Da muss ich mal auf die Suche gehen was da stört.
Gruß Volker
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Tommy Herrmann »

Wieso - ganz klar - die Thumbs sind zu klein. Mache diese Generierung weg und verwende einfach die Original-Fotos. Das stimmt sonst nie, denn es kann ja auch sein, dass Benutzer Fotos hochladen, die kleiner als die Thumbs von Dir sind.


P.S.:

Gucke bitte auch bei dem limitierten Download. Da ist noch ein Fehler, es wird immer nur der erste Token ausgeführt. Ich kann also nur einen Token erstellen.
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Volker »

Problem gelöst Kack Mobirise :D

https://www.niederastroth.de/page8.html

Habs jetzt riegeros gelöst. Damit Projekt abgeschlossen:

Download hier: https://www.niederastroth.de/bildergalerie.7z
Gruß Volker
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Tommy Herrmann »

Ja - jetzt ist es in Ordnung :tu:

https://www.mobirise-tutorials.com/Tuto ... Upload.php

… allerdings wird die Galerie auf der Adminseite immer noch unscharf angezeigt, was aber eher "kosmetisch" ist. Dennoch, sollte das nicht zu viel Arbeit sein, sollte das auch noch korrigiert werden, weil es einfach nicht schön ist. Nur perfekte Anwendungen schaffen Vertrauen.


Galerie auf Admin-Seite ist noch unscharf.jpg
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Volker »

Vertrauen ist gut - Kontrolle noch besser :D

Änder ich die Tage. Hab jetzt keinen Bock mehr :D

Als erstes ist das für mich so OK.

Ich träume schon in klammern und kommas und all dem kack :D
Gruß Volker
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Tommy Herrmann »

Ja - Du darfst das nicht übertreiben, das geht auf's Herz :kaffee:
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Volker »

Noch ein wichtiger Aspekt - hatte ich vergessen zu erwähnen :D

Anders als bei den Mobirse Blöcken kann der Nutzer natürlich auch durch das Script direkt Bilder von seinem Handy auf seine Webseite bringen ;) Das kann Mobirise nämlich nicht - ÄTSCH :P

Das ist eben der Vorteil wenn eine Anwendung online verfügbar ist ;)
Gruß Volker
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Volker »

So, damit ich Vertrauen bekomme :D

Admin hat jetzt auch die original Bilder. Thumb Ordner gibts nicht mehr

Fertig :D

Alles Neu im ZIP: https://www.niederastroth.de/bildergalerie.7z

Wer noch den Thumb Ordner hat, kann den löschen

Noch ein Hinweis: wer schon eine admin.php oder galerie.php in seinem Verzeichnis hat, kann auch beide Dateien umbenennen. Das sollte kein Problem darstellen.
Gruß Volker
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Tommy Herrmann »

Ich habe alles fertig (eventuell fehlt noch ein Sprunganker) und mein Tutorial auch geschrieben:

https://www.mobirise-tutorials.com/Tuto ... Upload.php
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Tommy Herrmann »

Moin,

ich habe mal ChatGPT gebeten das Script mit Sprunganker auf die Block id="galerie" zu erstellen. Das hat mehrere Anläufe gebraucht, bis es geklappt hat. Jetzt geht das, denn sonst sieht das nicht gut aus bei größeren Galerien. Sehen kannst Du es wenn Du die Anzahl der Bilder oben auf 6 stellst (wie bei diesem Link bereits eingearbeitet), damit zwei Seiten entstehen:

https://www.mobirise-tutorials.com/Tuto ... =1#galerie

Code: Alles auswählen

https://www.mobirise-tutorials.com/Tutorials-3/Galerie-Upload.php?gal_per_page=6&gal_page=1#galerie
Hier Dein umgeschriebenes Skript "galerie.php", so wie ich es jetzt verwende.

Keine Ahnung, ob Du das so in Deinen Download packen willst, denn es geht ja darum das korrekt in Mobirise einzubauen. So wie es bisher ist, fehlt der Sprunganker. Voraussetzung ist den Mobirise-Block mit dem PHP-Include oben links auch so zu nennen, denn da ist dann die Sprunganker-ID:

galerie

Code: Alles auswählen

<?php
// ========== KONFIG ==========
define('UPLOAD_DIR', 'uploads/');
define('THUMB_DIR',  'uploads/thumbs/');

// Optional: Wenn du die Links auf einen *bestimmten* Seitenpfad zwingen willst,
// kannst du hier z.B. '/Tutorials-3/Galerie-Upload.php' setzen.
// Leer lassen => es wird automatisch die aktuelle Seite (PHP_SELF) verwendet.
const GALLERY_SELF_PATH = ''; // z.B. '/deine-seite.php'

// ========== HILFSFUNKTIONEN ==========
function gallery_self_path(): string {
    if (GALLERY_SELF_PATH !== '') return GALLERY_SELF_PATH;
    // Sicherer, basisrelativer Pfad zur aktuell ausgeführten Seite
    $path = parse_url($_SERVER['PHP_SELF'] ?? '', PHP_URL_PATH);
    return $path ?: '/';
}

// Baut eine Galerie-URL: NUR die Galerie-Parameter, sonst nichts (robust gegen Konflikte)
function gallery_url_clean(int $page, int $perPage): string {
    $path = gallery_self_path();
    $query = http_build_query([
        'gal_page'     => max(1, $page),
        'gal_per_page' => max(6, min(50, $perPage)),
    ]);
    $url = $path . '?' . $query . '#galerie';
    return htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
}

// Bilder holen
function getGalleryImages(): array {
    $images = [];
    if (!is_dir(UPLOAD_DIR)) return $images;

    $files = glob(UPLOAD_DIR . '*.{jpg,jpeg,png,gif,webp}', GLOB_BRACE) ?: [];
    foreach ($files as $file) {
        $filename = basename($file);
        $images[] = [
            'filename'   => $filename,
            'full_path'  => $file,
            'thumb_path' => $file, // Original als Thumb
            'size'       => @filesize($file) ?: 0,
            'modified'   => @filemtime($file) ?: time(),
        ];
    }
    usort($images, fn($a,$b) => strnatcmp($a['filename'], $b['filename']));
    return $images;
}

// ========== LOGIK ==========
$galleryImages = getGalleryImages();

$imagesPerPage = isset($_GET['gal_per_page']) ? max(6, min(50, (int)$_GET['gal_per_page'])) : 12;
$currentPage   = isset($_GET['gal_page'])     ? max(1, (int)$_GET['gal_page']) : 1;

$totalImages   = count($galleryImages);
$totalPages    = max(1, (int)ceil($totalImages / $imagesPerPage));
$currentPage   = min($currentPage, $totalPages);
$startIndex    = ($currentPage - 1) * $imagesPerPage;
$currentImages = array_slice($galleryImages, $startIndex, $imagesPerPage);
?>

<style>
/* ... (dein bestehendes CSS, unverändert) ... */
.gallery-container img { image-rendering:-webkit-optimize-contrast!important; image-rendering:optimize-contrast!important; image-rendering:crisp-edges!important; -ms-interpolation-mode:nearest-neighbor!important; transform:none!important; filter:none!important; }
.gallery-container img { max-width:100%!important; height:auto!important; display:block!important; }
body{background-color:white;}
.gallery-container{max-width:1400px;margin:0 auto;padding:20px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;scroll-margin-top:90px;}
.gallery-header{text-align:center;margin-bottom:40px;}
.gallery-title{font-size:2.5rem;color:#333;margin-bottom:10px;background:linear-gradient(45deg,#667eea,#764ba2);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;}
.gallery-stats{color:#666;font-size:1.1rem;margin-bottom:20px;}
.gallery-controls{display:flex;justify-content:center;align-items:center;gap:20px;margin-bottom:30px;flex-wrap:wrap;}
.per-page-selector{display:flex;align-items:center;gap:10px;}
.per-page-selector select{padding:8px 12px;border:2px solid #e1e5e9;border-radius:8px;font-size:14px;background:white;cursor:pointer;}
.gallery-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:25px;margin-bottom:40px;}
.gallery-item{background:white;border-radius:15px;overflow:hidden;box-shadow:0 4px 20px rgba(0,0,0,.08);transition:all .3s ease;cursor:pointer;}
.gallery-item:hover{transform:translateY(-8px);box-shadow:0 12px 40px rgba(0,0,0,.15);}
.gallery-item img{width:100%;height:250px;object-fit:cover;transition:transform .3s ease;}
.gallery-item:hover img{transform:scale(1.1)!important;}
.gallery-item-info{padding:15px;text-align:center;}
.image-title{font-weight:600;color:#333;font-size:14px;margin-bottom:5px;word-break:break-word;}
.image-meta{font-size:12px;color:#888;}
.pagination{display:flex;justify-content:center;align-items:center;gap:10px;margin-top:40px;flex-wrap:wrap;}
.pagination a,.pagination span{padding:10px 15px;text-decoration:none;border:2px solid #e1e5e9;border-radius:8px;color:#333;font-weight:500;transition:all .3s ease;min-width:45px;text-align:center;}
.pagination a:hover{background:linear-gradient(45deg,#667eea,#764ba2);color:white;border-color:transparent;}
.pagination .current{background:linear-gradient(45deg,#667eea,#764ba2);color:white;border-color:transparent;}
.pagination .disabled{opacity:.5;cursor:not-allowed;}
.pagination .disabled:hover{background:white;color:#333;border-color:#e1e5e9;}
.lightbox{display:none;position:fixed;inset:0;background:rgba(0,0,0,.95);z-index:10000;cursor:pointer;justify-content:center;align-items:center;}
.lightbox-content{display:flex;flex-direction:column;align-items:center;max-width:95vw;max-height:95vh;text-align:center;}
.lightbox img{max-width:100%;max-height:100%;object-fit:contain;border-radius:10px;box-shadow:0 0 50px rgba(0,0,0,.5);}
.lightbox-info{color:white;margin-top:20px;font-size:16px;}
.lightbox-close{position:absolute;top:20px;right:30px;color:white;font-size:40px;cursor:pointer;z-index:10001;transition:opacity .3s ease;}
.lightbox-close:hover{opacity:.7;}
.lightbox-nav{position:absolute;top:50%;transform:translateY(-50%);color:white;font-size:30px;cursor:pointer;background:rgba(0,0,0,.5);padding:20px;border-radius:50%;transition:all .3s ease;user-select:none;}
.lightbox-nav:hover{background:rgba(0,0,0,.8);}
.lightbox-prev{left:30px;}
.lightbox-next{right:30px;}
.empty-gallery{text-align:center;padding:80px 20px;color:#666;}
.empty-gallery h3{font-size:1.5rem;margin-bottom:10px;}
@media(max-width:768px){.gallery-container{padding:15px}.gallery-title{font-size:2rem}.gallery-grid{grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:20px}.gallery-controls{flex-direction:column;gap:15px}.pagination{gap:5px}.pagination a,.pagination span{padding:8px 12px;font-size:14px}.lightbox-nav{font-size:24px;padding:15px}.lightbox-close{font-size:30px;top:15px;right:20px}}
@media(max-width:480px){.gallery-grid{grid-template-columns:1fr;gap:15px}.lightbox-nav{display:none}}
@media(min-width:769px){.lightbox img{max-width:80vw;max-height:80vh}}
</style>

<div id="galerie" class="gallery-container">
  <div class="gallery-header">
    <h1 class="gallery-title">Bilder</h1>
    <div class="gallery-stats">
      <?php echo $totalImages; ?> Bilder
      <?php if ($totalPages > 1): ?> • Seite <?php echo $currentPage; ?> von <?php echo $totalPages; ?> <?php endif; ?>
    </div>
  </div>

  <?php if ($totalImages > 0): ?>
    <div class="gallery-controls">
      <div class="per-page-selector">
        <label for="per-page">Bilder pro Seite:</label>
        <select id="per-page" onchange="changePerPage(this.value)">
          <option value="6"  <?php echo $imagesPerPage == 6  ? 'selected' : ''; ?>>6</option>
          <option value="12" <?php echo $imagesPerPage == 12 ? 'selected' : ''; ?>>12</option>
          <option value="24" <?php echo $imagesPerPage == 24 ? 'selected' : ''; ?>>24</option>
          <option value="48" <?php echo $imagesPerPage == 48 ? 'selected' : ''; ?>>48</option>
        </select>
      </div>
    </div>

    <div class="gallery-grid">
      <?php foreach ($currentImages as $index => $image): ?>
        <div class="gallery-item" onclick="openLightbox(event, <?php echo $startIndex + $index; ?>)">
          <img src="<?php echo htmlspecialchars($image['thumb_path']); ?>" alt="<?php echo htmlspecialchars($image['filename']); ?>" loading="lazy">
          <div class="gallery-item-info">
            <div class="image-title"><?php echo htmlspecialchars($image['filename']); ?></div>
            <div class="image-meta"><?php echo date('d.m.Y', $image['modified']); ?> • <?php echo number_format($image['size'] / 1024, 1); ?> KB</div>
          </div>
        </div>
      <?php endforeach; ?>
    </div>

    <?php if ($totalPages > 1): ?>
      <div class="pagination" id="gal-pagination">
        <?php if ($currentPage > 1): ?>
          <a href="<?php echo gallery_url_clean(1, $imagesPerPage); ?>" data-gal-page="1">«</a>
          <a href="<?php echo gallery_url_clean($currentPage-1, $imagesPerPage); ?>" data-gal-page="<?php echo $currentPage-1; ?>">‹</a>
        <?php else: ?>
          <span class="disabled">«</span>
          <span class="disabled">‹</span>
        <?php endif; ?>

        <?php
          $start = max(1, $currentPage - 2);
          $end   = min($totalPages, $currentPage + 2);

          if ($start > 1) {
            echo '<a href="'.gallery_url_clean(1, $imagesPerPage).'" data-gal-page="1">1</a>';
            if ($start > 2) echo '<span>...</span>';
          }

          for ($i = $start; $i <= $end; $i++) {
            if ($i == $currentPage) {
              echo '<span class="current">'.$i.'</span>';
            } else {
              echo '<a href="'.gallery_url_clean($i, $imagesPerPage).'" data-gal-page="'.$i.'">'.$i.'</a>';
            }
          }

          if ($end < $totalPages) {
            if ($end < $totalPages - 1) echo '<span>...</span>';
            echo '<a href="'.gallery_url_clean($totalPages, $imagesPerPage).'" data-gal-page="'.$totalPages.'">'.$totalPages.'</a>';
          }
        ?>

        <?php if ($currentPage < $totalPages): ?>
          <a href="<?php echo gallery_url_clean($currentPage+1, $imagesPerPage); ?>" data-gal-page="<?php echo $currentPage+1; ?>">›</a>
          <a href="<?php echo gallery_url_clean($totalPages, $imagesPerPage); ?>" data-gal-page="<?php echo $totalPages; ?>">»</a>
        <?php else: ?>
          <span class="disabled">›</span>
          <span class="disabled">»</span>
        <?php endif; ?>
      </div>
    <?php endif; ?>

  <?php else: ?>
    <div class="empty-gallery">
      <h3>Noch keine Bilder verfügbar</h3>
      <p>Die Galerie ist momentan leer.</p>
    </div>
  <?php endif; ?>
</div>

<div id="lightbox" class="lightbox" onclick="closeLightbox()">
  <span class="lightbox-close" onclick="closeLightbox()">&times;</span>
  <div class="lightbox-prev lightbox-nav" onclick="event.stopPropagation(); prevImage()">‹</div>
  <div class="lightbox-next lightbox-nav" onclick="event.stopPropagation(); nextImage()">›</div>
  <div class="lightbox-content">
    <img id="lightbox-img" src="" alt="">
    <div id="lightbox-info" class="lightbox-info"></div>
  </div>
</div>

<script>
// Daten
const allImages = <?php echo json_encode($galleryImages); ?>;
let currentLightboxIndex = 0;

// Lightbox
function openLightbox(e, idx){ e.stopPropagation(); currentLightboxIndex = idx; updateLightbox(); document.getElementById('lightbox').style.display='flex'; document.body.style.overflow='hidden'; }
function closeLightbox(){ document.getElementById('lightbox').style.display='none'; document.body.style.overflow='auto'; }
function updateLightbox(){
  const img = allImages[currentLightboxIndex]; if(!img) return;
  document.getElementById('lightbox-img').src = img.full_path;
  document.getElementById('lightbox-info').innerHTML =
    '<strong>'+img.filename+'</strong><br>'+
    new Date(img.modified*1000).toLocaleDateString('de-DE')+' • '+(img.size/1024).toFixed(1)+' KB';
}
function nextImage(){ if(currentLightboxIndex < allImages.length-1){ currentLightboxIndex++; updateLightbox(); } }
function prevImage(){ if(currentLightboxIndex > 0){ currentLightboxIndex--; updateLightbox(); } }

// Per-Page
function changePerPage(value){
  const url = new URL(window.location.href);
  url.searchParams.set('gal_per_page', value);
  url.searchParams.set('gal_page', '1');
  url.hash = 'galerie';
  window.location = url.toString();
}

// Onload: Hash beachten
window.onload = function(){
  document.getElementById('lightbox').style.display='none';
  if (location.hash === '#galerie') {
    const el = document.getElementById('galerie');
    if (el) el.scrollIntoView({ behavior: 'instant', block: 'start' });
  }
};

// Tastatur
document.addEventListener('keydown', e=>{
  const lb = document.getElementById('lightbox');
  if (lb.style.display === 'flex') {
    if (e.key === 'Escape') closeLightbox();
    if (e.key === 'ArrowLeft') prevImage();
    if (e.key === 'ArrowRight') nextImage();
  }
});

// Touch/Swipe
let touchStartX=0,touchEndX=0;
document.getElementById('lightbox').addEventListener('touchstart', e=>{ touchStartX = e.changedTouches[0].screenX; });
document.getElementById('lightbox').addEventListener('touchend',   e=>{
  touchEndX = e.changedTouches[0].screenX;
  const d = touchEndX - touchStartX; if (Math.abs(d) > 50) { d > 0 ? prevImage() : nextImage(); }
});

// Zusätzliche Absicherung: Pagination-Klicks per JS setzen (falls ein <base> o.ä. stört)
document.getElementById('gal-pagination')?.addEventListener('click', function(e){
  const a = e.target.closest('a[data-gal-page]');
  if (!a) return;
  // Wenn ein Theme/Script das Link-Ziel verbiegt, erzwingen wir unseren Weg:
  e.preventDefault();
  const url = new URL(window.location.href);
  url.searchParams.set('gal_page', a.getAttribute('data-gal-page'));
  url.searchParams.set('gal_per_page', '<?php echo $imagesPerPage; ?>');
  url.hash = 'galerie';
  window.location = url.toString();
});

// Optionales Lazy Loading (nur wenn data-src vorhanden)
if ('IntersectionObserver' in window) {
  const obs = new IntersectionObserver((entries,o)=>entries.forEach(en=>{
    if (en.isIntersecting) {
      const img = en.target;
      if (img.dataset && img.dataset.src) { img.src = img.dataset.src; img.classList.remove('lazy'); o.unobserve(img); }
    }
  }));
  document.querySelectorAll('img[data-src]').forEach(img=>obs.observe(img));
}
</script>

Hier die Erklärung von ChatGPT dazu:



ChatGPT hat geschrieben:
Was das Problem war

Parameter-Konflikt

Dein ursprüngliches Skript verwendete ?page=... und ?per_page=....

Mobirise verwendet aber intern auch die Parameter page und per_page in manchen Blöcken oder beim internen Routing.

Wenn dein Include auf einer Mobirise-Seite eingebettet war, kollidierten diese Parameter.

Ergebnis:

Dein Link änderte zwar ?page=2

Aber Mobirise interpretierte diesen Wert selbst – und lieferte weiter Seite 1 der Galerie zurück.

Doppelte IDs & Hash-Verhalten

Dein Mobirise-Block und das Galerie-Skript hatten beide id="galerie".

Das war kein direkter Fehler, aber Mobirise hat auf Klicks mit JavaScript gescrollt und das Neuladen der Galerie teilweise blockiert.

Basis-URL & <base href>

Mobirise setzt in vielen Projekten <base href="..."> in den <head>.

Dadurch haben relative Links wie ?page=2 manchmal nicht auf die gleiche Seite gezeigt, sondern wurden durch die Base-URL umgeleitet.

Teilweise blieb man deshalb visuell auf Seite 1 hängen, obwohl sich die URL änderte.

Was wir geändert haben

Eigene Parameter verwendet

Statt page / per_page nehmen wir jetzt gal_page und gal_per_page.

Diese sind eindeutig und können nicht mit Mobirise kollidieren.

Links explizit auf dieselbe Seite gesetzt

Alle Paginierungs-Links werden jetzt dynamisch mit $_SERVER['PHP_SELF'] gebaut.

Dadurch zeigen sie immer auf das richtige PHP-Skript – egal, wie Mobirise-URLs, Includes oder Unterverzeichnisse strukturiert sind.

Hash #galerie am Ende

Der Hash sorgt dafür, dass der Browser nach dem Reload automatisch zum Galerie-Bereich springt.

Das machen wir sauber und konsistent in allen Links.

JavaScript-Fallback eingebaut

Falls Mobirise per JavaScript einen Link-Click überschreibt, fängt unser Skript den Klick ab und setzt die URL aktiv neu.

Damit erzwingen wir, dass wirklich die nächste Galerie-Seite geladen wird.

In einfachen Worten

Vorher:
→ Klick auf „Seite 2“ → Mobirise fing ?page=2 ab → Galerie blieb auf Seite 1 → Sprunganker funktionierte trotzdem, weil der Hash ja da war.

Jetzt:
→ Klick auf „Seite 2“ → unser Link geht mit eigenen Parametern → keine Kollision mehr → PHP lädt Seite 2 → Browser springt zur Galerie.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Bildergalerie extra für den Einbau in Mobirise

Ungelesener Beitrag von Tommy Herrmann »

noch was - fast vergessen ...

... Deine Navigationspfeile in der Lightbox haben übrigens einen sehr unschönen, eierförmigen Hintergrund. Vielleicht magst Du das noch in der CSS anpassen. Ich Habe das für mich auf die Schnelle mit dem Padding zurecht gerückt:

.lightbox-nav{position:absolute;top:50%;transform:translateY(-50%);color:white;font-size:40px;cursor:pointer;background:rgba(0,0,139,.5);padding: 0px 26px 6px 26px;border-radius:50%;transition:all .3s ease;user-select:none;}
Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste