PHPとJQueryとLiteboxで画像ライブラリーをサクッと作る

ローカルで整理したままの階層で画像ライブラリーを作ってみた

SNSに画像を貼るとき、フォルダーで整理していると便利ですよね。
でも、SNSの画像アップロード画面ではフォルダー構造が反映されないので、アップロードした画像が増えてくると、目的の画像を探すのが大変です。
そこで、ローカルで整理したフォルダー構造をそのまま反映した画像ライブラリーを作ってみました。

画像をクリックすると、Lightboxで拡大表示されます。
画像の下に表示されているURLをコピーして、ブログの画像挿入画面に貼り付ければ、簡単に画像を挿入できます。

画像のURLは、https://*********.jp/blogger/img/以下に、ローカルのフォルダー構造が反映されています。
例えば、img/16x9_X/1280x720/imageDisplay.PNGのようになります。

画像のURLをコピーするには、Copy URLボタンをクリックしてください。
クリップボードにコピーされます。

image_display.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Image Display with Folder Tree</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Playball&family=Zen+Antique+Soft&display=swap" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.4/css/lightbox.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.4/js/lightbox.min.js" defer type="text/javascript"></script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

<style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            background-color: #222;
            color: #eee;
        }

        .playball-regular {
            font-family: "Playball", cursive;
            font-weight: 400;
            font-style: normal;
        }

        h1 {
            text-align: center;
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 10px;
            background-color: #000;
        }

        h3 {
            margin: 0;
            padding: 5px 0;
        }

        .container {
            display: flex;
            width: 100%;
            min-height: calc(100vh - 80px);
        }

        .sidebar {
            width: 25%;
            padding: 10px;
            overflow-y: auto;
            border-right: 1px solid #ccc;
        }

        .content {
            width: 75%;
            padding: 10px;
        }

        .current-folder {
            text-align: center;
            font-weight: bold;
            font-style: italic;
            margin-bottom: 15px;
            color: #eee;
        }

        .tree ul {
            list-style: none;
            padding-left: 20px;
        }

        .tree li {
            cursor: pointer;
            padding: 5px;
        }

        .tree li:hover {
            background: #333;
        }

        .tree li::before {
            content: '📁';
            margin-right: 5px;
        }

        .image-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
            gap: 10px;
        }

        .image-item:hover {
            background-color: #444;
            color: #fff;
            font-weight: bold;
        }

        .image-item {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 7px 3px 0px 3px;
            text-align: center;
        }

        .image-item p {
            margin: 0;
            font-size: 14px;
        }

        .image-item img {
            margin: 0 auto;
            padding: 0 auto;
            max-width: 100px;
        }

        .image-item input {
            width: 95%;
            font-size: 12px;
            margin-top: 0px;
        }

        .copy-btn {
            padding: 5px 15px;
            font-size: 12px;
            cursor: pointer;
        }

        @media (max-width: 768px) {
            .container {
                flex-direction: column;
            }

            .sidebar,
            .content {
                width: 100%;
            }
        }

        strong.hovers:hover {
            color: #f00;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <h1 class="playball-regular">Image Display</h1>
    <div class="container">
        <div class="sidebar">
            <h3>Folders</h3>
            <div class="tree">
                <?php
                $hostname = $_SERVER['HTTP_HOST'];
                ///////////////////////////////ローカル・本番環境切り替え ゴニョゴニョ
                $baseUrl = ($hostname != 'ローカルホスト名') ? '.' : '******************'; // ホスト名に置き換えてください
                if ($hostname != 'ローカルホスト名') { // ローカルホスト名に置き換えてください
                    echo "<p style='color:#f88; font-weight:bold;'>ローカル環境</p>";
                }
                ///////////////////////////////
                echo $hostname;
                function listFolders($dir, $base = '')
                {
                    $files = scandir($dir);
                    echo "<ul>";
                    foreach ($files as $file) {
                        if ($file[0] === '.' || $file === 'index.php') continue;
                        $path = $dir . '/' . $file;
                        $relPath = $base ? "$base/$file" : $file;
                        if (is_dir($path)) {
                            echo "<li data-path='$relPath'><strong class='hovers'>$file/</strong>";
                            listFolders($path, $relPath);
                            echo "</li>";
                        }
                    }
                    echo "</ul>";
                }
                listFolders("./img");
                ?>
            </div>
        </div>
        <div class="content">
            <h3>Images</h3>
            <div class="current-folder" id="current-folder">Current Folder: /</div>
            <div class="image-grid" id="image-grid"></div>
        </div>
    </div>
    <script>
        $(document).ready(function() {
            const baseUrl = '<?php echo $baseUrl; ?>';
            loadImages('');
            $('.tree li').click(function(e) {
                e.stopPropagation();
                const path = $(this).data('path') || '';
                loadImages(path);
                $('.tree li').removeClass('selected');
                $(this).addClass('selected');
                $('#current-folder').text('Current Folder: ' + (path || '/'));
            });

            function loadImages(path) {
                $.ajax({
                    url: baseUrl + '/fetch_images.php',
                    data: {
                        path: path
                    },
                    success: function(data) {
                        $('#image-grid').html(data);
                    },
                    error: function(xhr, status, error) {
                        $('#image-grid').html(`<p>Error loading images: ${xhr.status} ${error}</p>`);
                    }
                });
            }
            $(document).on('click', '.copy-btn', function() {
                const url = $(this).prev('input').val();
                navigator.clipboard.writeText(url).then(() => {
                    alert('URL copied to clipboard!');
                });
            });
        });
    </script>
</body>
</html>

fetch_images.php

<?php
$baseDir = './img';
$path = isset($_GET['path']) ? $_GET['path'] : '';
$dir = rtrim($baseDir . '/' . $path, '/');
$hostname = $_SERVER['HTTP_HOST'];
$https = "https://";
//////////////////////////////ローカル・本番環境切り替え ゴニョゴニョ
// ローカル環境用設定
if ($hostname != '*******************') { // ホスト名に置き換えてください
    echo "<p style='color:#f88; font-weight:bold;'>ローカル環境</p>";
    $hostname = 'localhost:8000' . '*******************'; //サーバールートパスに置き換えてください
    $https = "http://";
}
///////////////////////////////
$output = '';
if (is_dir($dir)) {
    $files = scandir($dir);
    foreach ($files as $file) {
        if ($file[0] === '.') continue;
        $filePath = $dir . '/' . $file;
        $relPath = $path ? "$path/$file" : $file;
        if (!is_dir($filePath)) {
            $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
            if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif'])) {
                $ext = substr($file, strrpos($file, '.') + 1); // 拡張子取得
                $size = getimagesize($filePath);
                $url = $https . $hostname . '/blogger/img/' . $relPath;
                $output .= "<div class='image-item'>";
                $output .= "<a href='$url' data-lightbox='group'><img src='$url' alt='$file'></a>";
                $output .= "<p>({$size[0]}x{$size[1]}) $ext</p>";
                $output .= "<input type='text' value='$url' readonly>";
                $output .= "<button class='copy-btn'>Copy URL</button>";
                $output .= "</div>";
            }
        }
    }
}
echo $output ?: '<p>No images found.</p>';

