TypeScript 地图标记案例

TypeScript 地图案例

效果图
在这里插入图片描述
需求:
随机创建用户和公司 并把它们的位置标注到地图中

  • 案例准备
    - 安装依赖
    - 创建应用
  • 创建用户
  • 创建公司
  • 创建地图
  • 封装地图类
  • 地图标记
  • 消除重复的代码
  • 增加程序扩展性
  • 创建标记弹框
  • 使用接口约束类

案例准备

安装依赖

parcel 是前端构建工具 类似于 webpack parcel 的最大的特点是打包速度非常快 而且零配置开箱即用

为什么 需要模块打包工具?

ts -> js -> 代码不能直接运行,浏览器不识别模块。
ts -> js -> 模块打包 -> 在浏览器中直接运行。

在 cmd 终端 输入以下命令 安装

npm install parcel@2.4.1 -g

安装成功后 在cmd 输入 npm list -y 查看
在这里插入图片描述
使用 @faker-js/faker 可以随机创建模拟数据,当前案例中用于随机生成用户和公司信息

在项目根目录
在这里插入图片描述

@types/google.maps 是谷歌地图的 TS 类型声明文件。

在这里插入图片描述

创建应用
# 在桌面或者任意位置  创建文件夹 case
# 创建项目工程文件
npm init -y
# 在项目创建   src  文件夹
# 创建  index.html  页面入口
# 在src  里 创建   index.ts  应用逻辑入口

具体长这样
在这里插入图片描述

<!-- 在应用页面入口文件中导入应用逻辑入口文件 -->
<!-- 当 parcel 检测到引入的是 TS 文件时, parcel 会先将其转换为 JS, 再将 TS 文件替换为转换后的 JS  -->
<script src="./src/index.ts" type="module"></script>

在这里插入图片描述

# 启动服务器
parcel index.html

在项目的 根目录 打开终端 输入命令 启动服务
在这里插入图片描述

创建用户

在 src 文件夹里 创建 用户的文件 User.ts

代码:

// 导入  faker
import faker from "@faker-js/faker";

// 创建  用户  类
export class User {
	// 姓名   string类型
	name: string;
	// 位置
	location: {
		// 纬度   number 类型
		lat: number;
		// 经度   number 类型
		lng: number;
	};
	// 
	constructor() {
		// 随机创建用户姓名
		this.name = faker.name.firstName();
		// 随机创建用户位置
		this.location = {
			lat: parseFloat(faker.address.latitude()),
			lng: parseFloat(faker.address.longitude()),
		}
	}
}  

有图有真相
在这里插入图片描述

// 在  src 下的  index.ts 里
// 导入  User  类
import {User} from "./User";
// 创建用户
const user = new User();
// 测试  在控制台输出用户信息
console.log(user);

在这里插入图片描述

在浏览器 查看

在这里插入图片描述

创建公司

在src 文件夹下 创建 Company.ts 公司

//  src 下  的  Company.ts
//  导入  faker 
import faker from "@faker-js/faker";

// 创建公司类
export class Company {
	// 公司名称  string 类型
	companyName: string;
	// 公司口号  string 类型
	catchPhrase: string;
	// 公司位置  number  类型
	location: {
		//  纬度
		lat: number;
		//  经度
		lng: number;
	};
	//  随机创建
	constructor() {
		// 随机创建公司名称
		this.companyName = faker.company.companyName();
		// 随机创建公司口号
		this.catchPhrase = faker.company.catchPhrase();
		// 随机创建公司位置
		this.location = {
			lat: parseFloat(faker.address.latitude());
			lng: parseFloat(faker.address.longitude());
		};
	}
}

有图有真相

在这里插入图片描述

// 在  src 下的  index.ts
// 导入  Company 类
import { Company } from "./Company";
// 创建公司
const company = new Company();
// 测试: 在控制台中输出公司信息
console.log(company);

在这里插入图片描述

在浏览器查看

在这里插入图片描述

创建地图

目标:
在浏览器页面 显示 如下图

在这里插入图片描述

先在 应用页面 index.html 入口文件 添加 Google Map API

<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBNLrJhOMz6idD05pzfn5lhA-TAw-mAZCU"></script>

然后 在 index.html 文件中创建用户放地图的容器

<style>
  html, body, #map {
    height: 100%;
    margin: 0;
    padding: 0;
  }
</style>
<div id="map"></div>

有图有真相

在这里插入图片描述

在 Usrer.ts 下 创建地图

new google.maps.Map(document.getElementById("map"), {
	zoom: 1,
	center: {
		lat: 0,
		lng: 0,
	}
})

有图有真相

在这里插入图片描述

封装地图类

目标:
创建 Map 类 在类中封装和地图的相关的业务逻辑 以后在创建地图时只需要对该类进行 实例化即可

