С одной HTML страницы открывать разные изображения в разных альбомах

Как сделать фотоальбом на js.

Нажимаешь на альбом с животными - открывается страница с изображениями животных, нажимаешь на альбом с деревьями - открывается страница с изображениями деревьев, смысл понятен.

Вопрос в том как это реализовать.

Делать 20 html страниц на 20 альбомов явно не вариант, думаю сделать один основной html документ и в нем один на все альбомы другой html док. Только я не знаю как написать так, чтобы при открытии разных альбомов открывались разные изображения. Может кто подскажет в каком направлении мне идти чтобы это реализовать? Или где об этом можно почитать? И можно ли сделать это без бэкенда на js?

<main class="albom">
  <ul class="cards">
    <li class="card">
      <a href="./photos.html">
        <img class="picture" src="./pictures/IMG_2229.JPG">
      </a>
    </li>
    <li class="card">
      <a href="./photos.html">
        <img class="picture" src="./pictures/IMG_5398.JPG">
      </a>
    </li>
    <li class="card">
      <a href="./photos.html">
        <img class="picture" src="./pictures/IMG_5398.JPG">
      </a>
    </li>
    <li class="card">
      <a href="./photos.html">
        <img class="picture" src="./pictures/IMG_5398.JPG">
      </a>
    </li>
  </ul>
</main>

Ответы (2 шт):

Автор решения: Dev18

Предложу вариант с простенькой реализацией фотоальбома на JavaScript, где при нажатии на "ссылку" <a> с атрибутом data-album будут подгружаться соответствующие изображения из заранее определенного массива. Эти изображения будут отображаться в контейнере imagesContainer, который необходимо очистить перед каждой новой загрузкой. imagesContainer.innerHTML = "";

document.addEventListener("DOMContentLoaded", function() {
  const albums = {
    animals: [
      "https://i.sstatic.net/7oVRCSke.jpg",
      "https://i.sstatic.net/LRuawLtd.jpg",
      "https://i.sstatic.net/fzB8KfZ6.jpg"
    ],
    trees: [
      "https://i.sstatic.net/tCn2EM1y.jpg",
      "https://i.sstatic.net/kEgUX3lb.jpg",
      "https://i.sstatic.net/TiGiwwJj.jpg"
    ]
  };

  const albumLinks = document.querySelectorAll(".album-list a");
  const imagesContainer = document.getElementById("imagesContainer");

  albumLinks.forEach(link => {
    link.addEventListener("click", function(event) {
      event.preventDefault();
      const albumName = link.dataset.album;
      loadAlbum(albumName);
    });
  });

  function loadAlbum(albumName) {
    imagesContainer.innerHTML = "";

    if (albums[albumName]) {
      albums[albumName].forEach(src => {
        const img = document.createElement("img");
        img.src = src;
        imagesContainer.appendChild(img);
      });
    }
  }
});
.album-list {
  display: flex;
  gap: 20px;
}

.album-list a {
  cursor: pointer;
  text-decoration: underline;
}

.images-container {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 20px;
}

.images-container img {
  width: 200px;
  height: 150px;
  object-fit: cover;
}
<div class="album-list">
  <a href="#" data-album="animals">Альбом с животными</a>
  <a href="#" data-album="trees">Альбом с деревьями</a>
</div>

<div class="images-container" id="imagesContainer">
  <!-- Изображения будут подгружаться сюда -->
</div>

→ Ссылка
Автор решения: EzioMercer

Создайте файл album.html, создайте и к нему подключите файл album.js

На вашей основной странице в ссылках на альбомы будете писать так: /path/to/album.html?id=<название или id альбома>. Так же в основном JS файле, вам нужно будет создать объект по типу:

const albums = {
  first: [
    "Some links for this album"
  ],
  second: [
    "Some links for this album"
  ],
  ...
}

Далее этот объект сохраняете в localStorage

После клика по ссылке, вас перенаправит на файл album.html, где в адресной строке будет указан id, который нужно будет достать в album.js. А ещё в этом же файле нужно будет достать объект, который в localStorage. Из этого объекта достаёте альбом по ключу равному id из адресной строки

Далее на основе полученного альбома (т.е. массива ссылок на картинки), нужно будет сгенерировать альбом в albom.html и всё

Таким образом у вас будет одна страница, которая в зависимости от преданного id будет показывать нужный альбом

Ну и естественно, вам нужно будет обработать случаи, когда id не окажется в объекте. Как вариант можно на 404-ую страницу отправить

Примерно так я вижу структуру вашего сайта:

введите сюда описание изображения

Ниже будут содержания каждого из файлов:

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Albums</title>
        <script defer src="/localDB/albumsDB.js"></script>
        <script defer src="index.js"></script>
        <link rel="stylesheet" href="index.css">
    </head>
    <body>
        <main class="albums_preview_container">
            <h1>Ниже вы можете увидеть список альбомов</h1>

            <ul class="albums_preview_list"></ul>
        </main>
    </body>
