<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>GameStore Ultra - Upload & Persist Data</title>
<meta name="description" content="高度なインタラクションと洗練されたデザイン、アップロードデータの保持機能を実現したゲームストアサイト。">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
/*────────────────────────────
グローバルリセット&変数設定
────────────────────────────*/
:root {
--primary: #ff6600;
--accent: #e55a00;
--secondary: #222;
--light: #fff;
--dark: #333;
--text: #333;
--shadow: 0 2px 8px rgba(0,0,0,0.15);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { font-family: 'Helvetica Neue', Arial, sans-serif; background: #f8f8f8; color: var(--text); }
a { text-decoration: none; color: inherit; }
img { display: block; max-width: 100%; height: auto; }
/*────────────────────────────
ヘッダー&ナビゲーション
────────────────────────────*/
header {
background: var(--secondary);
color: var(--light);
padding: 10px 20px;
position: sticky;
top: 0;
z-index: 1000;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: var(--shadow);
}
.logo { display: flex; align-items: center; gap: 10px; }
.logo img { width: 40px; height: 40px; }
.logo h1 { font-size: 24px; }
nav { background: var(--dark); }
.nav-container {
max-width: 1200px;
margin: auto;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
}
.nav-menu { list-style: none; display: flex; gap: 20px; }
.nav-menu li { position: relative; }
.nav-menu li a {
color: var(--light);
padding: 8px 10px;
transition: background 0.3s;
}
.nav-menu li a:hover { background: #444; }
/* ドロップダウン */
.dropdown {
position: absolute;
top: 100%;
left: 0;
background: var(--dark);
display: none;
flex-direction: column;
min-width: 150px;
}
.dropdown li a { padding: 8px 10px; }
.nav-menu li:hover .dropdown { display: flex; }
/* アップロードリンク(管理者向け) */
.nav-menu li.upload-link { margin-left: auto; }
/* ハンバーガーメニュー(モバイル) */
.hamburger {
display: none;
flex-direction: column;
gap: 4px;
cursor: pointer;
}
.hamburger span { width: 25px; height: 3px; background: var(--light); }
@media (max-width: 768px) {
.nav-menu { display: none; flex-direction: column; width: 100%; }
.nav-menu.active { display: flex; }
.hamburger { display: flex; }
.nav-container { flex-direction: column; align-items: flex-start; }
}
.search-container { position: relative; }
.search-container input[type="text"] {
padding: 6px 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.search-container button {
position: absolute;
right: 0;
top: 0;
bottom: 0;
background: var(--primary);
border: none;
padding: 6px 10px;
border-radius: 0 4px 4px 0;
color: var(--light);
cursor: pointer;
}
/*────────────────────────────
ヒーロースライダー
────────────────────────────*/
.hero-slider {
position: relative;
overflow: hidden;
height: 600px;
}
.hero-slide {
position: absolute;
top: 0; left: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
opacity: 0;
transition: opacity 1s ease;
display: flex;
align-items: center;
justify-content: center;
}
.hero-slide.active { opacity: 1; position: relative; }
.hero-content {
background: rgba(0, 0, 0, 0.6);
padding: 20px 30px;
border-radius: 8px;
text-align: center;
color: var(--light);
}
.hero-content h2 { font-size: 48px; margin-bottom: 15px; }
.hero-content p { font-size: 20px; margin-bottom: 20px; }
.hero-content .btn {
background: var(--primary);
padding: 12px 24px;
border-radius: 4px;
transition: background 0.3s;
}
.hero-content .btn:hover { background: var(--accent); }
.hero-controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 8px;
}
.hero-control {
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--light);
opacity: 0.5;
cursor: pointer;
}
.hero-control.active { opacity: 1; }
/*────────────────────────────
スクロール時フェードインアニメーション
────────────────────────────*/
.fade-in {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.6s ease-out, transform 0.6s ease-out;
}
.fade-in.visible { opacity: 1; transform: none; }
/*────────────────────────────
セクション共通スタイル
────────────────────────────*/
section {
padding: 60px 20px;
max-width: 1200px;
margin: auto;
}
.section-title {
font-size: 32px;
margin-bottom: 20px;
border-left: 5px solid var(--primary);
padding-left: 10px;
}
.section-description {
font-size: 18px;
margin-bottom: 30px;
color: #666;
}
/*────────────────────────────
ゲームカードグリッド
────────────────────────────*/
.game-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
}
.game-card {
background: var(--light);
border-radius: 8px;
box-shadow: var(--shadow);
overflow: hidden;
cursor: pointer;
position: relative;
transition: transform 0.3s;
}
.game-card:hover { transform: translateY(-5px); }
.game-card img {
width: 100%;
height: 180px;
object-fit: cover;
}
.game-card-content { padding: 15px; }
.game-card-content h3 { font-size: 22px; margin-bottom: 10px; }
.game-card-content p { font-size: 16px; color: #666; margin-bottom: 10px; }
.game-card-content .price { font-size: 20px; color: var(--primary); }
.card-overlay {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.3);
opacity: 0;
transition: opacity 0.3s;
}
.game-card:hover .card-overlay { opacity: 1; }
/*────────────────────────────
カテゴリセクション
────────────────────────────*/
.categories {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 20px;
}
.category-card {
position: relative;
border-radius: 8px;
overflow: hidden;
cursor: pointer;
}
.category-card img {
width: 100%;
height: 150px;
object-fit: cover;
filter: brightness(70%);
transition: filter 0.3s;
}
.category-card:hover img { filter: brightness(100%); }
.category-card span {
position: absolute;
bottom: 10px;
left: 10px;
background: rgba(0,0,0,0.5);
color: var(--light);
padding: 8px 12px;
border-radius: 4px;
font-size: 18px;
}
/*────────────────────────────
ユーザーレビュー・スライダー
────────────────────────────*/
.reviews-slider {
position: relative;
overflow: hidden;
padding: 20px 0;
}
.reviews-track {
display: flex;
gap: 20px;
transition: transform 0.5s ease-in-out;
}
.review-card {
background: var(--light);
border-radius: 8px;
box-shadow: var(--shadow);
padding: 20px;
min-width: 320px;
}
.review-card h4 { font-size: 20px; margin-bottom: 10px; }
.review-card .rating { margin-bottom: 10px; }
.review-card .rating span { color: gold; font-size: 22px; }
.review-card p { font-size: 16px; color: #444; }
/*────────────────────────────
ブログセクション
────────────────────────────*/
.blog-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
.blog-card {
background: var(--light);
border-radius: 8px;
box-shadow: var(--shadow);
overflow: hidden;
}
.blog-card img {
width: 100%;
height: 200px;
object-fit: cover;
}
.blog-card-content { padding: 15px; }
.blog-card-content h3 { font-size: 22px; margin-bottom: 10px; }
.blog-card-content p { font-size: 16px; color: #666; margin-bottom: 10px; }
.blog-card-content .btn {
background: var(--primary);
padding: 8px 16px;
border-radius: 4px;
transition: background 0.3s;
font-size: 16px;
}
.blog-card-content .btn:hover { background: var(--accent); }
/*────────────────────────────
モーダル(商品詳細、ログイン、登録、カート、アップロード)
────────────────────────────*/
.modal-overlay {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.6);
display: none;
align-items: center;
justify-content: center;
z-index: 2000;
}
.modal-overlay.active { display: flex; }
.modal {
background: var(--light);
max-width: 600px;
width: 90%;
border-radius: 8px;
overflow: hidden;
animation: modalFade 0.3s;
position: relative;
}
@keyframes modalFade {
from { opacity: 0; transform: translateY(-20px); }
to { opacity: 1; transform: translateY(0); }
}
.modal-header, .modal-footer { padding: 15px; background: var(--dark); color: var(--light); }
.modal-body { padding: 20px; }
.modal-close {
position: absolute;
top: 15px;
right: 15px;
font-size: 24px;
cursor: pointer;
color: var(--light);
}
/*────────────────────────────
Back-to-Top ボタン
────────────────────────────*/
#backToTop {
position: fixed;
bottom: 40px;
right: 40px;
background: var(--primary);
color: var(--light);
padding: 12px;
border-radius: 50%;
display: none;
cursor: pointer;
box-shadow: var(--shadow);
transition: background 0.3s;
z-index: 1500;
}
#backToTop:hover { background: var(--accent); }
/*────────────────────────────
フィルターサイドバー(デスクトップ)
────────────────────────────*/
.filter-sidebar {
position: fixed;
top: 100px;
left: 20px;
width: 250px;
background: var(--light);
border: 1px solid #ccc;
border-radius: 8px;
padding: 20px;
box-shadow: var(--shadow);
z-index: 1200;
}
.filter-sidebar h3 { font-size: 20px; margin-bottom: 15px; }
.filter-sidebar label { display: block; margin-bottom: 8px; font-size: 16px; }
.filter-sidebar input, .filter-sidebar select {
width: 100%;
padding: 6px 8px;
margin-bottom: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
.filter-sidebar button {
width: 100%;
padding: 10px;
background: var(--primary);
border: none;
color: var(--light);
border-radius: 4px;
font-size: 16px;
transition: background 0.3s;
cursor: pointer;
}
.filter-sidebar button:hover { background: var(--accent); }
@media (max-width: 1024px) { .filter-sidebar { display: none; } }
</style>
</head>
<body>
<!--────────────────────────────
ヘッダー
────────────────────────────-->
<header>
<div class="logo">
<img src="images/logo.png" alt="GameStore Logo" loading="lazy">
<h1>GameStore Ultra</h1>
</div>
<div class="hamburger" id="hamburger">
<span></span>
<span></span>
<span></span>
</div>
</header>
<!--────────────────────────────
ナビゲーション
────────────────────────────-->
<nav>
<div class="nav-container">
<ul class="nav-menu" id="navMenu">
<li><a href="#">ホーム</a></li>
<li>
<a href="#">新作</a>
<ul class="dropdown">
<li><a href="#">今週の新作</a></li>
<li><a href="#">今月の新作</a></li>
</ul>
</li>
<li>
<a href="#">人気タイトル</a>
<ul class="dropdown">
<li><a href="#">ランキング</a></li>
<li><a href="#">レビュー</a></li>
</ul>
</li>
<li><a href="#">セール</a></li>
<li><a href="#">ブログ</a></li>
<li class="upload-link"><a href="#" id="uploadLink">アップロード</a></li>
</ul>
<div class="search-container">
<input type="text" placeholder="ゲームを検索..." id="searchInput">
<button id="searchButton">検索</button>
</div>
</div>
</nav>
<!--────────────────────────────
フィルターサイドバー(デスクトップ用)
────────────────────────────-->
<aside class="filter-sidebar" id="filterSidebar">
<h3>フィルター</h3>
<label for="filterGenre">ジャンル:</label>
<select id="filterGenre">
<option value="">すべて</option>
<option value="アクション">アクション</option>
<option value="RPG">RPG</option>
<option value="シューティング">シューティング</option>
<option value="パズル">パズル</option>
</select>
<label for="filterPrice">価格上限:</label>
<input type="number" id="filterPrice" placeholder="例: 5000">
<button id="applyFilter">フィルター適用</button>
</aside>
<!--────────────────────────────
ヒーロースライダー
────────────────────────────-->
<div class="hero-slider" id="heroSlider">
<div class="hero-slide active" style="background-image: url('images/hero1.jpg');">
<div class="hero-content">
<h2>最新作が続々登場!</h2>
<p>冒険、戦略、アクション…全てのゲームがここに。</p>
<a href="#" class="btn">詳しく見る</a>
</div>
</div>
<div class="hero-slide" style="background-image: url('images/hero2.jpg');">
<div class="hero-content">
<h2>セール開催中!</h2>
<p>期間限定、最大50%OFF!</p>
<a href="#" class="btn">セールを見る</a>
</div>
</div>
<div class="hero-slide" style="background-image: url('images/hero3.jpg');">
<div class="hero-content">
<h2>ユーザーレビューで選ぶ</h2>
<p>実際の評価を元に、あなたにピッタリのゲームを見つけよう。</p>
<a href="#" class="btn">レビューを見る</a>
</div>
</div>
<div class="hero-controls" id="heroControls"></div>
</div>
<!--────────────────────────────
新作ゲームセクション
────────────────────────────-->
<section id="new-releases" class="fade-in">
<h2 class="section-title">新作ゲーム</h2>
<p class="section-description">最新のゲームタイトルをチェック!</p>
<div class="game-grid" id="newReleasesGrid">
<div class="game-card" data-title="新作ゲーム1" data-genre="アクション" data-price="3500円" data-description="迫力のアクションと最新技術が融合した作品。">
<img src="images/new1.jpg" alt="新作ゲーム1" loading="lazy">
<div class="game-card-content">
<h3>新作ゲーム1</h3>
<p>ジャンル: アクション</p>
<p class="price">3500円</p>
</div>
<div class="card-overlay"></div>
</div>
<div class="game-card" data-title="新作ゲーム2" data-genre="RPG" data-price="4200円" data-description="壮大な物語と美しい世界観が魅力。">
<img src="images/new2.jpg" alt="新作ゲーム2" loading="lazy">
<div class="game-card-content">
<h3>新作ゲーム2</h3>
<p>ジャンル: RPG</p>
<p class="price">4200円</p>
</div>
<div class="card-overlay"></div>
</div>
<div class="game-card" data-title="新作ゲーム3" data-genre="シューティング" data-price="2900円" data-description="高速なアクションとリアルなグラフィックが特長。">
<img src="images/new3.jpg" alt="新作ゲーム3" loading="lazy">
<div class="game-card-content">
<h3>新作ゲーム3</h3>
<p>ジャンル: シューティング</p>
<p class="price">2900円</p>
</div>
<div class="card-overlay"></div>
</div>
<div class="game-card" data-title="新作ゲーム4" data-genre="パズル" data-price="1500円" data-description="頭脳を刺激する独自のパズル体験。">
<img src="images/new4.jpg" alt="新作ゲーム4" loading="lazy">
<div class="game-card-content">
<h3>新作ゲーム4</h3>
<p>ジャンル: パズル</p>
<p class="price">1500円</p>
</div>
<div class="card-overlay"></div>
</div>
</div>
</section>
<!--────────────────────────────
注目特集セクション
────────────────────────────-->
<section id="featured" class="fade-in">
<h2 class="section-title">注目の特集</h2>
<p class="section-description">今週の注目タイトルや特集記事をお届けします。</p>
<div class="game-grid">
<div class="game-card" data-title="特集タイトル1" data-genre="特集" data-price="記事を見る" data-description="最新トレンドを徹底解説。">
<img src="images/featured1.jpg" alt="特集1" loading="lazy">
<div class="game-card-content">
<h3>特集タイトル1</h3>
<p>期間限定特集:最新トレンド</p>
<p class="price">特集記事を見る</p>
</div>
<div class="card-overlay"></div>
</div>
<div class="game-card" data-title="特集タイトル2" data-genre="特集" data-price="記事を見る" data-description="インディーゲームの革新を追う。">
<img src="images/featured2.jpg" alt="特集2" loading="lazy">
<div class="game-card-content">
<h3>特集タイトル2</h3>
<p>話題のインディーゲーム特集</p>
<p class="price">特集記事を見る</p>
</div>
<div class="card-overlay"></div>
</div>
</div>
</section>
<!--────────────────────────────
アップロード済みゲーム表示(管理者アップロードデータ)
────────────────────────────-->
<section id="my-uploads" class="fade-in">
<h2 class="section-title">アップロードしたゲーム</h2>
<p class="section-description">管理者がアップロードしたゲームデータです。</p>
<div class="game-grid" id="myUploadsGrid"></div>
</section>
<!--────────────────────────────
ジャンル別セクション
────────────────────────────-->
<section id="categories" class="fade-in">
<h2 class="section-title">ジャンル別</h2>
<p class="section-description">お気に入りのジャンルからゲームを探してみましょう。</p>
<div class="categories">
<a href="#" class="category-card">
<img src="images/cat-action.jpg" alt="アクション" loading="lazy">
<span>アクション</span>
</a>
<a href="#" class="category-card">
<img src="images/cat-rpg.jpg" alt="RPG" loading="lazy">
<span>RPG</span>
</a>
<a href="#" class="category-card">
<img src="images/cat-shooting.jpg" alt="シューティング" loading="lazy">
<span>シューティング</span>
</a>
<a href="#" class="category-card">
<img src="images/cat-puzzle.jpg" alt="パズル" loading="lazy">
<span>パズル</span>
</a>
<a href="#" class="category-card">
<img src="images/cat-adventure.jpg" alt="アドベンチャー" loading="lazy">
<span>アドベンチャー</span>
</a>
</div>
</section>
<!--────────────────────────────
ユーザーレビューセクション
────────────────────────────-->
<section id="reviews" class="fade-in">
<h2 class="section-title">ユーザーレビュー</h2>
<p class="section-description">実際にプレイしたユーザーの評価をチェック!</p>
<div class="reviews-slider">
<div class="reviews-track">
<div class="review-card">
<h4>最高のアクション体験!</h4>
<div class="rating"><span>★★★★★</span></div>
<p>アクションゲームの決定版。グラフィックも音楽も最高でした。</p>
</div>
<div class="review-card">
<h4>壮大なストーリーに引き込まれる</h4>
<div class="rating"><span>★★★★☆</span></div>
<p>RPGの世界観が素晴らしく、ストーリーにのめり込みました。</p>
</div>
<div class="review-card">
<h4>クセになる操作感!</h4>
<div class="rating"><span>★★★★★</span></div>
<p>シューティングゲームとして非常に爽快な操作感で、何度も挑戦しました。</p>
</div>
</div>
</div>
</section>
<!--────────────────────────────
ブログセクション
────────────────────────────-->
<section id="blog" class="fade-in">
<h2 class="section-title">最新ブログ</h2>
<p class="section-description">ゲーム業界の最新情報や攻略記事をお届けします。</p>
<div class="blog-grid">
<div class="blog-card">
<img src="images/blog1.jpg" alt="ブログ記事1" loading="lazy">
<div class="blog-card-content">
<h3>2025年の注目ゲームトレンド</h3>
<p>今年注目すべきゲームの傾向と今後の展望について解説します。</p>
<a href="#" class="btn">続きを読む</a>
</div>
</div>
<div class="blog-card">
<img src="images/blog2.jpg" alt="ブログ記事2" loading="lazy">
<div class="blog-card-content">
<h3>セール攻略:お得に買う方法</h3>
<p>賢く買い物するための裏技やポイントを紹介します。</p>
<a href="#" class="btn">続きを読む</a>
</div>
</div>
<div class="blog-card">
<img src="images/blog3.jpg" alt="ブログ記事3" loading="lazy">
<div class="blog-card-content">
<h3>レビューで選ぶ!おすすめタイトル</h3>
<p>実際のユーザーレビューをもとに、人気タイトルをピックアップ。</p>
<a href="#" class="btn">続きを読む</a>
</div>
</div>
</div>
</section>
<!--────────────────────────────
商品詳細モーダル
────────────────────────────-->
<div class="modal-overlay" id="productModal">
<div class="modal">
<div class="modal-header">
<h2 id="modalTitle">ゲーム詳細</h2>
<span class="modal-close" id="modalClose">×</span>
</div>
<div class="modal-body" id="modalBody">
<p id="modalDescription">詳細情報がここに表示されます。</p>
<p><strong>ジャンル:</strong> <span id="modalGenre"></span></p>
<p><strong>価格:</strong> <span id="modalPrice"></span></p>
</div>
<div class="modal-footer">
<button class="btn" id="modalBuyButton">今すぐ購入</button>
</div>
</div>
</div>
<!--────────────────────────────
ログインモーダル
────────────────────────────-->
<div class="modal-overlay" id="loginModal">
<div class="modal">
<div class="modal-header">
<h2>ログイン</h2>
<span class="modal-close" id="loginClose">×</span>
</div>
<div class="modal-body">
<form id="loginForm">
<label for="loginUsername">ユーザー名:</label>
<input type="text" id="loginUsername" required>
<label for="loginPassword">パスワード:</label>
<input type="password" id="loginPassword" required>
<button class="btn" type="submit">ログイン</button>
</form>
</div>
</div>
</div>
<!--────────────────────────────
新規登録モーダル
────────────────────────────-->
<div class="modal-overlay" id="registerModal">
<div class="modal">
<div class="modal-header">
<h2>新規登録</h2>
<span class="modal-close" id="registerClose">×</span>
</div>
<div class="modal-body">
<form id="registerForm">
<label for="registerUsername">ユーザー名:</label>
<input type="text" id="registerUsername" required>
<label for="registerEmail">メールアドレス:</label>
<input type="email" id="registerEmail" required>
<label for="registerPassword">パスワード:</label>
<input type="password" id="registerPassword" required>
<button class="btn" type="submit">登録</button>
</form>
</div>
</div>
</div>
<!--────────────────────────────
カートモーダル
────────────────────────────-->
<div class="modal-overlay" id="cartModal">
<div class="modal">
<div class="modal-header">
<h2>カート</h2>
<span class="modal-close" id="cartClose">×</span>
</div>
<div class="modal-body" id="cartBody">
<p>カートにアイテムはありません。</p>
</div>
<div class="modal-footer">
<button class="btn" id="checkoutButton">チェックアウト</button>
</div>
</div>
</div>
<!--────────────────────────────
アップロードモーダル(管理者向け)
────────────────────────────-->
<div class="modal-overlay" id="uploadModal">
<div class="modal">
<div class="modal-header">
<h2>ゲームアップロード</h2>
<span class="modal-close" id="uploadClose">×</span>
</div>
<div class="modal-body">
<form id="uploadForm" enctype="multipart/form-data">
<label for="uploadTitle">ゲームタイトル:</label>
<input type="text" id="uploadTitle" required>
<label for="uploadGenre">ジャンル:</label>
<input type="text" id="uploadGenre" required>
<label for="uploadPrice">価格:</label>
<input type="number" id="uploadPrice" required>
<label for="uploadDescription">説明:</label>
<textarea id="uploadDescription" rows="4" required></textarea>
<label for="uploadFile">画像アップロード:</label>
<input type="file" id="uploadFile" accept="image/*" required>
<button class="btn" type="submit">アップロード</button>
</form>
</div>
</div>
</div>
<!--────────────────────────────
フローティングカートボタン
────────────────────────────-->
<button id="cartButton" style="position: fixed; bottom: 100px; right: 40px; background: var(--primary); color: var(--light); padding:12px; border:none; border-radius:50%; box-shadow: var(--shadow); cursor:pointer; z-index:1500;">
🛒
</button>
<!--────────────────────────────
Back-to-Top ボタン
────────────────────────────-->
<div id="backToTop">⇧</div>
<!--────────────────────────────
JavaScript(各種機能の実装)
────────────────────────────-->
<script>
// ハンバーガーメニューの切替
const hamburger = document.getElementById('hamburger');
const navMenu = document.getElementById('navMenu');
hamburger.addEventListener('click', () => {
navMenu.classList.toggle('active');
});
// ヒーロースライダー(自動・手動切替)
const slides = document.querySelectorAll('.hero-slide');
const heroControls = document.getElementById('heroControls');
let currentSlide = 0;
slides.forEach((_, index) => {
const dot = document.createElement('div');
dot.classList.add('hero-control');
if(index === 0) dot.classList.add('active');
dot.addEventListener('click', () => showSlide(index));
heroControls.appendChild(dot);
});
function showSlide(index) {
slides[currentSlide].classList.remove('active');
heroControls.children[currentSlide].classList.remove('active');
currentSlide = index;
slides[currentSlide].classList.add('active');
heroControls.children[currentSlide].classList.add('active');
}
setInterval(() => {
let next = (currentSlide + 1) % slides.length;
showSlide(next);
}, 5000);
// Back-to-Top ボタン表示
const backToTop = document.getElementById('backToTop');
window.addEventListener('scroll', () => {
backToTop.style.display = window.scrollY > 300 ? 'block' : 'none';
});
backToTop.addEventListener('click', () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
// IntersectionObserver によるフェードイン効果
const faders = document.querySelectorAll('.fade-in');
const appearOptions = { threshold: 0.1 };
const appearOnScroll = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if(entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target);
}
});
}, appearOptions);
faders.forEach(fader => appearOnScroll.observe(fader));
// 商品詳細モーダル
const gameCards = document.querySelectorAll('.game-card');
const productModal = document.getElementById('productModal');
const modalTitle = document.getElementById('modalTitle');
const modalDescription = document.getElementById('modalDescription');
const modalGenre = document.getElementById('modalGenre');
const modalPrice = document.getElementById('modalPrice');
const modalClose = document.getElementById('modalClose');
gameCards.forEach(card => {
card.addEventListener('click', () => {
modalTitle.textContent = card.getAttribute('data-title');
modalGenre.textContent = card.getAttribute('data-genre');
modalPrice.textContent = card.getAttribute('data-price');
modalDescription.textContent = card.getAttribute('data-description');
productModal.classList.add('active');
});
});
modalClose.addEventListener('click', () => productModal.classList.remove('active'));
productModal.addEventListener('click', (e) => { if(e.target === productModal) productModal.classList.remove('active'); });
// 検索フィルター
const searchInput = document.getElementById('searchInput');
const searchButton = document.getElementById('searchButton');
searchButton.addEventListener('click', () => {
const query = searchInput.value.toLowerCase();
const cards = document.querySelectorAll('.game-card');
cards.forEach(card => {
const title = card.getAttribute('data-title').toLowerCase();
const genre = card.getAttribute('data-genre').toLowerCase();
card.style.display = (title.includes(query) || genre.includes(query)) ? 'block' : 'none';
});
});
// フィルターサイドバー機能
const filterGenre = document.getElementById('filterGenre');
const filterPrice = document.getElementById('filterPrice');
const applyFilter = document.getElementById('applyFilter');
applyFilter.addEventListener('click', () => {
const genreValue = filterGenre.value;
const priceValue = filterPrice.value;
const cards = document.querySelectorAll('.game-card');
cards.forEach(card => {
const cardGenre = card.getAttribute('data-genre');
const cardPrice = parseInt(card.getAttribute('data-price')) || 0;
let matchesGenre = genreValue === "" || cardGenre === genreValue;
let matchesPrice = !priceValue || (cardPrice && cardPrice <= parseInt(priceValue));
card.style.display = (matchesGenre && matchesPrice) ? 'block' : 'none';
});
});
// ログインモーダル
const loginModal = document.getElementById('loginModal');
const loginClose = document.getElementById('loginClose');
loginClose.addEventListener('click', () => loginModal.classList.remove('active'));
loginModal.addEventListener('click', (e) => { if(e.target === loginModal) loginModal.classList.remove('active'); });
// 新規登録モーダル
const registerModal = document.getElementById('registerModal');
const registerClose = document.getElementById('registerClose');
registerClose.addEventListener('click', () => registerModal.classList.remove('active'));
registerModal.addEventListener('click', (e) => { if(e.target === registerModal) registerModal.classList.remove('active'); });
// カートモーダル
const cartModal = document.getElementById('cartModal');
const cartClose = document.getElementById('cartClose');
const cartButton = document.getElementById('cartButton');
cartButton.addEventListener('click', () => cartModal.classList.add('active'));
cartClose.addEventListener('click', () => cartModal.classList.remove('active'));
cartModal.addEventListener('click', (e) => { if(e.target === cartModal) cartModal.classList.remove('active'); });
// アップロードモーダル(管理者向け)
const uploadModal = document.getElementById('uploadModal');
const uploadLink = document.getElementById('uploadLink');
const uploadClose = document.getElementById('uploadClose');
uploadLink.addEventListener('click', (e) => {
e.preventDefault();
uploadModal.classList.add('active');
});
uploadClose.addEventListener('click', () => uploadModal.classList.remove('active'));
uploadModal.addEventListener('click', (e) => { if(e.target === uploadModal) uploadModal.classList.remove('active'); });
// アップロードフォーム送信(アップロードデータをlocalStorageへ保存)
const uploadForm = document.getElementById('uploadForm');
uploadForm.addEventListener('submit', (e) => {
e.preventDefault();
const title = document.getElementById('uploadTitle').value;
const genre = document.getElementById('uploadGenre').value;
const price = document.getElementById('uploadPrice').value + "円";
const description = document.getElementById('uploadDescription').value;
const fileInput = document.getElementById('uploadFile');
const file = fileInput.files[0];
if(file) {
const reader = new FileReader();
reader.onload = function(event) {
const imageData = event.target.result;
const gameData = { title, genre, price, description, image: imageData };
let uploadedGames = JSON.parse(localStorage.getItem('uploadedGames')) || [];
uploadedGames.push(gameData);
localStorage.setItem('uploadedGames', JSON.stringify(uploadedGames));
loadUploadedGames();
alert('アップロードが完了しました。');
uploadModal.classList.remove('active');
uploadForm.reset();
};
reader.readAsDataURL(file);
}
});
// アップロード済みゲームを読み込み表示する(「アップロードしたゲーム」セクション)
function loadUploadedGames() {
const grid = document.getElementById('myUploadsGrid');
let uploadedGames = JSON.parse(localStorage.getItem('uploadedGames')) || [];
grid.innerHTML = "";
uploadedGames.forEach(game => {
const card = document.createElement('div');
card.classList.add('game-card');
card.setAttribute('data-title', game.title);
card.setAttribute('data-genre', game.genre);
card.setAttribute('data-price', game.price);
card.setAttribute('data-description', game.description);
card.innerHTML = `
<img src="${game.image}" alt="${game.title}" loading="lazy">
<div class="game-card-content">
<h3>${game.title}</h3>
<p>ジャンル: ${game.genre}</p>
<p class="price">${game.price}</p>
</div>
<div class="card-overlay"></div>
`;
card.addEventListener('click', () => {
modalTitle.textContent = game.title;
modalGenre.textContent = game.genre;
modalPrice.textContent = game.price;
modalDescription.textContent = game.description;
productModal.classList.add('active');
});
grid.appendChild(card);
});
}
// ページ読み込み時にアップロード済みゲームを表示
loadUploadedGames();
</script>
</body>
<footer>
<div class="footer-container">
<div class="footer-col">
<h4>会社情報</h4>
<ul>
<li><a href="#">企業理念</a></li>
<li><a href="#">採用情報</a></li>
<li><a href="#">プレスリリース</a></li>
</ul>
</div>
<div class="footer-col">
<h4>サポート</h4>
<ul>
<li><a href="#">お問い合わせ</a></li>
<li><a href="#">FAQ</a></li>
<li><a href="#">利用規約</a></li>
</ul>
</div>
<div class="footer-col">
<h4>ニュースレター</h4>
<p>最新情報をメールで受け取る</p>
<form class="subscribe-form">
<input type="email" placeholder="メールアドレス" required>
<button type="submit">登録</button>
</form>
</div>
</div>
<div class="footer-bottom">© 2025 GameStore Ultra. All rights reserved.</div>
</footer>
</html>