Dynamische Bildergalerie

Anwendungen für Webseiten. Künstliche Intelligenz verwenden.
Antworten
Volker
Moderator
Moderator
Beiträge: 1678
Registriert: Sa 12. Dez 2020, 22:35

Dynamische Bildergalerie

Beitrag von Volker »

Moin :D

Hab es mal als extra Thema hier neu gemacht.

Meine neuste Entwicklung



Hier die Codes die Ihr braucht:

HTML Block:

Code: Alles auswählen

<section data-bs-version="5.1" class="content-gallery" group="Content" mbr-style="{
    'padding-top': paddingTop + 'rem',
    'padding-bottom': paddingBottom + 'rem',
    'background-color': bgColor,
    '--btnColor': btnColor
  }" data-thumbsize="{{thumbSize}}" data-perrow="{{perRow}}" data-maximages="{{maxImages}}">

  <mbr-parameters>
    <header>Abstände</header>
    <input type="range" inline title="Abstand oben" name="paddingTop" min="0" max="10" step="1" value="6">
    <input type="range" inline title="Abstand unten" name="paddingBottom" min="0" max="10" step="1" value="6">

    <header>Galerie-Einstellungen</header>
    <input type="range" title="Größe der Vorschaubilder (px)" name="thumbSize" min="80" max="240" step="10" value="210">
    <input type="range" title="Bilder pro Reihe" name="perRow" min="2" max="10" step="1" value="5">
    <input type="range" title="Bilder pro Seite" name="maxImages" min="1" max="50" step="1" value="10">

    <header>Farben</header>
    <input type="color" title="Hintergrundfarbe" name="bgColor" value="#000000">
    <input type="color" title="Buttonfarbe (Ordner)" name="btnColor" value="#ffa600">

    <header>Inhalt</header>
    <input type="text" title="Titel" name="title" value="Unsere Foto-Galerien">
    <textarea title="Beschreibung" name="text">Klicke auf ein Thema, um die Fotos anzuzeigen.</textarea>
  </mbr-parameters>

  <div class="container text-center">
    <h3 class="mbr-section-title mbr-fonts-style mb-3" mbr-theme-style="display-5">Dynamische Bilder Galerie</h3>
    <p class="mbr-text mbr-fonts-style mb-4" mbr-theme-style="display-7">Bilder werden einfach aus Ordnern eingelesen</p>

    <div id="galleryButtons" class="mb-4 d-flex flex-wrap justify-content-center gap-2"></div>
    <h5 id="currentGalleryTitle" class="text-center mb-4 text-muted"></h5>

    <div id="galleryGrid" class="gallery-grid"></div>

    <!-- Pagination -->
    <div id="pagination" class="mt-4 d-flex justify-content-center flex-wrap gap-1">
      <button id="prevPage" class="btn btn-outline-primary m-1">Zurück</button>
      <div id="pageNumbers" class="d-flex flex-wrap justify-content-center"></div>
      <button id="nextPage" class="btn btn-outline-primary m-1">Weiter</button>
    </div>
  </div>

  <!-- Lightbox -->
  <div id="lightbox-gallery" class="lightbox">
    <span class="close" onclick="closeGallery()">×</span>
    <div class="lightbox-content">
      <img class="lightbox-image" id="lightbox-image" src alt>
      <a class="prev" onclick="changeSlide(-1)">❮</a>
      <a class="next" onclick="changeSlide(1)">❯</a>
    </div>
  </div>

  <script>
    let galleryImages = [], currentSlide = 0, currentPage = 1, totalPages = 1;

    async function loadGalleries() {
      const res = await fetch('galerien/');
      const text = await res.text();
      const doc = new DOMParser().parseFromString(text, 'text/html');
      const folders = [...doc.querySelectorAll('a')]
        .map(a => a.getAttribute('href'))
        .filter(h => h && h.endsWith('/') && !h.includes('../') && !h.toLowerCase().includes('blogblock'))
        .map(h => h.replace('/', ''));

      const btns = document.getElementById('galleryButtons');
      btns.innerHTML = '';

      folders.forEach(f => {
        const b = document.createElement('button');
        b.className = 'btn m-1 gal-btn';
        b.textContent = f.charAt(0).toUpperCase() + f.slice(1);
        b.onclick = () => loadFolder(f);
        btns.appendChild(b);
      });

      if (folders.length) loadFolder(folders[0]);
    }

    async function loadFolder(folder) {
      const res = await fetch('galerien/' + folder + '/');
      const text = await res.text();
      const doc = new DOMParser().parseFromString(text, 'text/html');
      galleryImages = [...doc.querySelectorAll('a')]
        .map(a => a.getAttribute('href'))
        .filter(h => h && h.match(/\.(jpg|jpeg|png|gif|webp)$/i))
        .map(h => 'galerien/' + folder + '/' + h);

      currentPage = 1;
      renderGallery();

      document.getElementById('currentGalleryTitle').textContent =
        'Aktuelle Galerie: ' + folder.charAt(0).toUpperCase() + folder.slice(1);
    }

    function renderGallery() {
      const section = document.querySelector('.content-gallery');
      const perRow = parseInt(section.getAttribute('data-perRow')) || 4;
      const thumb = parseInt(section.getAttribute('data-thumbSize')) || 150;
      const perPage = parseInt(section.getAttribute('data-maxImages')) || 6;

      const grid = document.getElementById('galleryGrid');
      grid.innerHTML = '';
      grid.style.gridTemplateColumns = `repeat(${perRow}, 1fr)`;

      totalPages = Math.ceil(galleryImages.length / perPage);
      const start = (currentPage - 1) * perPage;
      const end = start + perPage;

      galleryImages.slice(start, end).forEach((src, i) => {
        const img = document.createElement('img');
        img.src = src;
        img.className = 'gallery-thumb-small';
        img.style.width = thumb + 'px';
        img.alt = 'Bild ' + (i + 1);
        img.onclick = () => openGallery(start + i);
        grid.appendChild(img);
      });

      updatePagination();
    }

    function updatePagination() {
      const prevBtn = document.getElementById('prevPage');
      const nextBtn = document.getElementById('nextPage');
      const pageContainer = document.getElementById('pageNumbers');

      prevBtn.disabled = currentPage === 1;
      nextBtn.disabled = currentPage === totalPages;

      pageContainer.innerHTML = '';

      for (let i = 1; i <= totalPages; i++) {
        const btn = document.createElement('button');
        btn.className = 'btn btn-sm m-1 page-btn ' + (i === currentPage ? 'active' : '');
        btn.textContent = i;
        btn.onclick = () => { currentPage = i; renderGallery(); };
        pageContainer.appendChild(btn);
      }

      prevBtn.onclick = () => {
        if (currentPage > 1) { currentPage--; renderGallery(); }
      };
      nextBtn.onclick = () => {
        if (currentPage < totalPages) { currentPage++; renderGallery(); }
      };
    }

    function openGallery(i) {
      currentSlide = i;
      document.getElementById('lightbox-gallery').style.display = 'block';
      showSlide(i);
    }
    function closeGallery() {
      document.getElementById('lightbox-gallery').style.display = 'none';
    }
    function changeSlide(n) {
      currentSlide = (currentSlide + n + galleryImages.length) % galleryImages.length;
      showSlide(currentSlide);
    }
    function showSlide(i) {
      document.getElementById('lightbox-image').src = galleryImages[i];
    }

    document.addEventListener('DOMContentLoaded', loadGalleries);
  </script>
