アイコン探し

# アプリで使うアイコンを探したい

アプリ内で読み込みや保存とかに使うよくあるアイコン画像。
ＭＳ様とかがＳＤＫで公開しているものとかは、数百以上ありファイル別のディレクトリに分かれているのですがこれを一個ずつ見ていくのは大変すぎる。
そこで、アイコン一覧を作るスクリプトを作ってみた。

## 使い方

1. 以下のコマンドを実行
```shell
python icon_list.py /path/to/icon/dir
```

2. /path/to/icon/dir/icons.htmlをブラウザで開く
![browser.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322199/5d390405-cfb2-467e-9d6f-6d5b7ccd04f7.png)

ブラウザで出来る事
- 閲覧している画像サイズをスライダで調整
- 画像ファイル名でフィルタ(ありそうなファイル名を入れる。保存用アイコンだったらsave等)
- 画像をクリックすると、クリップボードにその画像のファイルパスがコピーされる

一度icons.htmlを作ってしまえば、それ以降はブラウザで開くだけでお手軽です。

## ファイル構成

場所は何処でも良いので、icon_list.pyとtemplate.htmlを同じディレクトリに置く

配置イメージ
./icon_list.py
./template.html

```icon_list.py
import os
from pathlib import Path
import glob
import sys

def create_image_gallery_html(directory_path, output_file):
    """
    画像の一覧のhtmlを作成する
    :param directory_path: 画像のあるディレクトリパス
    :param output_file: 出力ファイル名(*.html)
    """
    # PNG画像ファイルを検索
    png_files = glob.glob(os.path.join(directory_path, "**/*.png"), recursive=True)
   
    # ギャラリーアイテムのHTML生成
    gallery_items = ""
    for image_path in png_files:
        relative_path = os.path.relpath(image_path, directory_path)
        filename = os.path.basename(image_path)
        gallery_items += f"""
            <div class="item">
                <div class="image">
                    <img src="{relative_path}" alt="{filename}" title="{relative_path}" loading="lazy">
                </div>
                <div class="caption">{filename}</div>
            </div>
        """
   
    # 最終的なHTMLの生成
    # HTMLテンプレートファイルを読み込んで全内容を取得
    with open("template.html", "r", encoding="utf-8") as file:
        html_template = file.read()  # ファイル全体を文字列として読み込む

    html_content = html_template.replace("{0}", gallery_items)
   
    # HTMLファイルの保存
    output_path = os.path.join(directory_path, output_file)
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(html_content)
   
    print(f"Gallery has been created at: {output_path}")
    return output_path

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python script.py <directory>")
        sys.exit(1)
    directory = sys.argv[1]
    output_html_file = 'icons.html'
    create_image_gallery_html(directory, output_html_file)
```


```template.html
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Image Gallery</title>
	<style>
		body {
			margin: 0;
			padding: 20px;
			font-family: Arial, sans-serif;
		}
		.slider {
			position: fixed;
			top: 20px;
			right: 20px;
			background: rgba(255, 255, 255, 0.9);
			padding: 10px;
			border-radius: 5px;
			box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
			z-index: 1000;
			width: 200px;
		}
		.gallery {
			display: grid;
			grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
			gap: 20px;
			padding-top: 150px;
		}
		.item {
			width: 100%;
			background: #f5f5f5;
			padding: 10px;
			box-sizing: border-box;
			border-radius: 5px;
			display: flex;
			flex-direction: column;
			cursor: pointer;
			transition: background-color 0.2s;
		}
		.item:hover {
			background: #e0e0e0;
		}
		.item.copied {
			background: #d4f7d4;
		}
		.image {
			position: relative;
			width: 100%;
			padding-top: 75%; /* 4:3 aspect ratio */
			overflow: hidden;
		}
		.item img {
			position: absolute;
			top: 0;
			left: 0;
			width: 100%;
			height: 100%;
			object-fit: contain;
			object-position: center;
		}
		.caption {
			margin-top: 5px;
			font-size: 0.9em;
			text-align: center;
			word-break: break-all;
		}
		.filter {
			width: 100%;
			padding: 5px;
			margin-top: 10px;
			border: 1px solid #ccc;
			border-radius: 3px;
		}
		.hidden {
			display: none;
		}
		.copy-message {
			position: fixed;
			bottom: 20px;
			left: 50%;
			transform: translateX(-50%);
			background: rgba(0, 0, 0, 0.7);
			color: white;
			padding: 10px 20px;
			border-radius: 4px;
			opacity: 0;
			transition: opacity 0.3s;
			z-index: 1001;
		}
		.copy-message.show {
			opacity: 1;
		}
	</style>
</head>
<body>
<div class="slider">
	<label for="size-slider">画像サイズ調整:</label><br>
	<input type="range" id="size-slider" min="100" max="500" value="200">
	<br>
	<label for="filter-input">画像フィルター:</label><br>
	<input type="text" id="filter-input" class="filter-input" placeholder="画像名を入力...">
</div>
<div class="gallery" id="image-gallery">
{0}
</div>
<div class="copy-message" id="copy-message">URLをコピーしました</div>
<script>
    const slider = document.getElementById('size-slider');
    const gallery = document.getElementById('image-gallery');
    const filterInput = document.getElementById('filter-input');
    const copyMessage = document.getElementById('copy-message');

    slider.addEventListener('input', function () {
        const value = this.value;
        gallery.style.gridTemplateColumns = `repeat(auto-fill, minmax(${value}px, 1fr))`;
    });

    // フィルター機能の実装
    filterInput.addEventListener('input', function () {
        const filterValue = this.value.toLowerCase();
        const galleryItems = document.querySelectorAll('.item');
        galleryItems.forEach(item => {
            const img = item.querySelector('img');
            const altText = img.getAttribute('alt').toLowerCase();
            if (altText.includes(filterValue)) {
                item.classList.remove('hidden');
            } else {
                item.classList.add('hidden');
            }
        });
    });

    // クリップボードコピー機能
    function setupCopyFunction() {
        const items = document.querySelectorAll('.item');
        items.forEach(item => {
            item.addEventListener('click', function() {
                const img = this.querySelector('img');
                const imgSrc = img.getAttribute('src');

                // クリップボードにコピー
                navigator.clipboard.writeText(imgSrc)
                    .then(() => {
                        // コピー成功時の視覚的フィードバック
                        this.classList.add('copied');
                        setTimeout(() => {
                            this.classList.remove('copied');
                        }, 1000);

                        // コピーメッセージを表示
                        copyMessage.textContent = `${imgSrc} をコピーしました`;
                        copyMessage.classList.add('show');
                        setTimeout(() => {
                            copyMessage.classList.remove('show');
                        }, 2000);
                    })
                    .catch(err => {
                        console.error('クリップボードへのコピーに失敗しました:', err);
                        alert('クリップボードへのコピーに失敗しました。');
                    });
            });
        });
    }

    // 初期設定
    setupCopyFunction();

    function addNewGalleryItem(imageSrc, altText) {
        const newItem = document.createElement('div');
        newItem.className = 'item';

        newItem.innerHTML = `
            <div class="image">
                <img src="${imageSrc}" alt="${altText}" title="${imageSrc}" loading="lazy">
            </div>
            <div class="caption">${altText}</div>
        `;

        gallery.appendChild(newItem);

        setupCopyFunction();
    }
</script>
</body>
</html>
```