hookehuyr

fix 代码备注

1 /* 1 /*
2 * @Date: 2025-01-22 11:45:30 2 * @Date: 2025-01-22 11:45:30
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-02-08 10:24:25 4 + * @LastEditTime: 2025-02-24 13:21:58
5 * @FilePath: /map-demo/src/utils/TileCutter.js 5 * @FilePath: /map-demo/src/utils/TileCutter.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -21,27 +21,38 @@ export function TileCutter(imageURL, bounds, zoomLevel) { ...@@ -21,27 +21,38 @@ export function TileCutter(imageURL, bounds, zoomLevel) {
21 } 21 }
22 22
23 23
24 +/**
25 + * 将图片切割成瓦片并打包下载
26 + * @param {HTMLImageElement} image - 要切割的图片元素
27 + * @param {L.LatLngBounds} bounds - 图片边界范围,包含西南角和东北角的经纬度
28 + * @param {number} zoomLevel - 地图缩放级别
29 + */
24 function sliceImageToTiles(image, bounds, zoomLevel) { 30 function sliceImageToTiles(image, bounds, zoomLevel) {
31 + // 创建画布及上下文
25 const canvas = document.createElement("canvas"); 32 const canvas = document.createElement("canvas");
26 const ctx = canvas.getContext("2d"); 33 const ctx = canvas.getContext("2d");
27 34
28 - const imgWidth = image.width; 35 + // 获取原始图片尺寸
29 - const imgHeight = image.height; 36 + const imgWidth = image.width; // 图片原始宽度
37 + const imgHeight = image.height; // 图片原始高度
30 38
31 - const southWest = bounds.getSouthWest(); 39 + // 获取边界经纬度
32 - const northEast = bounds.getNorthEast(); 40 + const southWest = bounds.getSouthWest(); // 西南角坐标
41 + const northEast = bounds.getNorthEast(); // 东北角坐标
33 42
34 - const lonStart = southWest.lng; 43 + // 提取边界经纬度值
35 - const latStart = southWest.lat; 44 + const lonStart = southWest.lng; // 起始经度
36 - const lonEnd = northEast.lng; 45 + const latStart = southWest.lat; // 起始纬度
37 - const latEnd = northEast.lat; 46 + const lonEnd = northEast.lng; // 结束经度
47 + const latEnd = northEast.lat; // 结束纬度
38 48
39 - let tileStartX = lonToTileX(lonStart, zoomLevel); 49 + // 计算瓦片坐标范围
40 - let tileEndX = lonToTileX(lonEnd, zoomLevel); 50 + let tileStartX = lonToTileX(lonStart, zoomLevel); // 起始瓦片X坐标
41 - let tileStartY = latToTileY(latEnd, zoomLevel); // 取 latEnd 作为起点 51 + let tileEndX = lonToTileX(lonEnd, zoomLevel); // 结束瓦片X坐标
42 - let tileEndY = latToTileY(latStart, zoomLevel); // 取 latStart 作为终点 52 + let tileStartY = latToTileY(latEnd, zoomLevel); // 起始瓦片Y坐标
53 + let tileEndY = latToTileY(latStart, zoomLevel); // 结束瓦片Y坐标
43 54
44 - // 确保 tileStartX <= tileEndX,tileStartY <= tileEndY 55 + // 确保瓦片坐标范围正确(起始值小于结束值)
45 tileStartX = Math.min(tileStartX, tileEndX); 56 tileStartX = Math.min(tileStartX, tileEndX);
46 tileEndX = Math.max(tileStartX, tileEndX); 57 tileEndX = Math.max(tileStartX, tileEndX);
47 tileStartY = Math.min(tileStartY, tileEndY); 58 tileStartY = Math.min(tileStartY, tileEndY);
...@@ -49,9 +60,11 @@ function sliceImageToTiles(image, bounds, zoomLevel) { ...@@ -49,9 +60,11 @@ function sliceImageToTiles(image, bounds, zoomLevel) {
49 60
50 const scaleFactor = 2; // 调高分辨率倍率 61 const scaleFactor = 2; // 调高分辨率倍率
51 62
63 + // 设置画布尺寸
52 canvas.width = tileSize * scaleFactor; 64 canvas.width = tileSize * scaleFactor;
53 canvas.height = tileSize * scaleFactor; 65 canvas.height = tileSize * scaleFactor;
54 66
67 + // 设置画布缩放
55 ctx.scale(scaleFactor, scaleFactor); 68 ctx.scale(scaleFactor, scaleFactor);
56 69
57 const zip = new JSZip(); // 创建一个 JSZip 实例,用来打包所有瓦片 70 const zip = new JSZip(); // 创建一个 JSZip 实例,用来打包所有瓦片
...@@ -62,26 +75,28 @@ function sliceImageToTiles(image, bounds, zoomLevel) { ...@@ -62,26 +75,28 @@ function sliceImageToTiles(image, bounds, zoomLevel) {
62 for (let tileX = tileStartX; tileX <= tileEndX; tileX++) { 75 for (let tileX = tileStartX; tileX <= tileEndX; tileX++) {
63 for (let tileY = tileStartY; tileY <= tileEndY; tileY++) { 76 for (let tileY = tileStartY; tileY <= tileEndY; tileY++) {
64 // 计算当前瓦片的经纬度范围 77 // 计算当前瓦片的经纬度范围
65 - const tileLonStart = tileX * 360 / Math.pow(2, zoomLevel) - 180; 78 + const tileLonStart = tileX * 360 / Math.pow(2, zoomLevel) - 180; // 瓦片起始经度
66 - const tileLonEnd = (tileX + 1) * 360 / Math.pow(2, zoomLevel) - 180; 79 + const tileLonEnd = (tileX + 1) * 360 / Math.pow(2, zoomLevel) - 180; // 瓦片结束经度
67 - const tileLatStart = Math.atan(Math.sinh(Math.PI * (1 - 2 * (tileY + 1) / Math.pow(2, zoomLevel)))) * 180 / Math.PI; 80 + const tileLatStart = Math.atan(Math.sinh(Math.PI * (1 - 2 * (tileY + 1) / Math.pow(2, zoomLevel)))) * 180 / Math.PI; // 瓦片起始纬度
68 - const tileLatEnd = Math.atan(Math.sinh(Math.PI * (1 - 2 * tileY / Math.pow(2, zoomLevel)))) * 180 / Math.PI; 81 + const tileLatEnd = Math.atan(Math.sinh(Math.PI * (1 - 2 * tileY / Math.pow(2, zoomLevel)))) * 180 / Math.PI; // 瓦片结束纬度
69 - 82 +
70 - // 计算图片在当前瓦片中的位置和尺寸 83 + // 计算图片在当前瓦片中的位置和尺寸(像素坐标)
71 - const tileImgX = (lonStart - tileLonStart) / (tileLonEnd - tileLonStart) * tileSize; 84 + const tileImgX = (lonStart - tileLonStart) / (tileLonEnd - tileLonStart) * tileSize; // 图片在瓦片中的X坐标
72 - const tileImgY = (tileLatEnd - latEnd) / (tileLatEnd - tileLatStart) * tileSize; 85 + const tileImgY = (tileLatEnd - latEnd) / (tileLatEnd - tileLatStart) * tileSize; // 图片在瓦片中的Y坐标
73 - const tileImgWidth = (lonEnd - lonStart) / (tileLonEnd - tileLonStart) * tileSize; 86 + const tileImgWidth = (lonEnd - lonStart) / (tileLonEnd - tileLonStart) * tileSize; // 图片在瓦片中的宽度
74 - const tileImgHeight = (latEnd - latStart) / (tileLatEnd - tileLatStart) * tileSize; 87 + const tileImgHeight = (latEnd - latStart) / (tileLatEnd - tileLatStart) * tileSize; // 图片在瓦片中的高度
75 - 88 +
89 + // 清空画布
76 ctx.clearRect(0, 0, tileSize * scaleFactor, tileSize * scaleFactor); 90 ctx.clearRect(0, 0, tileSize * scaleFactor, tileSize * scaleFactor);
77 91
78 - // 根据图片在瓦片中的实际位置和尺寸绘制 92 + // 绘制图片到画布
79 ctx.drawImage( 93 ctx.drawImage(
80 image, 94 image,
81 0, 0, imgWidth, imgHeight, // 源图像区域(使用完整图片) 95 0, 0, imgWidth, imgHeight, // 源图像区域(使用完整图片)
82 tileImgX, tileImgY, tileImgWidth, tileImgHeight // 目标画布区域(保持实际位置和比例) 96 tileImgX, tileImgY, tileImgWidth, tileImgHeight // 目标画布区域(保持实际位置和比例)
83 ); 97 );
84 98
99 + // 将画布内容转换为Blob对象
85 canvas.toBlob((blob) => { 100 canvas.toBlob((blob) => {
86 if (!blob) { 101 if (!blob) {
87 console.error("瓦片转换失败!"); 102 console.error("瓦片转换失败!");
...@@ -104,6 +119,7 @@ function sliceImageToTiles(image, bounds, zoomLevel) { ...@@ -104,6 +119,7 @@ function sliceImageToTiles(image, bounds, zoomLevel) {
104 } 119 }
105 } 120 }
106 } 121 }
122 +
107 // 经纬度转换为瓦片坐标 123 // 经纬度转换为瓦片坐标
108 function lonToTileX(lon, zoom) { 124 function lonToTileX(lon, zoom) {
109 return Math.floor(((lon + 180) / 360) * Math.pow(2, zoom)); 125 return Math.floor(((lon + 180) / 360) * Math.pow(2, zoom));
...@@ -127,7 +143,7 @@ function saveTile(blob, filename) { ...@@ -127,7 +143,7 @@ function saveTile(blob, filename) {
127 // 生成并下载压缩包 143 // 生成并下载压缩包
128 function generateAndDownloadZip(zip, zoomLevel) { 144 function generateAndDownloadZip(zip, zoomLevel) {
129 zip.generateAsync({ type: "blob" }).then((content) => { 145 zip.generateAsync({ type: "blob" }).then((content) => {
130 - // 使用 FileSaver.js 下载压缩包 146 + // 使用 FileSaver.js 下载压缩包
131 - saveAs(content, `${zoomLevel}级瓦片切片包.zip`); 147 + saveAs(content, `${zoomLevel}级瓦片切片包.zip`);
132 }); 148 });
133 } 149 }
......