備考

ローカル環境とサーバー環境両方動かすためにゴニョゴニョやってます。w
ホスト名とサーバールートパスをそれぞれ書き換えてください。必要ない場合ばざっくり削って良いです。
ローカル環境で動かす場合は、PHPのビルトインサーバーを使うと簡単です。
ターミナルで、php -S localhost:8000とやると、http://localhost:8000でアクセスできます。
PHPのインストールが必要です。

ローカルとサーバー名は逆の方が良かったんだけどローカル環境作りながらやってたのでややこしくなりましたwww
ローカル環境で動かす場合は、fetch_images.phpの$hostnameと$httpsの部分をコメントアウトして、$hostnameにlocalhost:8000などを直接書き込んでください。
サーバー環境で動かす場合は、$hostnameと$httpsの部分を有効にしてください。

Lightbox2を使ってます。
Lightbox2 - Simple, unobtrusive script used to overlay images on top of the current page. It's a snap to setup and works on all modern browsers.

Lightbox2のCSSとJSをCDNで読み込んでいます。

Lightbox2の使い方は、Lightbox2のサイトを参照してください。


参考にしたサイト

コメント

人気の投稿

Bloggerでは“コピー用アイコン”が出せないの?

Googleドライブの共有で浮気がバレるかもしれない・・・www

ブックマークレット