Showing
1 changed file
with
19 additions
and
68 deletions
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-01-22 11:40:12 | 2 | * @Date: 2025-01-22 11:40:12 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-03-05 10:39:58 | 4 | + * @LastEditTime: 2025-03-05 11:21:28 |
| 5 | * @FilePath: /map-demo/src/views/mapCutter.vue | 5 | * @FilePath: /map-demo/src/views/mapCutter.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -419,7 +419,7 @@ const imageRotation = ref(0); | ... | @@ -419,7 +419,7 @@ const imageRotation = ref(0); |
| 419 | 419 | ||
| 420 | // 修改 rotateMap 方法,只旋转图片 | 420 | // 修改 rotateMap 方法,只旋转图片 |
| 421 | const rotateMap = (deltaAngle) => { | 421 | const rotateMap = (deltaAngle) => { |
| 422 | - if (!imageLayer.value || !imageURL.value || !originalBounds.value || !originalAspectRatio.value) return; | 422 | + if (!imageLayer.value || !imageURL.value || !bounds.value) return; |
| 423 | 423 | ||
| 424 | imageRotation.value = (imageRotation.value + deltaAngle) % 360; | 424 | imageRotation.value = (imageRotation.value + deltaAngle) % 360; |
| 425 | 425 | ||
| ... | @@ -430,8 +430,10 @@ const rotateMap = (deltaAngle) => { | ... | @@ -430,8 +430,10 @@ const rotateMap = (deltaAngle) => { |
| 430 | const canvas = document.createElement('canvas'); | 430 | const canvas = document.createElement('canvas'); |
| 431 | const ctx = canvas.getContext('2d', { alpha: true }); | 431 | const ctx = canvas.getContext('2d', { alpha: true }); |
| 432 | 432 | ||
| 433 | - // 提高Canvas分辨率 | 433 | + // 获取当前的边界 |
| 434 | - const scaleFactor = 2; | 434 | + const currentBounds = bounds.value; |
| 435 | + const sw = currentBounds.getSouthWest(); | ||
| 436 | + const ne = currentBounds.getNorthEast(); | ||
| 435 | 437 | ||
| 436 | // 计算旋转后的画布大小 | 438 | // 计算旋转后的画布大小 |
| 437 | const angleRad = (imageRotation.value * Math.PI) / 180; | 439 | const angleRad = (imageRotation.value * Math.PI) / 180; |
| ... | @@ -439,27 +441,19 @@ const rotateMap = (deltaAngle) => { | ... | @@ -439,27 +441,19 @@ const rotateMap = (deltaAngle) => { |
| 439 | const sinAngle = Math.abs(Math.sin(angleRad)); | 441 | const sinAngle = Math.abs(Math.sin(angleRad)); |
| 440 | 442 | ||
| 441 | // 使用更精确的计算方式 | 443 | // 使用更精确的计算方式 |
| 442 | - const newWidth = Math.ceil((img.width * cosAngle + img.height * sinAngle) * scaleFactor); | 444 | + const newWidth = Math.ceil((img.width * cosAngle + img.height * sinAngle)); |
| 443 | - const newHeight = Math.ceil((img.height * cosAngle + img.width * sinAngle) * scaleFactor); | 445 | + const newHeight = Math.ceil((img.height * cosAngle + img.width * sinAngle)); |
| 444 | 446 | ||
| 445 | // 设置高分辨率画布 | 447 | // 设置高分辨率画布 |
| 446 | canvas.width = newWidth; | 448 | canvas.width = newWidth; |
| 447 | canvas.height = newHeight; | 449 | canvas.height = newHeight; |
| 448 | - canvas.style.width = `${newWidth / scaleFactor}px`; | ||
| 449 | - canvas.style.height = `${newHeight / scaleFactor}px`; | ||
| 450 | 450 | ||
| 451 | - // 清除画布背景 | 451 | + // 优化渲染上下文 |
| 452 | - ctx.clearRect(0, 0, newWidth, newHeight); | ||
| 453 | - | ||
| 454 | - // 设置更高质量的图像平滑 | ||
| 455 | ctx.imageSmoothingEnabled = true; | 452 | ctx.imageSmoothingEnabled = true; |
| 456 | ctx.imageSmoothingQuality = 'high'; | 453 | ctx.imageSmoothingQuality = 'high'; |
| 457 | 454 | ||
| 458 | - // 应用分辨率缩放 | 455 | + // 应用变换矩阵 |
| 459 | - ctx.scale(scaleFactor, scaleFactor); | 456 | + ctx.translate(canvas.width / 2, canvas.height / 2); |
| 460 | - | ||
| 461 | - // 移动到画布中心点 | ||
| 462 | - ctx.translate(newWidth / (2 * scaleFactor), newHeight / (2 * scaleFactor)); | ||
| 463 | 457 | ||
| 464 | // 使用精确的旋转角度 | 458 | // 使用精确的旋转角度 |
| 465 | ctx.rotate(angleRad); | 459 | ctx.rotate(angleRad); |
| ... | @@ -476,65 +470,22 @@ const rotateMap = (deltaAngle) => { | ... | @@ -476,65 +470,22 @@ const rotateMap = (deltaAngle) => { |
| 476 | // 获取高质量的旋转后图片URL | 470 | // 获取高质量的旋转后图片URL |
| 477 | const rotatedImageURL = canvas.toDataURL('image/png', 1.0); | 471 | const rotatedImageURL = canvas.toDataURL('image/png', 1.0); |
| 478 | 472 | ||
| 479 | - // 基于原始边界计算旋转后的边界 | 473 | + // 计算新的边界,保持图片大小不变 |
| 480 | - const sw = originalBounds.value.getSouthWest(); | 474 | + const currentWidth = ne.lng - sw.lng; |
| 481 | - const ne = originalBounds.value.getNorthEast(); | 475 | + const currentHeight = ne.lat - sw.lat; |
| 482 | const centerLng = (sw.lng + ne.lng) / 2; | 476 | const centerLng = (sw.lng + ne.lng) / 2; |
| 483 | const centerLat = (sw.lat + ne.lat) / 2; | 477 | const centerLat = (sw.lat + ne.lat) / 2; |
| 484 | 478 | ||
| 485 | - // 计算四个角的经纬度 | 479 | + const newBounds = new AMap.Bounds( |
| 486 | - const calculateCorner = (x, y, centerX, centerY) => { | 480 | + [centerLng - currentWidth / 2, centerLat - currentHeight / 2], |
| 487 | - const angle = imageRotation.value * Math.PI / 180; | 481 | + [centerLng + currentWidth / 2, centerLat + currentHeight / 2] |
| 488 | - const rotatedX = centerX + (x - centerX) * Math.cos(angle) - (y - centerY) * Math.sin(angle); | 482 | + ); |
| 489 | - const rotatedY = centerY + (x - centerX) * Math.sin(angle) + (y - centerY) * Math.cos(angle); | ||
| 490 | - return { lng: rotatedX, lat: rotatedY }; | ||
| 491 | - }; | ||
| 492 | - | ||
| 493 | - // 以图片中心点为基准 | ||
| 494 | - const centerX = centerLng; | ||
| 495 | - const centerY = centerLat; | ||
| 496 | - | ||
| 497 | - const topLeft = calculateCorner(sw.lng, ne.lat, centerX, centerY); | ||
| 498 | - const topRight = calculateCorner(ne.lng, ne.lat, centerX, centerY); | ||
| 499 | - const bottomLeft = calculateCorner(sw.lng, sw.lat, centerX, centerY); | ||
| 500 | - const bottomRight = calculateCorner(ne.lng, sw.lat, centerX, centerY); | ||
| 501 | - | ||
| 502 | - // 找到四个角的最小和最大经纬度 | ||
| 503 | - const minLng = Math.min(topLeft.lng, topRight.lng, bottomLeft.lng, bottomRight.lng); | ||
| 504 | - const maxLng = Math.max(topLeft.lng, topRight.lng, bottomLeft.lng, bottomRight.lng); | ||
| 505 | - const minLat = Math.min(topLeft.lat, topRight.lat, bottomLeft.lat, bottomRight.lat); | ||
| 506 | - const maxLat = Math.max(topLeft.lat, topRight.lat, bottomLeft.lat, bottomRight.lat); | ||
| 507 | - | ||
| 508 | - // 计算旋转后的图片宽度和高度 | ||
| 509 | - const rotatedWidth = maxLng - minLng; | ||
| 510 | - const rotatedHeight = maxLat - minLat; | ||
| 511 | - | ||
| 512 | - // 以左下角为基准,计算新的右上角坐标 | ||
| 513 | - let newNeLng = bottomLeft.lng + rotatedWidth; | ||
| 514 | - let newNeLat = bottomLeft.lat + rotatedHeight; | ||
| 515 | - | ||
| 516 | - // 调整新的右上角坐标,确保图片完全显示在可视范围内 | ||
| 517 | - if (newNeLng > ne.lng) { | ||
| 518 | - newNeLng = ne.lng; | ||
| 519 | - } | ||
| 520 | - if (newNeLat > ne.lat) { | ||
| 521 | - newNeLat = ne.lat; | ||
| 522 | - } | ||
| 523 | 483 | ||
| 524 | // 更新图层 | 484 | // 更新图层 |
| 525 | if (imageLayer.value) { | 485 | if (imageLayer.value) { |
| 526 | map.value.remove(imageLayer.value); | 486 | map.value.remove(imageLayer.value); |
| 527 | } | 487 | } |
| 528 | 488 | ||
| 529 | - // 使用计算出的最小和最大经纬度创建新的边界,确保图片完整显示 | ||
| 530 | - let newBounds = new AMap.Bounds( | ||
| 531 | - [minLng, minLat], | ||
| 532 | - [maxLng, maxLat] | ||
| 533 | - ); | ||
| 534 | - | ||
| 535 | - // 更新当前边界值 | ||
| 536 | - bounds.value = newBounds; | ||
| 537 | - | ||
| 538 | imageLayer.value = new AMap.ImageLayer({ | 489 | imageLayer.value = new AMap.ImageLayer({ |
| 539 | url: rotatedImageURL, | 490 | url: rotatedImageURL, |
| 540 | bounds: newBounds, | 491 | bounds: newBounds, |
| ... | @@ -543,7 +494,7 @@ const rotateMap = (deltaAngle) => { | ... | @@ -543,7 +494,7 @@ const rotateMap = (deltaAngle) => { |
| 543 | }); | 494 | }); |
| 544 | 495 | ||
| 545 | map.value.add(imageLayer.value); | 496 | map.value.add(imageLayer.value); |
| 546 | - // 移除FIXME注释,旋转后的图片位置已经通过新的边界计算方式修复 | 497 | + bounds.value = newBounds; |
| 547 | }; | 498 | }; |
| 548 | }; | 499 | }; |
| 549 | 500 | ... | ... |
-
Please register or login to post a comment