| <!doctype html> |
| <html lang="zh-CN"> |
| <head> |
| <meta charset="utf-8"> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width"> |
| <title>美食探索</title> |
| |
| <script> |
| window._AMapSecurityConfig = { |
| securityJsCode: 'cf71cd668b9003a1144459e461092afb', |
| } |
| </script> |
| <script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=11b1daeff703d83adef3e84cd746ab84&plugin=AMap.CitySearch,AMap.PlaceSearch"></script> |
| |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <style type="text/css"> |
| * { |
| margin: 0; |
| padding: 0; |
| box-sizing: border-box; |
| font-family: 'Helvetica Neue', Arial, sans-serif; |
| } |
| |
| body { |
| height: 100vh; |
| display: flex; |
| flex-direction: column; |
| background-color: #f5f5f5; |
| } |
| |
| .header { |
| background: linear-gradient(135deg, #ff7e5f, #feb47b); |
| color: white; |
| padding: 15px 20px; |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); |
| z-index: 100; |
| } |
| |
| .header h1 { |
| font-size: 22px; |
| font-weight: 600; |
| } |
| |
| .search-container { |
| background: white; |
| padding: 15px; |
| display: flex; |
| align-items: center; |
| box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); |
| } |
| |
| .search-bar { |
| display: flex; |
| flex: 1; |
| position: relative; |
| } |
| |
| .search-bar input { |
| flex: 1; |
| padding: 12px 15px; |
| border: 1px solid #e0e0e0; |
| border-radius: 24px; |
| font-size: 16px; |
| outline: none; |
| transition: border 0.3s; |
| } |
| |
| .search-bar input:focus { |
| border-color: #ff7e5f; |
| } |
| |
| .search-bar button { |
| position: absolute; |
| right: 10px; |
| top: 50%; |
| transform: translateY(-50%); |
| background: none; |
| border: none; |
| color: #ff7e5f; |
| font-size: 18px; |
| cursor: pointer; |
| } |
| |
| .city-selector { |
| margin-left: 15px; |
| display: flex; |
| align-items: center; |
| cursor: pointer; |
| padding: 8px 12px; |
| border-radius: 20px; |
| background: #f7f7f7; |
| transition: background 0.3s; |
| } |
| |
| .city-selector:hover { |
| background: #f0f0f0; |
| } |
| |
| .main-content { |
| display: flex; |
| flex: 1; |
| overflow: hidden; |
| } |
| |
| #container { |
| flex: 1; |
| height: 100%; |
| } |
| |
| #panel { |
| width: 360px; |
| background: white; |
| overflow-y: auto; |
| box-shadow: -2px 0 10px rgba(0, 0, 0, 0.1); |
| padding: 0; |
| transition: transform 0.3s; |
| } |
| |
| .food-categories { |
| display: flex; |
| overflow-x: auto; |
| padding: 15px; |
| background: white; |
| margin-bottom: 15px; |
| box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); |
| scrollbar-width: none; |
| } |
| |
| .food-categories::-webkit-scrollbar { |
| display: none; |
| } |
| |
| .category { |
| flex: 0 0 auto; |
| margin-right: 15px; |
| padding: 8px 15px; |
| background: #f7f7f7; |
| border-radius: 20px; |
| cursor: pointer; |
| transition: all 0.3s; |
| font-size: 14px; |
| white-space: nowrap; |
| } |
| |
| .category.active { |
| background: #ff7e5f; |
| color: white; |
| } |
| |
| .category:hover:not(.active) { |
| background: #f0f0f0; |
| } |
| |
| .result-item { |
| border-bottom: 1px solid #f0f0f0; |
| padding: 15px; |
| cursor: pointer; |
| transition: background 0.3s; |
| } |
| |
| .result-item:hover { |
| background: #f9f9f9; |
| } |
| |
| .result-item h3 { |
| font-size: 16px; |
| margin-bottom: 8px; |
| color: #333; |
| } |
| |
| .result-item p { |
| font-size: 14px; |
| color: #666; |
| margin-bottom: 8px; |
| } |
| |
| .result-item .rating { |
| color: #ff7e5f; |
| margin-bottom: 8px; |
| } |
| |
| .result-item .address { |
| display: flex; |
| align-items: center; |
| font-size: 13px; |
| color: #999; |
| } |
| |
| .result-item .address i { |
| margin-right: 5px; |
| } |
| |
| .loading { |
| position: absolute; |
| top: 50%; |
| left: 50%; |
| transform: translate(-50%, -50%); |
| display: none; |
| } |
| |
| .loading i { |
| font-size: 40px; |
| color: #ff7e5f; |
| animation: spin 1s infinite linear; |
| } |
| |
| @keyframes spin { |
| from { transform: rotate(0deg); } |
| to { transform: rotate(360deg); } |
| } |
| |
| .no-results { |
| padding: 30px; |
| text-align: center; |
| color: #666; |
| } |
| |
| .amap-info-content { |
| padding: 10px; |
| border-radius: 8px; |
| } |
| |
| |
| @media (max-width: 768px) { |
| .main-content { |
| flex-direction: column; |
| } |
| |
| #container { |
| height: 40%; |
| } |
| |
| #panel { |
| width: 100%; |
| height: 60%; |
| box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); |
| } |
| |
| .header h1 { |
| font-size: 18px; |
| } |
| } |
| </style> |
| </head> |
| <body> |
| <div class="header"> |
| <h1>美食探索</h1> |
| <div id="current-city" class="city-selector"> |
| <i class="fas fa-map-marker-alt"></i> |
| <span>定位中...</span> |
| </div> |
| </div> |
| |
| <div class="search-container"> |
| <div class="search-bar"> |
| <input type="text" id="keyword" placeholder="搜索美食、餐厅" value="美食"> |
| <button id="search-btn"><i class="fas fa-search"></i></button> |
| </div> |
| </div> |
| |
| <div class="food-categories"> |
| <div class="category active" data-keyword="美食">全部美食</div> |
| <div class="category" data-keyword="火锅">火锅</div> |
| <div class="category" data-keyword="烧烤">烧烤</div> |
| <div class="category" data-keyword="小吃">特色小吃</div> |
| <div class="category" data-keyword="西餐">西餐</div> |
| <div class="category" data-keyword="日料">日料</div> |
| <div class="category" data-keyword="甜点">甜点</div> |
| <div class="category" data-keyword="咖啡">咖啡</div> |
| <div class="category" data-keyword="面包">面包</div> |
| <div class="category" data-keyword="早餐">早餐</div> |
| </div> |
| |
| <div class="main-content"> |
| <div id="container"></div> |
| <div id="panel"></div> |
| </div> |
| |
| <div class="loading"> |
| <i class="fas fa-spinner"></i> |
| </div> |
|
|
| <script type="text/javascript"> |
| |
| var map = new AMap.Map("container", { |
| resizeEnable: true, |
| zoom: 12, |
| center: [116.397428, 39.90923] |
| }); |
| |
| |
| var currentCity = { |
| name: '北京', |
| adcode: '010' |
| }; |
| |
| |
| var currentKeyword = '美食'; |
| |
| |
| var placeSearch = null; |
| |
| |
| function updateCityText() { |
| document.querySelector('#current-city span').textContent = currentCity.name; |
| } |
| |
| |
| function getCityByIP() { |
| |
| var citysearch = new AMap.CitySearch(); |
| |
| |
| citysearch.getLocalCity(function(status, result) { |
| if (status === 'complete' && result.info === 'OK') { |
| if (result && result.city && result.bounds) { |
| currentCity = { |
| name: result.city, |
| adcode: result.adcode |
| }; |
| |
| updateCityText(); |
| |
| |
| map.setBounds(result.bounds); |
| |
| |
| initPlaceSearch(); |
| } |
| } else { |
| |
| updateCityText(); |
| initPlaceSearch(); |
| } |
| }); |
| } |
| |
| |
| function initPlaceSearch() { |
| placeSearch = new AMap.PlaceSearch({ |
| pageSize: 10, |
| pageIndex: 1, |
| city: currentCity.adcode, |
| citylimit: true, |
| map: map, |
| autoFitView: true |
| }); |
| |
| |
| placeSearch.on('complete', function(results) { |
| document.querySelector('.loading').style.display = 'none'; |
| if (results.info === 'OK') { |
| customizeResultList(results.poiList.pois); |
| } else { |
| document.getElementById('panel').innerHTML = '<div class="no-results">没有找到相关结果</div>'; |
| } |
| }); |
| |
| |
| searchPOI(); |
| } |
| |
| |
| function searchPOI() { |
| if (!placeSearch) { |
| return; |
| } |
| |
| document.querySelector('.loading').style.display = 'block'; |
| placeSearch.search(currentKeyword, function(status, result) { |
| document.querySelector('.loading').style.display = 'none'; |
| if (status === 'error' || status === 'no_data') { |
| document.getElementById('panel').innerHTML = '<div class="no-results">没有找到相关结果</div>'; |
| } |
| }); |
| } |
| |
| |
| function customizeResultList(pois) { |
| var panel = document.getElementById('panel'); |
| panel.innerHTML = ''; |
| |
| if (!pois || pois.length === 0) { |
| panel.innerHTML = '<div class="no-results">没有找到相关结果</div>'; |
| return; |
| } |
| |
| pois.forEach(function(poi) { |
| var item = document.createElement('div'); |
| item.className = 'result-item'; |
| |
| |
| var rating = (Math.random() * 1.0 + 4.0).toFixed(1); |
| |
| var price = Math.floor(Math.random() * 180 + 20); |
| |
| |
| var stars = ''; |
| var fullStars = Math.floor(rating); |
| var halfStar = rating % 1 >= 0.5; |
| |
| for (var i = 0; i < 5; i++) { |
| if (i < fullStars) { |
| stars += '<i class="fas fa-star"></i>'; |
| } else if (halfStar && i === fullStars) { |
| stars += '<i class="fas fa-star-half-alt"></i>'; |
| halfStar = false; |
| } else { |
| stars += '<i class="far fa-star"></i>'; |
| } |
| } |
| |
| item.innerHTML = ` |
| <h3>${poi.name}</h3> |
| <div class="rating">${stars} ${rating} · 人均 ¥${price}</div> |
| <p>${poi.type || '特色美食'}</p> |
| <div class="address"><i class="fas fa-map-marker-alt"></i>${poi.address || poi.location.toString()}</div> |
| `; |
| |
| item.addEventListener('click', function() { |
| map.setCenter(poi.location); |
| map.setZoom(15); |
| }); |
| |
| panel.appendChild(item); |
| }); |
| } |
| |
| |
| document.getElementById('search-btn').addEventListener('click', function() { |
| var keyword = document.getElementById('keyword').value.trim(); |
| if (keyword) { |
| currentKeyword = keyword; |
| searchPOI(); |
| |
| |
| document.querySelectorAll('.category').forEach(function(cat) { |
| cat.classList.remove('active'); |
| if (cat.dataset.keyword === keyword) { |
| cat.classList.add('active'); |
| } |
| }); |
| } |
| }); |
| |
| |
| document.getElementById('keyword').addEventListener('keyup', function(e) { |
| if (e.key === 'Enter') { |
| document.getElementById('search-btn').click(); |
| } |
| }); |
| |
| |
| document.querySelectorAll('.category').forEach(function(category) { |
| category.addEventListener('click', function() { |
| document.querySelectorAll('.category').forEach(function(cat) { |
| cat.classList.remove('active'); |
| }); |
| this.classList.add('active'); |
| |
| currentKeyword = this.dataset.keyword; |
| document.getElementById('keyword').value = currentKeyword; |
| searchPOI(); |
| }); |
| }); |
| |
| |
| document.getElementById('current-city').addEventListener('click', function() { |
| |
| alert('城市选择功能将在未来版本添加'); |
| }); |
| |
| |
| window.onload = function() { |
| getCityByIP(); |
| }; |
| </script> |
| </body> |
| </html> |