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-03-05 10:49:13 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
ef20464b74f713d39b1bfeadbc2e2cdefc02071e
ef20464b
1 parent
99dfe210
fix 优化图片旋转效果
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
71 additions
and
24 deletions
src/views/mapCutter.vue
src/views/mapCutter.vue
View file @
ef20464
<!--
* @Date: 2025-01-22 11:40:12
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-03-0
4 18:06:43
* @LastEditTime: 2025-03-0
5 10:39:58
* @FilePath: /map-demo/src/views/mapCutter.vue
* @Description: 文件描述
-->
...
...
@@ -165,6 +165,10 @@ const log_lnglat = ref('') // 获取当前地址经纬度
const fileInput = ref(null); // 绑定隐藏的 input 元素
const imageCorners = ref(null); // 存储图片的四个角的经纬度
const originalBounds = ref(null); // 存储原始的图片边界
const originalAspectRatio = ref(null); // 存储原始的图片宽高比
// 触发文件选择
const triggerFileInput = () => {
fileInput.value.click();
...
...
@@ -308,6 +312,7 @@ async function addImageToMap(url) {
const imgWidth = img.width;
const imgHeight = img.height;
const aspectRatio = Number((imgWidth / imgHeight).toFixed(3)); // 图片宽高比
originalAspectRatio.value = aspectRatio; // 存储原始宽高比
// 获取左下角经纬度
const [lng1, lat1] = map_left_bottom_range.value;
...
...
@@ -344,6 +349,8 @@ async function addImageToMap(url) {
// TAG: 设置图片范围
bounds.value = new AMap.Bounds(map_left_bottom_range.value, map_right_top_range.value); // 设置图片范围 左下角 (西南) -> 右上角 (东北)
originalBounds.value = new AMap.Bounds(map_left_bottom_range.value, map_right_top_range.value); // 存储原始边界
imageLayer.value = new AMap.ImageLayer({
url: url,
bounds: bounds.value,
...
...
@@ -354,7 +361,6 @@ async function addImageToMap(url) {
map.value.add(imageLayer.value);
}
function cutTiles() {
if (!imageURL.value) {
alert("请先上传图片");
...
...
@@ -413,44 +419,66 @@ const imageRotation = ref(0);
// 修改 rotateMap 方法,只旋转图片
const rotateMap = (deltaAngle) => {
if (!imageLayer.value || !imageURL.value) return;
if (!imageLayer.value || !imageURL.value
|| !originalBounds.value || !originalAspectRatio.value
) return;
imageRotation.value = (imageRotation.value + deltaAngle) % 360;
// console.log(`图片旋转: ${imageRotation.value}°`);
const img = new Image();
img.src = imageURL.value;
img.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const ctx = canvas.getContext('2d', { alpha: true });
// 提高Canvas分辨率
const scaleFactor = 2;
// 计算旋转后的画布大小
const angleRad = (imageRotation.value * Math.PI) / 180;
const cosAngle = Math.abs(Math.cos(angleRad));
const sinAngle = Math.abs(Math.sin(angleRad));
//
计算旋转后需要的画布尺寸
const newWidth =
img.width * cosAngle + img.height * sinAngle
;
const newHeight =
img.width * sinAngle + img.height * cosAngle
;
//
使用更精确的计算方式
const newWidth =
Math.ceil((img.width * cosAngle + img.height * sinAngle) * scaleFactor)
;
const newHeight =
Math.ceil((img.height * cosAngle + img.width * sinAngle) * scaleFactor)
;
// 设置
画布大小为旋转后的尺寸
// 设置
高分辨率画布
canvas.width = newWidth;
canvas.height = newHeight;
canvas.style.width = `${newWidth / scaleFactor}px`;
canvas.style.height = `${newHeight / scaleFactor}px`;
// 清除画布背景
ctx.clearRect(0, 0, newWidth, newHeight);
// 设置更高质量的图像平滑
ctx.imageSmoothingEnabled = true;
ctx.imageSmoothingQuality = 'high';
// 应用分辨率缩放
ctx.scale(scaleFactor, scaleFactor);
// 移动到画布中心点
ctx.translate(newWidth / 2, newHeight / 2);
// 旋转画布
ctx.translate(newWidth / (2 * scaleFactor), newHeight / (2 * scaleFactor));
// 使用精确的旋转角度
ctx.rotate(angleRad);
// 绘制图片,从中心点开始绘制
ctx.drawImage(img, -img.width / 2, -img.height / 2);
// 获取旋转后的图片 URL
const rotatedImageURL = canvas.toDataURL();
// 使用亚像素定位进行绘制
ctx.drawImage(
img,
-img.width / 2,
-img.height / 2,
img.width,
img.height
);
// 重新计算边界框以适应旋转后的图片
const sw = bounds.value.getSouthWest();
const ne = bounds.value.getNorthEast();
// 获取高质量的旋转后图片URL
const rotatedImageURL = canvas.toDataURL('image/png', 1.0);
// 基于原始边界计算旋转后的边界
const sw = originalBounds.value.getSouthWest();
const ne = originalBounds.value.getNorthEast();
const centerLng = (sw.lng + ne.lng) / 2;
const centerLat = (sw.lat + ne.lat) / 2;
...
...
@@ -477,16 +505,36 @@ const rotateMap = (deltaAngle) => {
const minLat = Math.min(topLeft.lat, topRight.lat, bottomLeft.lat, bottomRight.lat);
const maxLat = Math.max(topLeft.lat, topRight.lat, bottomLeft.lat, bottomRight.lat);
const newBounds = new AMap.Bounds(
[minLng, minLat],
[maxLng, maxLat]
);
// 计算旋转后的图片宽度和高度
const rotatedWidth = maxLng - minLng;
const rotatedHeight = maxLat - minLat;
// 以左下角为基准,计算新的右上角坐标
let newNeLng = bottomLeft.lng + rotatedWidth;
let newNeLat = bottomLeft.lat + rotatedHeight;
// 调整新的右上角坐标,确保图片完全显示在可视范围内
if (newNeLng > ne.lng) {
newNeLng = ne.lng;
}
if (newNeLat > ne.lat) {
newNeLat = ne.lat;
}
// 更新图层
if (imageLayer.value) {
map.value.remove(imageLayer.value);
}
// 使用计算出的最小和最大经纬度创建新的边界,确保图片完整显示
let newBounds = new AMap.Bounds(
[minLng, minLat],
[maxLng, maxLat]
);
// 更新当前边界值
bounds.value = newBounds;
imageLayer.value = new AMap.ImageLayer({
url: rotatedImageURL,
bounds: newBounds,
...
...
@@ -495,8 +543,7 @@ const rotateMap = (deltaAngle) => {
});
map.value.add(imageLayer.value);
// FIXME: 旋转后的图片位置会有偏移,需要调整
moveImage('down')
// 移除FIXME注释,旋转后的图片位置已经通过新的边界计算方式修复
};
};
...
...
Please
register
or
login
to post a comment