</section>

CSS Block:

Code: Alles auswählen

.content-gallery {
  position: relative;
}
.gal-btn {
  background-color: var(--btnColor, #007bff) !important;
  border-color: var(--btnColor, #007bff) !important;
  color: #fff !important;
  border-radius: 6px;
  transition: all 0.3s ease;
}
.gal-btn:hover {
  opacity: 0.85;
}
.page-btn {
  background-color: transparent;
  color: var(--btnColor, #007bff);
  border: 1px solid var(--btnColor, #007bff);
  border-radius: 4px;
  min-width: 40px;
  transition: all 0.3s ease;
}
.page-btn.active, .page-btn:hover {
  background-color: var(--btnColor, #007bff);
  color: #fff;
}
.gallery-grid {
  display: grid;
  gap: 10px;
  justify-items: center;
}
.gallery-thumb-small {
  cursor: pointer;
  border-radius: 8px;
  transition: transform 0.3s ease, opacity 0.3s ease;
}
.gallery-thumb-small:hover {
  transform: scale(1.05);
  opacity: 0.8;
}
#pagination button {
  min-width: 80px;
}
.lightbox {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.9);
  z-index: 9999;
}
.lightbox-content {
  position: relative;
  margin: 60px auto;
  max-width: 80%;
  text-align: center;
}
.lightbox-image {
  width: 100%;
  max-height: 80vh;
  object-fit: contain;
  border-radius: 10px;
}
.close, .prev, .next {
  color: #fff;
  cursor: pointer;
  font-size: 40px;
  font-weight: bold;
  user-select: none;
  transition: color .3s;
}
.close:hover, .prev:hover, .next:hover {
  color: #bbb;
}
.close {
  position: absolute;
  top: 15px;
  right: 35px;
}
.prev, .next {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  padding: 16px;
}
.prev {
  left: 0;
}
.next {
  right: 0;
}
P {
  color: #ffffff;
}
H3 {
  color: #ffffff;
}
htaccess Datei :

Code: Alles auswählen

Options +Indexes
IndexOptions FancyIndexing NameWidth=*
AddType text/html .html .htm
Volker
Moderator
Moderator
Beiträge: 1678
Registriert: Sa 12. Dez 2020, 22:35

Re: Dynamische Bildergalerie

Beitrag von Volker »

Hallo zusammen,

ich habe eine App gebaut, die Bilder vom Handy direkt in vorgegebene Ordner Eurer Webseite lädt, um sie z.B. in der dynamischen Galerie anzuzeigen. Es geht natürlich auch jede andere Galerie ;)
Screenshot_20251110_214847[1].jpg
Ihr müsst nur einmalig die ftp Daten eingeben, so wie ich im Bild zeige, also nur den Domainnamen, Benutzer und Passwort. Da ich einen Benutzer angelegt habe der nur in den Ordner Bilder kann, brauche ich unten kein Verzeichnis angeben. Ansonsten da eben das Verzeichnis noch eintragen wo die Bilder hin sollen.

Screenshot_20251111_085527[1].jpg
Ihr könnt vor dem Hochladen die Bilder umbenennen und drehen.

Hier der Download zur App: https://www.niederastroth.de/bildupload.apk
Hier die dynamische Bidler Galerie:https://www.niederastroth.de/dynamische_galerie.html

Würde mich freuen wenn der ein oder andere das mal testet :D
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7971
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Dynamische Bildergalerie

Beitrag von Tommy Herrmann »

Moin Volker,

wollte Dich aufmerksam machen:

Hatte gerade mal auf Deiner Seite die Galerie angeguckt. Dabei viel mir auf, dass die Schrift von der vertikalen Sidebar offensichtlich nicht formatiert ist:

Newsletter Sidebar unformatierte Schrift.jpg


… weiterhin sitzt diese Sidebar am Handy unter dem Chatbutton und an meinem Handy liegt dann auch noch der automatisch erscheinende Pfeil "nach oben" ⬆️ über den Buttons, der in Screenshots nicht angezeigt wird:


Newsletter und Chat Buttons am Handy.jpg



Tipp zur Info:

nur mal angucken - Werner Zenk hatte so etwas Ähnliches schon mal im Jahr 2016 erstellt:

https://www.mobirise-tutorials.com/Fotouploadalbum.php

Mit Upload (auch vom Handy), Klickzähler und Editor für jedes Foto, Suchfunktion und beliebig vielen Benutzern, die alle nur ihre eigenen Fotos bearbeiten können, nur der Admin hat Zugriff auf alle Fotos. Das ist dann also eher als ein CMS zu verstehen, das von jedem Browser aus bedient werden kann - ganz ohne Mobirise:


Fotoalbum-Editor.jpg


Upload am Handy:


Fotoalbum Upload am Handy.jpg
Volker
Moderator
Moderator
Beiträge: 1678
Registriert: Sa 12. Dez 2020, 22:35

Re: Dynamische Bildergalerie

Beitrag von Volker »

Das Fotoalbum von Werner kenn ich sehr gut sogar :D
Hatte ich auch mal eingebaut. Aber das ist komplett was anderes - vor allen mit SQLight DB und einiges an Scripten.

Du vergleichts immer Äpfel mit Birnen Tommy. ;)

Ich rede hier von einer App. Dazu ist meine Idee mit der dynamischen Bilder Galerie auch komplett anders gedacht und auch technisch komplett anders aufgebaut. Einfacher eben :D Nix PHP Nix DB Nix Admin ;)

Die Zeit schreitet voran Tommy, was 2016 Top war ist jetzt schon wieder überholt, zumal das Fotoalbum auf Lightbox verzichtet und man immer jede Bild neu klicken muss. ( Das sollte man mal in die Neuzeit überführen )

Ich beschäftige mich im Moment mit Dart, eine Sprache auch für die APP Programmierung für Android und IOS Handys.

Neben dieser "FTP" App hab auch auch schon ein dB Messgerät für mein Handy gebastelt :D
Antworten

Wer ist online?

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