hookehuyr

✨ feat: 最后切出来的图片,按照实际图片在瓦片的位置,而不是填充满瓦片的长宽

...@@ -47,14 +47,6 @@ function sliceImageToTiles(image, bounds, zoomLevel) { ...@@ -47,14 +47,6 @@ function sliceImageToTiles(image, bounds, zoomLevel) {
47 tileStartY = Math.min(tileStartY, tileEndY); 47 tileStartY = Math.min(tileStartY, tileEndY);
48 tileEndY = Math.max(tileStartY, tileEndY); 48 tileEndY = Math.max(tileStartY, tileEndY);
49 49
50 - // console.warn(`瓦片编号: X(${tileStartX} -> ${tileEndX}), Y(${tileStartY} -> ${tileEndY})`);
51 -
52 - const cols = tileEndX - tileStartX + 1;
53 - const rows = tileEndY - tileStartY + 1;
54 -
55 - const tileWidth = imgWidth / cols;
56 - const tileHeight = imgHeight / rows;
57 -
58 const scaleFactor = 2; // 调高分辨率倍率 50 const scaleFactor = 2; // 调高分辨率倍率
59 51
60 canvas.width = tileSize * scaleFactor; 52 canvas.width = tileSize * scaleFactor;
...@@ -66,14 +58,28 @@ function sliceImageToTiles(image, bounds, zoomLevel) { ...@@ -66,14 +58,28 @@ function sliceImageToTiles(image, bounds, zoomLevel) {
66 58
67 let tileIndex = 0; // 瓦片索引,用来给每个瓦片命名 59 let tileIndex = 0; // 瓦片索引,用来给每个瓦片命名
68 60
69 - for (let x = 0; x < cols; x++) { 61 + // 计算每个瓦片的经纬度范围
70 - for (let y = 0; y < rows; y++) { 62 + for (let tileX = tileStartX; tileX <= tileEndX; tileX++) {
71 - ctx.clearRect(0, 0, tileSize, tileSize); 63 + for (let tileY = tileStartY; tileY <= tileEndY; tileY++) {
64 + // 计算当前瓦片的经纬度范围
65 + const tileLonStart = tileX * 360 / Math.pow(2, zoomLevel) - 180;
66 + 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;
68 + const tileLatEnd = Math.atan(Math.sinh(Math.PI * (1 - 2 * tileY / Math.pow(2, zoomLevel)))) * 180 / Math.PI;
69 +
70 + // 计算图片在当前瓦片中的位置和尺寸
71 + const tileImgX = (lonStart - tileLonStart) / (tileLonEnd - tileLonStart) * tileSize;
72 + const tileImgY = (tileLatEnd - latEnd) / (tileLatEnd - tileLatStart) * tileSize;
73 + const tileImgWidth = (lonEnd - lonStart) / (tileLonEnd - tileLonStart) * tileSize;
74 + const tileImgHeight = (latEnd - latStart) / (tileLatEnd - tileLatStart) * tileSize;
75 +
76 + ctx.clearRect(0, 0, tileSize * scaleFactor, tileSize * scaleFactor);
72 77
78 + // 根据图片在瓦片中的实际位置和尺寸绘制
73 ctx.drawImage( 79 ctx.drawImage(
74 image, 80 image,
75 - x * tileWidth, y * tileHeight, tileWidth, tileHeight, // 源图像区域 81 + 0, 0, imgWidth, imgHeight, // 源图像区域(使用完整图片)
76 - 0, 0, tileSize, tileSize // 目标画布区域 82 + tileImgX, tileImgY, tileImgWidth, tileImgHeight // 目标画布区域(保持实际位置和比例)
77 ); 83 );
78 84
79 canvas.toBlob((blob) => { 85 canvas.toBlob((blob) => {
...@@ -81,10 +87,6 @@ function sliceImageToTiles(image, bounds, zoomLevel) { ...@@ -81,10 +87,6 @@ function sliceImageToTiles(image, bounds, zoomLevel) {
81 console.error("瓦片转换失败!"); 87 console.error("瓦片转换失败!");
82 return; 88 return;
83 } 89 }
84 - const tileX = tileStartX + x;
85 - const tileY = tileStartY + y;
86 - // console.warn(`保存瓦片: ${tileX}_${tileY}_${zoomLevel}.png`);
87 - // saveTile(blob, `${tileX}_${tileY}_${zoomLevel}.png`);
88 90
89 // 获取当前北京时间(UTC+8) 91 // 获取当前北京时间(UTC+8)
90 const beijingTime = dayjs().add(8, "hour").toDate(); 92 const beijingTime = dayjs().add(8, "hour").toDate();
...@@ -94,7 +96,8 @@ function sliceImageToTiles(image, bounds, zoomLevel) { ...@@ -94,7 +96,8 @@ function sliceImageToTiles(image, bounds, zoomLevel) {
94 tileIndex++; 96 tileIndex++;
95 97
96 // 如果所有瓦片都处理完,生成并下载压缩包 98 // 如果所有瓦片都处理完,生成并下载压缩包
97 - if (tileIndex === cols * rows) { 99 + const totalTiles = (tileEndX - tileStartX + 1) * (tileEndY - tileStartY + 1);
100 + if (tileIndex === totalTiles) {
98 generateAndDownloadZip(zip, zoomLevel); 101 generateAndDownloadZip(zip, zoomLevel);
99 } 102 }
100 }, "image/png", 1.0); 103 }, "image/png", 1.0);
......