Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Hooke
/
map-demo
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
hookehuyr
2025-02-24 13:39:58 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
7a03a90387353cda3bb69af4b3240cfecca7a876
7a03a903
1 parent
e955ce71
fix 代码备注
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
44 additions
and
28 deletions
src/utils/TileCutter.js
src/utils/TileCutter.js
View file @
7a03a90
/*
* @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
));
...
...
@@ -127,7 +143,7 @@ function saveTile(blob, filename) {
// 生成并下载压缩包
function
generateAndDownloadZip
(
zip
,
zoomLevel
)
{
zip
.
generateAsync
({
type
:
"blob"
}).
then
((
content
)
=>
{
// 使用 FileSaver.js 下载压缩包
saveAs
(
content
,
`
${
zoomLevel
}
级瓦片切片包.zip`
);
// 使用 FileSaver.js 下载压缩包
saveAs
(
content
,
`
${
zoomLevel
}
级瓦片切片包.zip`
);
});
}
...
...
Please
register
or
login
to post a comment