hookehuyr

fix 代码备注

/*
* @Date: 2025-01-22 11:45:30
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-02-08 10:24:25
* @LastEditTime: 2025-02-24 13:21:58
* @FilePath: /map-demo/src/utils/TileCutter.js
* @Description: 文件描述
*/
......@@ -21,27 +21,38 @@ export function TileCutter(imageURL, bounds, zoomLevel) {
}
/**
* 将图片切割成瓦片并打包下载
* @param {HTMLImageElement} image - 要切割的图片元素
* @param {L.LatLngBounds} bounds - 图片边界范围,包含西南角和东北角的经纬度
* @param {number} zoomLevel - 地图缩放级别
*/
function sliceImageToTiles(image, bounds, zoomLevel) {
// 创建画布及上下文
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const imgWidth = image.width;
const imgHeight = image.height;
// 获取原始图片尺寸
const imgWidth = image.width; // 图片原始宽度
const imgHeight = image.height; // 图片原始高度
const southWest = bounds.getSouthWest();
const northEast = bounds.getNorthEast();
// 获取边界经纬度
const southWest = bounds.getSouthWest(); // 西南角坐标
const northEast = bounds.getNorthEast(); // 东北角坐标
const lonStart = southWest.lng;
const latStart = southWest.lat;
const lonEnd = northEast.lng;
const latEnd = northEast.lat;
// 提取边界经纬度值
const lonStart = southWest.lng; // 起始经度
const latStart = southWest.lat; // 起始纬度
const lonEnd = northEast.lng; // 结束经度
const latEnd = northEast.lat; // 结束纬度
let tileStartX = lonToTileX(lonStart, zoomLevel);
let tileEndX = lonToTileX(lonEnd, zoomLevel);
let tileStartY = latToTileY(latEnd, zoomLevel); // 取 latEnd 作为起点
let tileEndY = latToTileY(latStart, zoomLevel); // 取 latStart 作为终点
// 计算瓦片坐标范围
let tileStartX = lonToTileX(lonStart, zoomLevel); // 起始瓦片X坐标
let tileEndX = lonToTileX(lonEnd, zoomLevel); // 结束瓦片X坐标
let tileStartY = latToTileY(latEnd, zoomLevel); // 起始瓦片Y坐标
let tileEndY = latToTileY(latStart, zoomLevel); // 结束瓦片Y坐标
// 确保 tileStartX <= tileEndX,tileStartY <= tileEndY
// 确保瓦片坐标范围正确(起始值小于结束值)
tileStartX = Math.min(tileStartX, tileEndX);
tileEndX = Math.max(tileStartX, tileEndX);
tileStartY = Math.min(tileStartY, tileEndY);
......@@ -49,9 +60,11 @@ function sliceImageToTiles(image, bounds, zoomLevel) {
const scaleFactor = 2; // 调高分辨率倍率
// 设置画布尺寸
canvas.width = tileSize * scaleFactor;
canvas.height = tileSize * scaleFactor;
// 设置画布缩放
ctx.scale(scaleFactor, scaleFactor);
const zip = new JSZip(); // 创建一个 JSZip 实例,用来打包所有瓦片
......@@ -62,26 +75,28 @@ function sliceImageToTiles(image, bounds, zoomLevel) {
for (let tileX = tileStartX; tileX <= tileEndX; tileX++) {
for (let tileY = tileStartY; tileY <= tileEndY; tileY++) {
// 计算当前瓦片的经纬度范围
const tileLonStart = tileX * 360 / Math.pow(2, zoomLevel) - 180;
const tileLonEnd = (tileX + 1) * 360 / Math.pow(2, zoomLevel) - 180;
const tileLatStart = Math.atan(Math.sinh(Math.PI * (1 - 2 * (tileY + 1) / Math.pow(2, zoomLevel)))) * 180 / Math.PI;
const tileLatEnd = Math.atan(Math.sinh(Math.PI * (1 - 2 * tileY / Math.pow(2, zoomLevel)))) * 180 / Math.PI;
// 计算图片在当前瓦片中的位置和尺寸
const tileImgX = (lonStart - tileLonStart) / (tileLonEnd - tileLonStart) * tileSize;
const tileImgY = (tileLatEnd - latEnd) / (tileLatEnd - tileLatStart) * tileSize;
const tileImgWidth = (lonEnd - lonStart) / (tileLonEnd - tileLonStart) * tileSize;
const tileImgHeight = (latEnd - latStart) / (tileLatEnd - tileLatStart) * tileSize;
const tileLonStart = tileX * 360 / Math.pow(2, zoomLevel) - 180; // 瓦片起始经度
const tileLonEnd = (tileX + 1) * 360 / Math.pow(2, zoomLevel) - 180; // 瓦片结束经度
const tileLatStart = Math.atan(Math.sinh(Math.PI * (1 - 2 * (tileY + 1) / Math.pow(2, zoomLevel)))) * 180 / Math.PI; // 瓦片起始纬度
const tileLatEnd = Math.atan(Math.sinh(Math.PI * (1 - 2 * tileY / Math.pow(2, zoomLevel)))) * 180 / Math.PI; // 瓦片结束纬度
// 计算图片在当前瓦片中的位置和尺寸(像素坐标)
const tileImgX = (lonStart - tileLonStart) / (tileLonEnd - tileLonStart) * tileSize; // 图片在瓦片中的X坐标
const tileImgY = (tileLatEnd - latEnd) / (tileLatEnd - tileLatStart) * tileSize; // 图片在瓦片中的Y坐标
const tileImgWidth = (lonEnd - lonStart) / (tileLonEnd - tileLonStart) * tileSize; // 图片在瓦片中的宽度
const tileImgHeight = (latEnd - latStart) / (tileLatEnd - tileLatStart) * tileSize; // 图片在瓦片中的高度
// 清空画布
ctx.clearRect(0, 0, tileSize * scaleFactor, tileSize * scaleFactor);
// 根据图片在瓦片中的实际位置和尺寸绘制
// 绘制图片到画布
ctx.drawImage(
image,
0, 0, imgWidth, imgHeight, // 源图像区域(使用完整图片)
tileImgX, tileImgY, tileImgWidth, tileImgHeight // 目标画布区域(保持实际位置和比例)
);
// 将画布内容转换为Blob对象
canvas.toBlob((blob) => {
if (!blob) {
console.error("瓦片转换失败!");
......@@ -104,6 +119,7 @@ function sliceImageToTiles(image, bounds, zoomLevel) {
}
}
}
// 经纬度转换为瓦片坐标
function lonToTileX(lon, zoom) {
return Math.floor(((lon + 180) / 360) * Math.pow(2, zoom));
......