( 现在只是地图的代码 以后有了别的代码 不能都写在一个文件里 不容易管理 )

在 src 下 创建 Map.ts 文件

代码:

//  src/ Map.ts
// 创建地图  类
export class Map{
	// 用于存储地图实例
	private googleMap: google.maps.Map;
	// 创建地图
	constructor(divId: string) {
		this.googleMaps = new google.maps.Map(document.getElementById(divId)!, {
			zoom: 1,
			center: {
				lat: 0,
				lng: 0,
			},
		});
	}
}

然后在 index.ts 文件 引入 地图类

// src/index.ts
import { Map } from "./Map";
// 创建地图
new Map("map");

有图有真相

在这里插入图片描述

把 之前 没封装的 地图 代码 删掉!!!!!!!

地图标记

目标:
随机 显示地图上的 标记 浏览器刷新 位置发生变化

效果图:

在这里插入图片描述

在 src 下的 Map.ts 下
代码:

// src/Map.ts
// 导入  用户  和   公司
import {Company} from "./Company";
import {User} from "./User";
// 地图  类
export class Map {
	/*......
		用于存储地图实例
	  ......
	*/

	
	// 在地图中标记用户位置
	addUserMarker(user: User) {
		new goole.maps.Marker({
			map: this.googleMap,
			position: {
				lat: user.location.lat,
				lng: user.location.lng,
			}
		})
	}
	
	// 在地图标记公司位置
	addCompanyMarker(company: Company) {
		new goole.maps.Marker({
			map: this.googleMap,
			position: {
				lat: company.location.lat,
				lng: company.location.lng,
			}
		})
	}
}

然后在 index.ts 调用

// src/index.ts
const map = new Map("map");
map.addUserMarker(user);
map.addCompanyMarker(company);

消除重复的代码

在目前的代码中 addUserMarker 和 addCompanyMarker 两个方法中的代码是一模一样的 为消除重复代码 决定把两个方法进行合并 并把参数更国改为 User 和 Company 的联合类型

在 src 下的 Map.ts 下
代码:

// 

export class Map {
	// 在地图中标记位置
	addMarker(mappable: User | Company) {
	new google.maps.Marker({
		map: this.google,
		position: {
			lat: mappable.location.lat,
			lng: mappable.location.lng,
		}
	})
}
}

由于 location 属性是 User Company 类型中的公共属性 所以在 addMarker 方法中可以直接调用

在 index.ts 修改

// 显示标记
map.addMarker(user)
map.addMarker(company)
// map.addUserMarker(user)
// map.addCompanyMarker(company)

在这里插入图片描述

增加程序扩展性

虽然重复代码被消除了 但是这不利于程序的扩展性 如果要在地图中标记其他物体的位置信息 那么就只能在参数后面不断的罗例其他物体的类型信息了

addMarker(mappable: User | Company | Park | School) {}

如上面 不能 以后多了个 停车位置 。。。就加一个 这样比较麻烦

解决方法:

解决问题的方式是定义通过的类型接口 不论是什么数据类型只要满足接口中定义的规范即可 从而解决程序扩展性问题

在 Map.ts 定义接口

interface Mappable {
	location: {
		lat: number;
		lng: number;
	};
}

在目前的代码中 不论是 User 类的实例还是 Company 类的实例 都是满足 Mappable 接口规范的

在这里插入图片描述

创建标记弹框

目标:
在点击地图中的标记时 通过弹框显示标记信息

在 Map.ts 下

// src/Map.ts
export class Map{
	// 在地图中标记位置
	addMarker(mappable: Mappable) {
		// 创建标记
		const marker = new google.maps.Marker();
		// 为标记绑定点击事件
		marker.addListener("click", () => {
			// 创建弹窗
			const infoWindow = new google.maps.InfoWindow({
				content: "Hello I am marker content"
			});
			// 打开弹框并指定弹框在那个地图的那个的标记的位置上弹出
			infoWindow.open(this.googleMap, marker);
		});
	}
}

在这里插入图片描述

使用接口约束类

目标 :
使用接口约束

在 src 下 的 Map.ts

export interface Mappable {
	markerContent(): string;
}
const infoWindow = new google.maps.InfoWindow({
	content: mappable.markerContent(),
})

在 User.ts 下

import {Mappable} from "./Map";

export class User implements Mappable {
	markerContent(): string {
		return `用户名: ${this.name}`;
	}
}

在 Company.ts 下

import {Mappable} from "./Map";

export class Company implements Mappable {
	markerContent(): string {
		return `
			<h3>公司名称: ${this.companyName}<h3/>
			<h5>公司口号: ${this.catchPhrase}<h5/>
		`
	}
}

完整代码

访问 gitee

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值