You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何制作具备悬停预览与点击固定功能的Genre下拉菜单?

Alright, let's tackle this Genre dropdown with your specific interaction requirements and integrate it with your existing search functionality. Here's a step-by-step implementation that covers all your needs:


HTML Structure

First, we'll build the core dropdown markup alongside your existing search area and movie display container:

<!-- Place this next to your search input -->
<div class="genre-dropdown">
  <button class="genre-btn">Genre <span class="dropdown-arrow">▼</span></button>
  <div class="genre-menu">
    <div class="genre-option" data-genre="adventure">冒险</div>
    <div class="genre-option" data-genre="horror">恐怖</div>
    <div class="genre-option" data-genre="action">动作</div>
    <div class="genre-option" data-genre="comedy">喜剧</div>
    <!-- Add more genres as needed -->
  </div>
</div>

<!-- Your existing search input (adjust ID to match your actual code) -->
<input type="text" id="movie-search" placeholder="搜索影片标题...">

<!-- Movie display container -->
<div class="movies-grid"></div>

CSS Styling

This handles the dropdown visibility, hover states, and selected styling:

.genre-dropdown {
  position: relative;
  display: inline-block;
  margin-right: 1rem;
}

.genre-btn {
  padding: 0.5rem 1rem;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  background: #ffffff;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.genre-menu {
  position: absolute;
  top: 100%;
  left: 0;
  width: 160px;
  margin-top: 0.25rem;
  border: 1px solid #e0e0e0;
  border-top: none;
  border-radius: 0 0 4px 4px;
  background: #ffffff;
  display: none;
  z-index: 100;
}

.genre-menu.active {
  display: block;
}

.genre-option {
  padding: 0.5rem 1rem;
  cursor: pointer;
  transition: background-color 0.2s;
}

.genre-option:hover {
  background-color: #f5f5f5;
}

.genre-option.selected {
  background-color: #e8f0fe;
  font-weight: 600;
}

/* Basic movie grid styling (adjust to your design) */
.movies-grid {
  margin-top: 1rem;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 1rem;
}

.movie-card {
  padding: 1rem;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
}

JavaScript Logic

This implements all the required interactions and ties everything together with your search feature:

// Get DOM elements
const genreBtn = document.querySelector('.genre-btn');
const genreMenu = document.querySelector('.genre-menu');
const genreOptions = document.querySelectorAll('.genre-option');
const searchInput = document.getElementById('movie-search');
const moviesGrid = document.querySelector('.movies-grid');

// Sample movie data (replace with your actual data source)
const movieDatabase = [
  { title: '夺宝奇兵:命运转盘', genre: 'adventure' },
  { title: '闪灵', genre: 'horror' },
  { title: '速度与激情10', genre: 'action' },
  { title: '失控玩家', genre: 'comedy' },
  { title: '侏罗纪世界3', genre: 'adventure' },
  { title: '招魂3', genre: 'horror' }
];

// Toggle dropdown on button click
genreBtn.addEventListener('click', () => {
  genreMenu.classList.toggle('active');
});

// Close dropdown when clicking outside
document.addEventListener('click', (e) => {
  if (!genreBtn.contains(e.target) && !genreMenu.contains(e.target)) {
    genreMenu.classList.remove('active');
  }
});

// Handle genre option interactions
genreOptions.forEach(option => {
  // Show movies on hover
  option.addEventListener('mouseenter', () => {
    const targetGenre = option.dataset.genre;
    renderMovies(filterMoviesByGenre(targetGenre));
  });

  // Fix selected genre on click
  option.addEventListener('click', () => {
    // Clear previous selected state
    genreOptions.forEach(opt => opt.classList.remove('selected'));
    // Mark current option as selected
    option.classList.add('selected');
    // Render movies for selected genre
    const targetGenre = option.dataset.genre;
    renderMovies(filterMoviesByGenre(targetGenre));
    // Close dropdown after selection
    genreMenu.classList.remove('active');
  });
});

// Integrate with search functionality
searchInput.addEventListener('input', () => {
  const searchTerm = searchInput.value.toLowerCase().trim();
  const selectedGenre = document.querySelector('.genre-option.selected')?.dataset.genre;

  let filteredMovies = movieDatabase;

  // Apply genre filter if one is selected
  if (selectedGenre) {
    filteredMovies = filterMoviesByGenre(selectedGenre);
  }

  // Apply search term filter
  if (searchTerm) {
    filteredMovies = filteredMovies.filter(movie => 
      movie.title.toLowerCase().includes(searchTerm)
    );
  }

  renderMovies(filteredMovies);
});

// Helper: Filter movies by genre
function filterMoviesByGenre(genre) {
  return movieDatabase.filter(movie => movie.genre === genre);
}

// Helper: Render movies to the grid
function renderMovies(movies) {
  moviesGrid.innerHTML = '';
  
  if (movies.length === 0) {
    moviesGrid.innerHTML = '<p>没有找到匹配的影片</p>';
    return;
  }

  movies.forEach(movie => {
    const card = document.createElement('div');
    card.className = 'movie-card';
    card.textContent = movie.title;
    moviesGrid.appendChild(card);
  });
}

// Initialize with all movies (optional)
renderMovies(movieDatabase);

Key Features Explained:

  • Click-only dropdown: The menu only opens/closes when clicking the Genre button, no hover activation.
  • Hover preview: Hovering any genre immediately shows its associated movies without selecting it.
  • Persistent selection: Clicking a genre marks it as selected and locks the movie display to that genre until another is chosen.
  • Search integration: The search feature now works alongside the selected genre—search results will only include movies from the active genre (if one is selected).

内容的提问来源于stack exchange,提问作者SoyBins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 09:27:30