Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,39 @@
# github.io
# github.io

## 🎨 インタラクティブカラーパレットジェネレーター

JavaScriptを使用して作成された、美しいカラーパレットを生成できるWebアプリケーションです。

### 主な機能

- 🎲 **ランダムカラー生成** - ボタンクリックまたはスペースキーで新しいパレットを生成
- 🔒 **カラーロック機能** - お気に入りの色を固定して他の色だけを再生成
- 💾 **パレット保存** - LocalStorageを使用して最大20個のパレットを保存
- 📋 **クリップボードコピー** - カラーコードをクリックでコピー
- 📱 **レスポンシブデザイン** - デスクトップとモバイルに対応
- 🌐 **日本語UI** - 完全日本語対応のインターフェース

### 使い方

1. ページを開くと、ランダムなカラーパレットが表示されます
2. 「新しいパレットを生成」ボタンをクリックするか、スペースキーを押して新しいパレットを生成
3. 🔓 アイコンをクリックして色をロックできます(ロックされた色は🔒アイコンになります)
4. 気に入ったパレットは「お気に入りに保存」ボタンで保存できます
5. カラーコードをクリックするとクリップボードにコピーされます

### 技術スタック

- HTML5
- CSS3 (Grid, Flexbox, Animations)
- Vanilla JavaScript (ES6+)
- LocalStorage API
- Clipboard API

### ファイル構成

```
├── index.html # メインHTML
├── app.js # JavaScriptアプリケーションロジック
├── style.css # スタイリング
└── README.md # このファイル
```
230 changes: 230 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
// カラーパレットジェネレーター
class ColorPaletteGenerator {
constructor() {
this.paletteSize = 5;
this.currentPalette = [];
this.lockedColors = new Set();
this.savedPalettes = this.loadSavedPalettes();

this.init();
}

init() {
this.generatePalette();
this.renderPalette();
this.renderSavedPalettes();
this.setupEventListeners();
}

setupEventListeners() {
// 生成ボタン
document.getElementById('generateBtn').addEventListener('click', () => {
this.generatePalette();
this.renderPalette();
});

// 保存ボタン
document.getElementById('saveBtn').addEventListener('click', () => {
this.savePalette();
});

// スペースキーで生成
document.addEventListener('keydown', (e) => {
if (e.code === 'Space' && e.target.tagName !== 'BUTTON') {
e.preventDefault();
this.generatePalette();
this.renderPalette();
}
});
}

// ランダムな色を生成
generateRandomColor() {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
return { r, g, b };
}

// RGBをHEXに変換
rgbToHex(r, g, b) {
return '#' + [r, g, b].map(x => {
const hex = x.toString(16);
return hex.length === 1 ? '0' + hex : hex;
}).join('').toUpperCase();
}

// パレットを生成
generatePalette() {
const newPalette = [];

for (let i = 0; i < this.paletteSize; i++) {
if (this.lockedColors.has(i) && this.currentPalette[i]) {
newPalette.push(this.currentPalette[i]);
} else {
const color = this.generateRandomColor();
newPalette.push({
...color,
hex: this.rgbToHex(color.r, color.g, color.b)
});
}
}

this.currentPalette = newPalette;
}

// パレットを描画
renderPalette() {
const paletteElement = document.getElementById('palette');
paletteElement.innerHTML = '';

this.currentPalette.forEach((color, index) => {
const colorBox = document.createElement('div');
colorBox.className = 'color-box';

const isLocked = this.lockedColors.has(index);
const lockIcon = isLocked ? '🔒' : '🔓';

colorBox.innerHTML = `
<div class="color-display" style="background-color: ${color.hex}">
<button class="lock-btn ${isLocked ? 'locked' : ''}" data-index="${index}">
${lockIcon}
</button>
</div>
<div class="color-info">
<div class="color-code">${color.hex}</div>
<div class="color-rgb">RGB(${color.r}, ${color.g}, ${color.b})</div>
</div>
`;

// カラーコードをクリックでコピー
colorBox.addEventListener('click', (e) => {
if (!e.target.classList.contains('lock-btn')) {
this.copyToClipboard(color.hex);
}
});

// ロックボタン
const lockBtn = colorBox.querySelector('.lock-btn');
lockBtn.addEventListener('click', (e) => {
e.stopPropagation();
this.toggleLock(index);
});

paletteElement.appendChild(colorBox);
});
}

// ロックを切り替え
toggleLock(index) {
if (this.lockedColors.has(index)) {
this.lockedColors.delete(index);
} else {
this.lockedColors.add(index);
}
this.renderPalette();
}

// クリップボードにコピー
copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
this.showNotification(`${text} をコピーしました!`);
}).catch(err => {
console.error('コピーに失敗しました:', err);
});
}

