• TypeScript 地图标记案例


    TypeScript 地图案例

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

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

    案例准备

    安装依赖

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

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

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

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

    npm install parcel@2.4.1 -g
    
    • 1

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

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

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

    在这里插入图片描述

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

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

    
    
    <script src="./src/index.ts" type="module">script>
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    # 启动服务器
    parcel index.html
    
    • 1
    • 2

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

    创建用户

    在 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()),
    		}
    	}
    }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

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

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

    在这里插入图片描述

    在浏览器 查看

    在这里插入图片描述

    创建公司

    在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());
    		};
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    有图有真相

    在这里插入图片描述

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

    在这里插入图片描述

    在浏览器查看

    在这里插入图片描述

    创建地图

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

    在这里插入图片描述

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

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

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

    <style>
      html, body, #map {
        height: 100%;
        margin: 0;
        padding: 0;
      }
    style>
    <div id="map">div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    有图有真相

    在这里插入图片描述

    在 Usrer.ts 下 创建地图

    new google.maps.Map(document.getElementById("map"), {
    	zoom: 1,
    	center: {
    		lat: 0,
    		lng: 0,
    	}
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    有图有真相

    在这里插入图片描述

    封装地图类

    目标:
    创建 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,
    			},
    		});
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

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

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

    有图有真相

    在这里插入图片描述

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

    地图标记

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

    效果图:

    在这里插入图片描述

    在 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,
    			}
    		})
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    然后在 index.ts 调用

    // src/index.ts
    const map = new Map("map");
    map.addUserMarker(user);
    map.addCompanyMarker(company);
    
    • 1
    • 2
    • 3
    • 4

    消除重复的代码

    在目前的代码中 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,
    		}
    	})
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

    在 index.ts 修改

    // 显示标记
    map.addMarker(user)
    map.addMarker(company)
    // map.addUserMarker(user)
    // map.addCompanyMarker(company)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    增加程序扩展性

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

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

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

    解决方法:

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

    在 Map.ts 定义接口

    interface Mappable {
    	location: {
    		lat: number;
    		lng: number;
    	};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在目前的代码中 不论是 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);
    		});
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    使用接口约束类

    目标 :
    使用接口约束

    在 src 下 的 Map.ts

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

    在 User.ts 下

    import {Mappable} from "./Map";
    
    export class User implements Mappable {
    	markerContent(): string {
    		return `用户名: ${this.name}`;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在 Company.ts 下

    import {Mappable} from "./Map";
    
    export class Company implements Mappable {
    	markerContent(): string {
    		return `
    			

    公司名称: ${this.companyName}

    公司口号: ${this.catchPhrase}
    ` } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    完整代码

    访问 gitee

  • 相关阅读:
    Java高并发编程实战1,那些年学过的锁
    【树莓派不吃灰】Linux服务器篇(核心概念)
    Excel画图
    分布式Netty集群方案 加代码 SpringBoot 版
    ffmpeg 通过遍历视频流,对视频帧进行打标
    Mysql数据库(3)—架构和日志
    6、MySQL——模糊查询、字段控制查询
    Oracle SQL - HAVING和分析函数的执行顺序
    云原生Kubernetes: 云主机部署K8S 1.30版本 单Master架构
    Linux下gdb调试打印字符串
  • 原文地址:https://blog.csdn.net/lhblmd/article/details/126728598