</html>

index.css

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html,
body {
    height: 100%;
}

ul {
    list-style: none;
}

.albums_preview_container {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.albums_preview_list {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-auto-rows: minmax(100px, 1fr);
    gap: 8px;
}

.albums_preview_list > a {
    width: 100%;
    height: 100%;
}

.album_preview_item > a > .preview_image {
    width: 100%;
    height: 100%;
}

index.js

localStorage.setItem('albumsDB', JSON.stringify(albumsDB));

const albumsList = document.querySelector('.albums_preview_list');
const fragment = document.createDocumentFragment();

/**
 * @param {Album} albumData
 * @param {string} albumId
 * @returns {HTMLLIElement}
 */
const createAlbumItem = (albumData, albumId) => {
    const albumItem = document.createElement("li");
    albumItem.classList.add("album_preview_item");
    
    const linkToWholeAlbum = document.createElement("a");
    linkToWholeAlbum.href = `/Album/pages/album/album.html?id=${albumId}`;
    
    const previewImage = document.createElement("img");
    previewImage.src = albumData.images[0];
    previewImage.classList.add('preview_image');
    
    linkToWholeAlbum.append(previewImage);
    albumItem.append(linkToWholeAlbum);
    
    return albumItem;
}

for (const albumId in albumsDB) {
    const albumData = albumsDB[albumId];
    
    fragment.append(createAlbumItem(albumData, albumId));
}

albumsList.append(fragment);

localDB/albumsDB.js

/**
 * @typedef {{
 *     title: string,
 *     images: string[]
 * }} Album
 */

/**
 * @type {{[key: string]: Album}}
 */
const albumsDB = {
    cats: {
        title: 'Кошки',
        images: [
            'https://www.alleycat.org/wp-content/uploads/2019/03/FELV-cat.jpg',
            'https://d2zp5xs5cp8zlg.cloudfront.net/image-53920-800.jpg',
            'https://www.vmcdn.ca/f/files/sootoday/village-life/pets/most-popular-cat-breeds/adobestock_66233948.jpeg;w=960'
        ]
    },
    dogs: {
        title: 'Собаки',
        images: [
            'https://cdn.britannica.com/79/232779-050-6B0411D7/German-Shepherd-dog-Alsatian.jpg',
            'https://dogtime.com/wp-content/uploads/sites/12/2023/11/GettyImages-529202089-e1701095552546.jpg?w=1024',
            'https://ichef.bbci.co.uk/news/976/cpsprodpb/12EAD/production/_131058477_dog.jpg'
        ]
    },
    nature: {
        title: 'Природа',
        images: [
            'https://good-nature-blog-uploads.s3.amazonaws.com/uploads/2022/01/good-nature-homepage-hero_2-scaled.jpg',
            'https://d19h8kn98xvxar.cloudfront.net/images/_hero/connectwithnature.jpg',
            'https://miro.medium.com/v2/resize:fit:1400/1*x0vDKUdcRMx7kfsFGq689w.jpeg'
        ]
    }
}

pages/album/album.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Album</title>
        <link rel="stylesheet" href="album.css">
        <script defer src="album.js"></script>
    </head>
    <body>
        <main class="album_container">
            <h1 class="album_title">Альбом: </h1>

            <ul class="images"></ul>
        </main>
    </body>
</html>

pages/album/album.css

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html,
body {
    height: 100%;
}

ul {
    list-style: none;
}

.album_container {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.images {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-auto-rows: minmax(100px, 1fr);
    gap: 8px;
}

.image > img {
    width: 100%;
    height: 100%;
}

pages/album/album.js

const albumsDB = JSON.parse(localStorage.getItem("albumsDB")) || {};
const albumId = new URLSearchParams(document.location.search).get("id");

/**
 * @type {Album | undefined}
 */
const album = albumsDB[albumId];

if (typeof album === 'undefined') {
    alert("No Album Found");
    
    window.location = '/Album';
}

const headerText = document.querySelector('h1');
headerText.textContent += album.title;

const imagesList = document.querySelector('.images');
const fragment = document.createDocumentFragment();

/**
 * @param {string} imageSrc
 * @returns {HTMLLIElement}
 */
const createAlbumItem = (imageSrc) => {
    const albumItem = document.createElement("li");
    albumItem.classList.add("image");
    
    const image = document.createElement("img");
    image.src = imageSrc;
    
    albumItem.append(image);
    
    return albumItem;
}

for (const imageSrc of album.images) {
    fragment.append(createAlbumItem(imageSrc));
}

imagesList.append(fragment);

→ Ссылка