// 通知を表示
showNotification(message) {
let notification = document.querySelector('.copy-notification');
if (!notification) {
notification = document.createElement('div');
notification.className = 'copy-notification';
document.body.appendChild(notification);
}

notification.textContent = message;
notification.classList.add('show');

setTimeout(() => {
notification.classList.remove('show');
}, 2000);
}

// パレットを保存
savePalette() {
const palette = {
id: Date.now(),
colors: this.currentPalette,
date: new Date().toLocaleString('ja-JP')
};

this.savedPalettes.unshift(palette);

// 最大20個まで保存
if (this.savedPalettes.length > 20) {
this.savedPalettes = this.savedPalettes.slice(0, 20);
}

this.savePalettesToStorage();
this.renderSavedPalettes();
this.showNotification('パレットを保存しました!');
}

// ローカルストレージに保存
savePalettesToStorage() {
localStorage.setItem('colorPalettes', JSON.stringify(this.savedPalettes));
}

// ローカルストレージから読み込み
loadSavedPalettes() {
const saved = localStorage.getItem('colorPalettes');
return saved ? JSON.parse(saved) : [];
}

// 保存されたパレットを描画
renderSavedPalettes() {
const savedList = document.getElementById('savedList');

if (this.savedPalettes.length === 0) {
savedList.innerHTML = '<p style="text-align: center; color: #999;">まだ保存されたパレットはありません</p>';
return;
}

savedList.innerHTML = '';

this.savedPalettes.forEach(palette => {
const paletteDiv = document.createElement('div');
paletteDiv.className = 'saved-palette';

const colorsHtml = palette.colors.map(color =>
`<div class="saved-color" style="background-color: ${color.hex}" title="${color.hex}"></div>`
).join('');

paletteDiv.innerHTML = `
<div class="saved-colors">${colorsHtml}</div>
<div class="saved-info">${palette.date}</div>
`;

paletteDiv.addEventListener('click', () => {
this.loadPalette(palette);
});

savedList.appendChild(paletteDiv);
});
}

// 保存されたパレットを読み込み
loadPalette(palette) {
this.currentPalette = palette.colors;
this.lockedColors.clear();
this.renderPalette();
this.showNotification('パレットを読み込みました!');
window.scrollTo({ top: 0, behavior: 'smooth' });
}
}

// アプリケーションを初期化
document.addEventListener('DOMContentLoaded', () => {
new ColorPaletteGenerator();
});
35 changes: 35 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>インタラクティブカラーパレットジェネレーター</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<header>
<h1>🎨 カラーパレットジェネレーター</h1>
<p>スペースキーを押すか、ボタンをクリックして新しいパレットを生成してください</p>
</header>

<div id="palette" class="palette">
<!-- カラーボックスはJavaScriptで生成されます -->
</div>

<div class="controls">
<button id="generateBtn" class="btn-primary">新しいパレットを生成</button>
<button id="saveBtn" class="btn-secondary">お気に入りに保存</button>
</div>

<div id="savedPalettes" class="saved-palettes">
<h2>保存されたパレット</h2>
<div id="savedList" class="saved-list">
<!-- 保存されたパレットがここに表示されます -->
</div>
</div>
</div>

<script src="app.js"></script>
</body>
</html>
Loading
Loading