tilehash
v1.1.2
Published
Efficient hash encoding library for map tiles (ZXY), supporting encoding, decoding, and spatial calculations
Downloads
20
Maintainers
Readme
tilehash
专为地图瓦片设计的高性能哈希编码库——解决GIS/地图开发者面临的ZXY坐标存储冗余、空间计算复杂等核心痛点。
- 用紧凑哈希(如
"k8q8y")替代冗长的ZXY坐标(z=10, x=345, y=678) - 支持8+种空间计算(邻近查询、距离估算、区域覆盖等)
- 无缝运行于Node.js/浏览器环境,提供完整TypeScript类型安全
- 核心方法每秒可处理百万级编码/解码操作
🌟 核心优势
1. 专为地图瓦片设计,比通用编码工具更专业
普通哈希工具(如MD5)或地理编码(如Geohash)无法适配地图瓦片的ZXY体系,而tilehash深度优化瓦片场景:
| 工具 | 目标场景 | 瓦片专属特性 | 空间计算能力 | |---------------------|------------------|-------------------------------|-----------------------------| | tilehash | 地图瓦片(ZXY) | ✅ 缩放级别前缀、边界循环处理 | 8+种(邻近、距离、包含等) | | Geohash | 地理坐标(经纬度)| ❌ 无瓦片适配能力 | 仅2种(邻近、包含) | | 普通哈希(如MD5) | 通用数据 | ❌ 无空间关联性 | 0种(仅哈希,无计算能力) |
2. 紧凑高效,大幅降低存储与传输成本
针对地图瓦片的ZXY分布特性优化哈希长度,兼顾压缩率与可读性:
- 动态长度:根据缩放级别自动调整(z=10时约5个字符,z=25时约8个字符)
- 存储节省:相比原始ZXY字符串(如
"z=10,x=345,y=678"),存储体积减少60%+ - 传输优化:更小的哈希体积可加快API请求速度,尤其适合地图瓦片预加载、缓存同步等场景
3. 性能强劲,支撑高并发场景
基于位运算与预计算查表优化,核心方法性能达到工业级标准:
性能测试数据(Node.js v18.16.0,Intel i7-12700H,10万次迭代)
| 方法 | 平均耗时(微秒/次) | 吞吐量(次/秒) | 开发者价值 |
|---------------------|---------------------|------------------------|-----------------------------|
| isValid(验证) | 0.21 – 0.28 | 350万 – 480万 | 每秒验证480万哈希,无卡顿 |
| encode(编码) | 0.62 – 1.85 | 54万 – 160万 | 高并发场景下每秒编码160万瓦片 |
| decode(解码) | 0.87 – 2.63 | 38万 – 115万 | 快速解析哈希,加速瓦片加载 |
| getNeighbors(邻近查询) | 8.76 – 23.74 | 4.2万 – 11.4万 | 每秒预加载10万+邻近瓦片 |
📌 核心优化手段:位运算批量处理二进制数据 + 预计算幂值/掩码表,避免重复计算
4. 易用性拉满,降低开发成本
无需复杂配置,3行代码即可上手,同时提供完善的开发者友好特性:
- TypeScript原生支持:完整类型定义,VS Code等IDE自动补全,减少类型错误
- 友好错误提示:参数非法时返回明确信息(如
"z必须在0-30之间",而非模糊的“参数错误”) - 零依赖:无额外第三方依赖,包体积<5KB(gzip后),不增加项目负担
5. 跨环境兼容,覆盖全场景需求
无需担心环境差异,一套代码可运行于所有主流开发场景:
| 运行环境 | 支持版本 | 依赖要求 | |---------------------|--------------------|---------------------------| | Node.js | ✅ v14.0.0+ | 无(原生支持) | | 浏览器 | ✅ Chrome/Firefox/Safari 13+ | 支持ES5+语法 | | 前端框架 | ✅ React/Vue/Angular | 无框架锁定,直接导入使用 |
🚀 典型使用场景
1. 地图瓦片缓存优化
- 问题:将ZXY坐标(如
"z10x345y678")存入localStorage或后端缓存时,字符串冗长、占用空间大。 - 解决方案:用tilehash编码为短字符串,减少60%+缓存体积。
// 编码后存入缓存 const hash = TileHash.encode(10, 345, 678); // "k8q8y" localStorage.setItem('cached_tile', hash); // 从缓存解码 const cachedHash = localStorage.getItem('cached_tile'); const { z, x, y } = TileHash.decode(cachedHash); // 恢复为z=10, x=345, y=678
2. 瓦片预加载(用户地图拖拽场景)
- 问题:用户拖拽地图时,需提前加载周边8个瓦片以避免空白,手动计算ZXY邻近值繁琐易出错。
- 解决方案:1行代码获取所有邻近瓦片哈希,直接用于预加载。
// 获取当前瓦片的8个邻近瓦片 const currentHash = "k8q8y"; const neighborHashes = TileHash.getNeighbors(currentHash); // 结果:["k8q8x", "k8q8z", "k8q90", ...](8个邻近瓦片) // 批量预加载邻近瓦片 neighborHashes.forEach(hash => { const { z, x, y } = TileHash.decode(hash); loadTile(z, x, y); // 调用瓦片加载函数 });
3. LBS应用空间搜索
- 问题:需查询“某瓦片1公里范围内的POI”,直接用经纬度范围计算效率低。
- 解决方案:结合距离估算与区域覆盖,快速锁定目标瓦片,缩小查询范围。
// 1. 估算1公里对应的瓦片范围(假设当前瓦片哈希为"k8q8y") const centerHash = "k8q8y"; const { z } = TileHash.decode(centerHash); // 2. 获取1公里范围对应的经纬度边界(需结合业务逻辑微调) const bounds = { minLng: 116.3, maxLng: 116.4, minLat: 39.9, maxLat: 40.0 }; // 3. 获取边界内所有瓦片,仅查询这些瓦片的POI const targetHashes = TileHash.getHashesInBounds( bounds.minLng, bounds.maxLng, bounds.minLat, bounds.maxLat, z ); // 4. 按瓦片哈希批量查询POI(效率远高于全局经纬度查询) const pois = await queryPoisByTileHashes(targetHashes);
🔧 快速开始
1. 安装
通过npm或yarn安装:
# npm
npm install tilehash --save
# yarn
yarn add tilehash2. 基础使用示例
Node.js/CommonJS
const { TileHash } = require('tilehash');
// 1. 编码:ZXY → 哈希
const z = 10; // 缩放级别(0-30)
const x = 345; // 瓦片列号(0 ≤ x ≤ 2^z - 1)
const y = 678; // 瓦片行号(0 ≤ y ≤ 2^z - 1)
const hash = TileHash.encode(z, x, y);
console.log('编码结果:', hash); // 输出示例:"k8q8y"
// 2. 解码:哈希 → ZXY
const decoded = TileHash.decode(hash);
console.log('解码结果:', decoded); // 输出:{ z: 10, x: 345, y: 678 }
// 3. 验证哈希合法性
const isValid = TileHash.isValid(hash);
console.log('是否合法:', isValid); // 输出:trueTypeScript/ES Modules
import { TileHash, TileCoordinates } from 'tilehash';
// 编码(类型自动推导)
const hash: string = TileHash.encode(10, 345, 678);
// 解码(类型安全,返回TileCoordinates接口)
const coords: TileCoordinates = TileHash.decode(hash);
console.log(coords.z, coords.x, coords.y); // 输出:10 345 678📚 完整API文档
所有方法均通过TileHash类静态调用,以下是核心API说明:
1. 核心编码/解码
TileHash.encode(z: number, x: number, y: number): string
将ZXY瓦片坐标编码为哈希字符串。
- 参数:
z:缩放级别(0-30,超出范围会抛出错误)x:瓦片列号(需满足0 ≤ x ≤ 2^z - 1)y:瓦片行号(需满足0 ≤ y ≤ 2^z - 1)
- 返回:紧凑的瓦片哈希字符串
- 抛出错误:参数超出有效范围时(如
z=31或x=-1)
TileHash.decode(hash: string): TileCoordinates
将哈希字符串解码为ZXY坐标。
- 参数:
hash:合法的tilehash字符串(长度≥2)
- 返回:
TileCoordinates对象(包含z/x/y属性) - 抛出错误:哈希非法(如字符无效、长度不匹配缩放级别)
TileHash.isValid(hash: string): boolean
验证哈希字符串是否合法(避免解码时抛出错误)。
- 参数:
hash:待验证的字符串 - 返回:
true(合法)/false(非法)
2. 空间计算方法
TileHash.getNeighbors(hash: string, wrapEdges?: boolean): string[]
获取指定瓦片的8个邻近瓦片哈希。
- 参数:
hash:目标瓦片的哈希wrapEdges:是否启用地图边界循环(默认true,适合全球地图,如左边界邻接右边界)
- 返回:8个邻近瓦片的哈希数组(顺序:上左→上→上右→左→右→下左→下→下右)
- 说明:
wrapEdges=false时,边界外瓦片返回空字符串
TileHash.contains(parentHash: string, childHash: string): boolean
判断父瓦片(低缩放级别)是否包含子瓦片(高缩放级别)。
- 参数:
parentHash:父瓦片哈希(低缩放级别,如z=5)childHash:子瓦片哈希(高缩放级别,如z=10)
- 返回:
true(包含)/false(不包含) - 逻辑:父瓦片哈希是子瓦片哈希的前缀(如z=5的哈希是其所有z=10子瓦片的前缀)
TileHash.estimateDistance(hash1: string, hash2: string): number
估算两个瓦片中心点之间的直线距离(单位:米)。
- 参数:
hash1:第一个瓦片的哈希hash2:第二个瓦片的哈希
- 返回:距离(米,基于地球赤道周长近似计算)
- 说明:自动将两个瓦片缩放至同一级别(取较高的缩放级别)以保证精度
TileHash.getHashesInBounds(minLng: number, maxLng: number, minLat: number, maxLat: number, z: number): string[]
获取覆盖指定经纬度范围的所有瓦片哈希。
- 参数:
minLng/maxLng:最小/最大经度(-180 ≤ 经度 ≤ 180)minLat/maxLat:最小/最大纬度(-85.05 ≤ 纬度 ≤ 85.05,地球瓦片有效范围)z:目标缩放级别
- 返回:范围内所有瓦片的哈希数组
- 优化:z>20时自动限制范围为1°×1°,避免生成百万级瓦片导致内存溢出
TileHash.scaleToLevel(hash: string, targetZ: number): string
将瓦片哈希缩放至指定缩放级别(放大/缩小)。
- 参数:
hash:原始瓦片哈希targetZ:目标缩放级别(0-30)
- 返回:目标级别的瓦片哈希
- 逻辑:
- 放大(
targetZ > 原z):坐标 × 2^(目标z-原z)(1个瓦片拆分为4个) - 缩小(
targetZ < 原z):坐标 ÷ 2^(原z-目标z)(4个瓦片合并为1个)
- 放大(
📄 许可证
本项目基于MIT许可证开源,可自由用于商业和非商业项目。详见LICENSE文件。
