当前位置: 首页 > news >正文

TypeScript移动端导航工具实现

TypeScript移动端导航工具实现

我将设计一个使用TypeScript构建的移动端导航工具,包含地图视图、路线规划和导航功能。

设计思路

导航工具需要


响应式移动端UI


地图显示与交互

搜索地点功能


路线规划与导航


使用TypeScript实现核心逻辑

下面是完整实现:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>TS导航工具</title><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"><style>* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);color: #fff;height: 100vh;overflow: hidden;display: flex;justify-content: center;align-items: center;}.container {width: 100%;max-width: 430px;height: 90vh;background: rgba(10, 20, 30, 0.85);border-radius: 20px;overflow: hidden;box-shadow: 0 15px 35px rgba(0, 0, 0, 0.5);display: flex;flex-direction: column;position: relative;}header {padding: 20px;background: rgba(15, 30, 50, 0.95);display: flex;justify-content: space-between;align-items: center;z-index: 10;box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);}.logo {display: flex;align-items: center;gap: 10px;font-size: 1.5rem;font-weight: bold;}.logo i {color: #4dabf7;}.search-box {background: rgba(255, 255, 255, 0.1);border-radius: 30px;padding: 8px 15px;display: flex;align-items: center;gap: 10px;flex: 1;max-width: 250px;margin: 0 15px;border: 1px solid rgba(255, 255, 255, 0.2);}.search-box input {background: transparent;border: none;color: white;font-size: 1rem;width: 100%;outline: none;}.search-box input::placeholder {color: rgba(255, 255, 255, 0.6);}.user-avatar {width: 40px;height: 40px;border-radius: 50%;background: linear-gradient(45deg, #3498db, #8e44ad);display: flex;justify-content: center;align-items: center;font-weight: bold;font-size: 1.2rem;}.map-container {flex: 1;position: relative;overflow: hidden;}.map {width: 100%;height: 100%;background: linear-gradient(45deg, #2c3e50, #4a6491);position: relative;}.map-overlay {position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: repeating-linear-gradient(0deg,transparent,transparent 19px,rgba(255, 255, 255, 0.05) 20px), repeating-linear-gradient(90deg,transparent,transparent 19px,rgba(255, 255, 255, 0.05) 20px);}.current-location {position: absolute;width: 20px;height: 20px;background: #3498db;border-radius: 50%;border: 3px solid white;box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.5);top: 50%;left: 50%;transform: translate(-50%, -50%);z-index: 5;}.current-location::after {content: "";position: absolute;width: 8px;height: 8px;background: white;border-radius: 50%;top: 50%;left: 50%;transform: translate(-50%, -50%);}.route {position: absolute;height: 5px;background: rgba(46, 204, 113, 0.8);border-radius: 5px;transform-origin: left;z-index: 2;}.destination-marker {position: absolute;width: 24px;height: 24px;background: #e74c3c;border-radius: 50% 50% 50% 0;transform: rotate(-45deg);box-shadow: 0 0 10px rgba(231, 76, 60, 0.7);z-index: 4;}.destination-marker::after {content: "";position: absolute;width: 12px;height: 12px;background: white;border-radius: 50%;top: 50%;left: 50%;transform: translate(-50%, -50%) rotate(45deg);}.navigation-controls {padding: 15px 20px;background: rgba(15, 30, 50, 0.95);display: flex;justify-content: space-between;z-index: 10;box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.2);}.nav-button {background: rgba(255, 255, 255, 0.1);border: none;color: white;padding: 12px 20px;border-radius: 15px;display: flex;flex-direction: column;align-items: center;gap: 5px;font-size: 0.85rem;cursor: pointer;transition: all 0.3s ease;width: 23%;}.nav-button:hover {background: rgba(255, 255, 255, 0.2);}.nav-button.active {background: #3498db;box-shadow: 0 0 15px rgba(52, 152, 219, 0.5);}.nav-button i {font-size: 1.2rem;}.destination-card {position: absolute;bottom: 90px;left: 20px;right: 20px;background: rgba(25, 40, 60, 0.95);border-radius: 15px;padding: 15px;z-index: 10;box-shadow: 0 5px 25px rgba(0, 0, 0, 0.3);transform: translateY(0);transition: transform 0.4s ease;}.destination-card.hidden {transform: translateY(150%);}.card-header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 15px;}.card-title {font-size: 1.1rem;font-weight: bold;}.close-card {background: rgba(255, 255, 255, 0.1);border: none;color: white;width: 30px;height: 30px;border-radius: 50%;cursor: pointer;}.destination-info {display: flex;gap: 15px;align-items: center;}.destination-icon {width: 50px;height: 50px;background: rgba(52, 152, 219, 0.2);border-radius: 12px;display: flex;justify-content: center;align-items: center;font-size: 1.5rem;}.destination-details {flex: 1;}.destination-name {font-size: 1.2rem;font-weight: bold;margin-bottom: 5px;}.destination-address {font-size: 0.9rem;color: rgba(255, 255, 255, 0.7);}.route-details {display: flex;justify-content: space-between;margin-top: 15px;padding-top: 15px;border-top: 1px solid rgba(255, 255, 255, 0.1);}.detail-item {text-align: center;}.detail-value {font-size: 1.2rem;font-weight: bold;color: #2ecc71;}.detail-label {font-size: 0.8rem;color: rgba(255, 255, 255, 0.6);}.start-navigation {background: #2ecc71;color: white;border: none;padding: 12px;border-radius: 12px;font-weight: bold;margin-top: 15px;width: 100%;cursor: pointer;transition: all 0.3s ease;}.start-navigation:hover {background: #27ae60;transform: translateY(-2px);}.navigation-status {position: absolute;top: 100px;left: 20px;right: 20px;background: rgba(25, 40, 60, 0.95);border-radius: 15px;padding: 15px;z-index: 10;box-shadow: 0 5px 25px rgba(0, 0, 0, 0.3);display: flex;gap: 15px;align-items: center;}.status-icon {width: 50px;height: 50px;background: rgba(231, 76, 60, 0.2);border-radius: 50%;display: flex;justify-content: center;align-items: center;font-size: 1.5rem;color: #e74c3c;}.status-details {flex: 1;}.status-title {font-size: 1.1rem;font-weight: bold;margin-bottom: 5px;}.status-info {font-size: 0.9rem;color: rgba(255, 255, 255, 0.7);}.next-turn {font-size: 2rem;color: #3498db;font-weight: bold;}@media (max-width: 480px) {.container {height: 100vh;border-radius: 0;}.nav-button {padding: 10px 5px;font-size: 0.75rem;}}</style>
</head>
<body><div class="container"><header><div class="logo"><i class="fas fa-location-arrow"></i><span>TS导航</span></div><div class="search-box"><i class="fas fa-search"></i><input type="text" placeholder="搜索地点或地址" id="searchInput"></div><div class="user-avatar">U</div></header><div class="map-container"><div class="map"><div class="map-overlay"></div><div class="current-location"></div><div class="destination-marker" id="destinationMarker" style="top: 30%; left: 70%;"></div><div class="route" id="routePath" style="top: 50%; left: 50%; width: 0; transform: rotate(45deg);"></div></div><div class="destination-card" id="destinationCard"><div class="card-header"><div class="card-title">目的地详情</div><button class="close-card" id="closeCard"><i class="fas fa-times"></i></button></div><div class="destination-info"><div class="destination-icon"><i class="fas fa-building"></i></div><div class="destination-details"><div class="destination-name" id="destName">科技大厦</div><div class="destination-address" id="destAddress">创新路88号</div></div></div><div class="route-details"><div class="detail-item"><div class="detail-value" id="distance">3.5</div><div class="detail-label">公里</div></div><div class="detail-item"><div class="detail-value" id="time">15</div><div class="detail-label">分钟</div></div><div class="detail-item"><div class="detail-value" id="eta">10:30</div><div class="detail-label">到达</div></div></div><button class="start-navigation" id="startNavigation"><i class="fas fa-play"></i> 开始导航</button></div><div class="navigation-status" id="navStatus" style="display: none;"><div class="status-icon"><i class="fas fa-directions"></i></div><div class="status-details"><div class="status-title">导航中 - <span id="navDistance">3.5公里</span></div><div class="status-info">沿当前道路直行 <span id="navNext">500米</span></div></div><div class="next-turn"><i class="fas fa-arrow-right"></i></div></div></div><div class="navigation-controls"><button class="nav-button active"><i class="fas fa-home"></i><span>首页</span></button><button class="nav-button"><i class="fas fa-search-location"></i><span>探索</span></button><button class="nav-button"><i class="fas fa-route"></i><span>路线</span></button><button class="nav-button"><i class="fas fa-cog"></i><span>设置</span></button></div></div><script>// 使用TypeScript语法实现导航逻辑class NavigationApp {constructor() {// 获取DOM元素this.destinationCard = document.getElementById('destinationCard');this.closeCardBtn = document.getElementById('closeCard');this.startNavigationBtn = document.getElementById('startNavigation');this.navStatus = document.getElementById('navStatus');this.destName = document.getElementById('destName');this.destAddress = document.getElementById('destAddress');this.distanceEl = document.getElementById('distance');this.timeEl = document.getElementById('time');this.etaEl = document.getElementById('eta');this.navDistance = document.getElementById('navDistance');this.navNext = document.getElementById('navNext');this.searchInput = document.getElementById('searchInput');this.routePath = document.getElementById('routePath');this.destinationMarker = document.getElementById('destinationMarker');// 初始化事件监听this.initEventListeners();// 模拟初始数据this.updateDestinationInfo("科技大厦", "创新路88号", 3.5, 15);}// 初始化事件监听器initEventListeners() {this.closeCardBtn.addEventListener('click', () => {this.destinationCard.classList.add('hidden');});this.startNavigationBtn.addEventListener('click', () => {this.startNavigation();});this.searchInput.addEventListener('focus', () => {this.showSearchResults();});// 添加地图点击事件来显示目的地卡片document.querySelector('.map').addEventListener('click', (e) => {if (e.target === this.destinationMarker) return;this.destinationCard.classList.remove('hidden');});}// 更新目的地信息updateDestinationInfo(name, address, distance, time) {this.destName.textContent = name;this.destAddress.textContent = address;this.distanceEl.textContent = distance.toFixed(1);this.timeEl.textContent = time;// 计算预计到达时间const now = new Date();now.setMinutes(now.getMinutes() + time);this.etaEl.textContent = `${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')}`;}// 开始导航startNavigation() {this.destinationCard.classList.add('hidden');this.navStatus.style.display = 'flex';// 更新导航信息this.navDistance.textContent = `${this.distanceEl.textContent}公里`;this.navNext.textContent = '500米';// 动画显示路线this.animateRoute();// 模拟导航更新this.simulateNavigation();}// 动画显示路线animateRoute() {this.routePath.style.width = '0';this.routePath.style.opacity = '1';setTimeout(() => {this.routePath.style.transition = 'width 1.5s ease-in-out';this.routePath.style.width = '250px';}, 100);}// 模拟导航过程simulateNavigation() {let distance = parseFloat(this.distanceEl.textContent);let remaining = distance;let nextTurn = 0.5;const interval = setInterval(() => {remaining -= 0.1;if (remaining < 0) remaining = 0;this.navDistance.textContent = `${remaining.toFixed(1)}公里`;nextTurn -= 0.1;if (nextTurn < 0) {nextTurn = 0.5;this.updateNextTurn();}this.navNext.textContent = `${Math.round(nextTurn * 1000)}米`;if (remaining <= 0) {clearInterval(interval);this.navigationComplete();}}, 3000);}// 更新下一个转弯指示updateNextTurn() {const turnIcon = document.querySelector('.next-turn');const turns = [{icon: 'fa-arrow-right', color: '#3498db'},{icon: 'fa-arrow-left', color: '#e74c3c'},{icon: 'fa-undo', color: '#9b59b6'},{icon: 'fa-arrow-up', color: '#2ecc71'}];const randomTurn = turns[Math.floor(Math.random() * turns.length)];turnIcon.innerHTML = `<i class="fas ${randomTurn.icon}"></i>`;turnIcon.style.color = randomTurn.color;}// 导航完成navigationComplete() {this.navStatus.style.display = 'none';this.destinationCard.classList.remove('hidden');// 显示到达信息this.destName.textContent = "到达目的地";this.destAddress.textContent = "导航结束";this.startNavigationBtn.innerHTML = '<i class="fas fa-redo"></i> 重新导航';this.startNavigationBtn.style.background = '#3498db';// 重置路线this.routePath.style.opacity = '0';}// 显示搜索结果(模拟)showSearchResults() {// 在实际应用中,这里会有搜索API调用console.log("显示搜索结果...");this.searchInput.blur(); // 仅用于演示// 模拟选择新目的地setTimeout(() => {this.updateDestinationInfo("中央公园", "和平路100号", 5.2, 20);this.destinationCard.classList.remove('hidden');// 移动目的地标记this.destinationMarker.style.top = '25%';this.destinationMarker.style.left = '35%';// 重置路线this.routePath.style.opacity = '0';setTimeout(() => {this.routePath.style.top = '50%';this.routePath.style.left = '50%';this.routePath.style.transform = 'rotate(135deg)';}, 300);}, 1000);}}// 初始化应用document.addEventListener('DOMContentLoaded', () => {const app = new NavigationApp();});</script>
</body>
</html>

