Code Monkey home page Code Monkey logo

photo-gallery's Introduction

PhotoGallery

A minimal photo gallery mimicking Google Photos' style and intended for use with static websites.

Preview of the app

Demo (in production!)

axel.leroy.sh/photography

Blog article

axel.leroy.sh/blog/the-making-of-photo-gallery

Goals and functionalities

When working on this project, my goals were to make this photo gallery

  • Embeddable in a static website hosted on AWS (S3 & Cloudfront).
  • Functionaly minimal: it should just display albums and pictures with relevant EXIF data.
  • (relatively) Lightweight with minimal dependancies, with notably no CSS framework involved.
  • Efficient, with small thumbnails and HTTP requests caching.
  • Look like Google Photo's album grid.

What are not goals of this project

  • Being user friendly: there's no GUI to manage albums and pictures.
  • Handle everyone's use-cases. My main goal was to make a custom solution for my own portfolio, not to anwser a broad userbase's needs.

Using PhotoGallery

How it works

PhotoGallery fetches all of its data from static JSON files meant to be stored allongside the app or pictures.

There are two types of JSON files:

  • Album List: describes the albums shown by the app
[
    {
        id: "string",
        name: "string",
        thumbnail: {
            default : {
                url: "string",
                height: 300, // in pixels
                width: 400 // in pixels
            },
            webp: [
                {
                    url: "string",
                    height: 300, // in pixels
                    width: 400 // in pixels
                },
                {
                    url: "string",
                    height: 600, // in pixels
                    width: 800 // in pixels
                }
            ],
            jpeg: [
                {
                    url: "string",
                    height: 300, // in pixels
                    width: 400 // in pixels
                },
                {
                    url: "string",
                    height: 600, // in pixels
                    width: 800 // in pixels
                }
            ]
        }
    },
    {
        id: "string",
        name: "string",
        thumbnail: {
            ...
        }
    }
]
  • Album Content: describes an album and the pictures it contains
{
   id: "string",
   name: "string",
   pictures: [
     {
       id: "string",
       thumbnail: {
          default : {
              url: "string",
              height: 300, // in pixels
              width: 400 // in pixels
          },
          webp: [
              {
                  url: "string",
                  height: 300, // in pixels
                  width: 400 // in pixels
              },
              {
                  url: "string",
                  height: 600, // in pixels
                  width: 800 // in pixels
              }
          ],
          jpeg: [
              {
                  url: "string",
                  height: 300, // in pixels
                  width: 400 // in pixels
              },
              {
                  url: "string",
                  height: 600, // in pixels
                  width: 800 // in pixels
              }
          ]
       },
       fullsize: {
          default : {
               url: "string",
               height: 300, // in pixels
               width: 400 // in pixels
          },
          webp: [
           {
                url: "string",
                height: 300, // in pixels
                width: 400 // in pixels
            },
            {
                url: "string",
                height: 600, // in pixels
                width: 800 // in pixels
            }
           ],
           jpeg: [
            {
                url: "string",
                height: 300, // in pixels
                width: 400 // in pixels
            },
            {
                url: "string",
                height: 600, // in pixels
                width: 800 // in pixels
            }
           ]
       },
       exif: {
         'Tag': "value" 
       }   
     },
     {
       id: "string",
       thumbnail: {
         ...
       },
       fullsize: {
         ...
       }
     }
   ]
}

These JSONs are mapped to TypeScript classes you can find in src/app/types and are generated by the Python script in scripts/.

Speaking of Python script…

Uploading pictures and generating JSON files

In order to easily upload pictures and create the JSONs, I created a Python script taking care of everything.

Given a folder containing pictures you want to add to an album, it

  • parses the relevant EXIF data from each picture
  • generates thumbnails and different sizes of the pictures
  • generates a JSON file describing the album's content (see How it Works)
  • uploads the JSON, pictures and the thumbnails to the given S3 bucket (all under s3://bucket-name/albumname/)
  • updates the albums list JSON with the new album on top

It is located in scripts/ and requires

  • Python 3.6+
  • libjpeg and libwebp installed
  • a few dependencies you have to install using pip install -r requirements.txt
  • and to set up your AWS credentials

Finally, to list its parameters, just type python add-album.py -h.

Once it had run, take the created/updated albums.json and upload it wherever you want (in a bucket, on your website allongside the gallery, etc.)

Note to users of previous version: Since the album structure has changed to handle different sizes and WebP, I made a migration script named migrate-albums.py to migrate existing albums.

Building the Angular app

First, install everything using npm install. Then modify src/environments/environment.ts or copy it to src/environments/environment.prod.ts and make the modifications you need (refer to AppConfig.ts).

The most important attributes to set are

  • albumListUrl: the URL to the albums list JSON
  • albumBaseUrl: the URL to the folder containing the albums to display
  • albumFileNameUrl: Name of the album JSON file, with file extension.

Set the last two variables so that the app fetches the JSON at albumBaseUrl + albumId + albumFileNameUrl.

For example, given this configuration

{
  albumListUrl: 'https://my-wonderful-website.com/assets/albums.json',
  albumBaseUrl: 'https://my-bucket.s3.eu-central-1.amazonaws.com/',
  albumFileNameUrl: '/album.json'
}

The app will fetch the albums list at https://my-wonderful-website.com/assets/albums.json and for an album with the ID fantastic-album will fetch its content at https://my-bucket.s3.eu-central-1.amazonaws.com/fantastic-album/album.json.

Once everything is all set, build the app

npm build [--prod] --baseHref=/base-folder [--deployUrl=/assets/]

Then take everything in /dist/photo-gallery and deploy anywhere you want !

Note: make sure the assets folder containing the icons is at the root of you website. Edit the code if you want the icons to be stored somewhere else.

Making it yours: customize its CSS

Here are some CSS styles to apply to the page containing the app in order to customize its look to your liking:

Changing the typography

Style h1 and .thumbnail-legend to change the look of the page title and thumbnails' legend. You can also style the links using the a and a:hover selectors.

Grid spacing

To widen or tighten the gap between thumbnails, change .thumbnail-list-item's margin properties.

Placeholder color

To change the color of loading pictures, change the .thumbnail-bg's background-color.

Loader style and color

Use border properties to customize the style and color of the .loader component. You can find multiple examples here.

Make the last line of thumbnails fill the entire width of the page

Just set the following:

.thumbnail-list-end {
  flex-grow: 0 !important;
}

photo-gallery's People

Contributors

axeleroy avatar dependabot[bot] avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.