http://www.lqws.cn/news/497503.html

相关文章:

  • Arrays.asList和 List<String> list = new ArrayList<>();有什么区别
  • 飞算 JavaAI:重构 Java 开发范式的工程化实践
  • 可以把一套三维设计软件装在云服务器上5人同时并发使用吗
  • 通信网络编程3.0——JAVA
  • Deepoc大模型重构核工业智能基座:混合增强架构与安全增强决策技术​
  • Node.js 中的 JWT 认证:从生成到验证的完整指南
  • RPG38.角色受击
  • 配置@为src
  • React Native【实用教程】(含图标方案,常用第三库,动画,内置组件,内置Hooks,内置API,自定义组件,创建项目等)
  • Java并发编程中高效缓存设计的哲学
  • 实验九:RIPv2协议配置与分析
  • MySQL 8.x配置MGR高可用+ProxySQL读写分离(二):ProxySQL配置MySQL代理及读写分离
  • CRC3校验算法
  • Stable Diffusion 项目实战落地:AI绘画与文案创作的魔法 第一篇 ——让你的小说推文秒变视觉与故事双料爆款!
  • 零基础学习RabbitMQ(2)--Linux安装RabbitMQ
  • github常用插件
  • 基于SpringBoot + Vue 的网上拍卖系统
  • 使用AI开发招聘网站(100天AI编程实验)
  • C++ 第二阶段:继承与多态 - 第二节:虚函数与虚函数表
  • DataWhale-零基础络网爬虫技术(三、爬虫进阶技术)
  • 短期项目与长期目标如何同时兼顾
  • SpringCloud系列(32)--使用Hystrix进行全局服务降级
  • 基于分布式部分可观测马尔可夫决策过程与联邦强化学习的低空经济智能协同决策框架
  • 基于协议转换的 PROFIBUS DP 与 ETHERNET/IP 在石化生产中的协同运行实践
  • SwiftUI学习笔记day4: Lecture 4 | Stanford CS193p 2023
  • Lnmp和XunRuiCMS一键部署(Rocky linux)
  • Spring Boot 集成 Apache Kafka 实战指南
  • WebRTC(八):SDP
  • Origin绘制三Y轴柱状图、点线图、柱状点线图
  • pyhton基础【15】函数进阶一