Showing
2 changed files
with
189 additions
and
6 deletions
| ... | @@ -15,6 +15,7 @@ declare module '@vue/runtime-core' { | ... | @@ -15,6 +15,7 @@ declare module '@vue/runtime-core' { |
| 15 | ElButton: typeof import('element-plus/es')['ElButton'] | 15 | ElButton: typeof import('element-plus/es')['ElButton'] |
| 16 | ElInput: typeof import('element-plus/es')['ElInput'] | 16 | ElInput: typeof import('element-plus/es')['ElInput'] |
| 17 | ElOption: typeof import('element-plus/es')['ElOption'] | 17 | ElOption: typeof import('element-plus/es')['ElOption'] |
| 18 | + ElProgress: typeof import('element-plus/es')['ElProgress'] | ||
| 18 | ElSelect: typeof import('element-plus/es')['ElSelect'] | 19 | ElSelect: typeof import('element-plus/es')['ElSelect'] |
| 19 | Floor: typeof import('./src/components/Floor/index.vue')['default'] | 20 | Floor: typeof import('./src/components/Floor/index.vue')['default'] |
| 20 | InfoPopup: typeof import('./src/components/InfoPopup.vue')['default'] | 21 | InfoPopup: typeof import('./src/components/InfoPopup.vue')['default'] | ... | ... |
| 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-02-08 10:47:47 | 4 | + * @LastEditTime: 2025-02-08 14:14:42 |
| 5 | * @FilePath: /map-demo/src/views/mapCutter.vue | 5 | * @FilePath: /map-demo/src/views/mapCutter.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -48,10 +48,13 @@ | ... | @@ -48,10 +48,13 @@ |
| 48 | v-model="img_ratio" | 48 | v-model="img_ratio" |
| 49 | style="width: 240px" | 49 | style="width: 240px" |
| 50 | placeholder="输入上传图片比例" | 50 | placeholder="输入上传图片比例" |
| 51 | - /> | 51 | + > |
| 52 | + </el-input> | ||
| 52 | </div> | 53 | </div> |
| 53 | <div v-if="showUpload"> | 54 | <div v-if="showUpload"> |
| 54 | - <input type="file" @change="handleImageUpload" /> | 55 | + <!-- 触发上传按钮 --> |
| 56 | + <el-button type="primary" @click="triggerFileInput">上传图片</el-button> | ||
| 57 | + <input ref="fileInput" type="file" @change="handleImageUpload" style="display: none" /> | ||
| 55 | <el-button type="primary" @click="cutTiles">切割瓦片</el-button> | 58 | <el-button type="primary" @click="cutTiles">切割瓦片</el-button> |
| 56 | </div> | 59 | </div> |
| 57 | </div> | 60 | </div> |
| ... | @@ -59,7 +62,7 @@ | ... | @@ -59,7 +62,7 @@ |
| 59 | <div> | 62 | <div> |
| 60 | 63 | ||
| 61 | </div> | 64 | </div> |
| 62 | - <div v-if="showUpload" class="controls"> | 65 | + <!-- <div v-if="showUpload" class="controls"> |
| 63 | <el-button type="primary" :icon="Top" @click="moveImage('up')">图片上移</el-button> | 66 | <el-button type="primary" :icon="Top" @click="moveImage('up')">图片上移</el-button> |
| 64 | <el-button type="primary" :icon="Bottom" @click="moveImage('down')">图片下移</el-button> | 67 | <el-button type="primary" :icon="Bottom" @click="moveImage('down')">图片下移</el-button> |
| 65 | <el-button type="primary" :icon="Back" @click="moveImage('left')">图片左移</el-button> | 68 | <el-button type="primary" :icon="Back" @click="moveImage('left')">图片左移</el-button> |
| ... | @@ -68,15 +71,42 @@ | ... | @@ -68,15 +71,42 @@ |
| 68 | <el-button type="primary" :icon="Minus" @click="scaleImage(0.99)">图片缩小</el-button> | 71 | <el-button type="primary" :icon="Minus" @click="scaleImage(0.99)">图片缩小</el-button> |
| 69 | <el-button type="primary" @click="rotateMap(10)">地图顺时针旋转</el-button> | 72 | <el-button type="primary" @click="rotateMap(10)">地图顺时针旋转</el-button> |
| 70 | <el-button type="primary" @click="rotateMap(-10)">地图逆时针旋转</el-button> | 73 | <el-button type="primary" @click="rotateMap(-10)">地图逆时针旋转</el-button> |
| 71 | - </div> | 74 | + </div> --> |
| 72 | 75 | ||
| 73 | <div v-if="log_lnglat" style="position: fixed; top: 8rem; left: 1rem; color: black; background-color: white; padding: 1rem;"> | 76 | <div v-if="log_lnglat" style="position: fixed; top: 8rem; left: 1rem; color: black; background-color: white; padding: 1rem;"> |
| 74 | <div style=" display: flex; align-items: center; justify-content: center;">经纬度:{{ log_lnglat }} <el-button @click="copyText(log_lnglat)" type="primary" :icon="Brush" size="small">复制</el-button></div> | 77 | <div style=" display: flex; align-items: center; justify-content: center;">经纬度:{{ log_lnglat }} <el-button @click="copyText(log_lnglat)" type="primary" :icon="Brush" size="small">复制</el-button></div> |
| 75 | </div> | 78 | </div> |
| 79 | + | ||
| 80 | + <div v-if="showUpload" class="controls-container"> | ||
| 81 | + <!-- 遥控器界面 --> | ||
| 82 | + <div class="remote-control"> | ||
| 83 | + <!-- 方向控制 --> | ||
| 84 | + <div class="direction-control"> | ||
| 85 | + <button class="z-button" @click="moveImage('up')">↑</button> | ||
| 86 | + <div class="horizontal"> | ||
| 87 | + <button class="z-button" @click="moveImage('left')">←</button> | ||
| 88 | + <button class="z-button" @click="moveImage('right')">→</button> | ||
| 89 | + </div> | ||
| 90 | + <button class="z-button" @click="moveImage('down')">↓</button> | ||
| 91 | + </div> | ||
| 92 | + | ||
| 93 | + <!-- 缩放控制 --> | ||
| 94 | + <div class="zoom-control"> | ||
| 95 | + <button class="z-button" @click="scaleImage(1.01)">+</button> | ||
| 96 | + <button class="z-button" @click="scaleImage(0.99)">-</button> | ||
| 97 | + </div> | ||
| 98 | + | ||
| 99 | + <!-- 旋转控制 --> | ||
| 100 | + <div class="rotate-control"> | ||
| 101 | + <button class="z-button" @click="rotateMap(10)">↺</button> | ||
| 102 | + <button class="z-button" @click="rotateMap(-10)">↻</button> | ||
| 103 | + </div> | ||
| 104 | + </div> | ||
| 105 | + </div> | ||
| 76 | </template> | 106 | </template> |
| 77 | 107 | ||
| 78 | <script setup> | 108 | <script setup> |
| 79 | -import { onMounted, ref, computed } from "vue"; | 109 | +import { onMounted, ref, computed, onBeforeUnmount } from "vue"; |
| 80 | // import AMapLoader from "@amap/amap-jsapi-loader"; | 110 | // import AMapLoader from "@amap/amap-jsapi-loader"; |
| 81 | import { TileCutter } from "@/utils/TileCutter"; | 111 | import { TileCutter } from "@/utils/TileCutter"; |
| 82 | import { Top, Bottom, Back, Right, Plus, Minus, Brush } from '@element-plus/icons-vue' | 112 | import { Top, Bottom, Back, Right, Plus, Minus, Brush } from '@element-plus/icons-vue' |
| ... | @@ -110,10 +140,51 @@ const map_center = ref(null); | ... | @@ -110,10 +140,51 @@ const map_center = ref(null); |
| 110 | 140 | ||
| 111 | const log_lnglat = ref('') // 获取当前地址经纬度 | 141 | const log_lnglat = ref('') // 获取当前地址经纬度 |
| 112 | 142 | ||
| 143 | +const fileInput = ref(null); // 绑定隐藏的 input 元素 | ||
| 144 | + | ||
| 145 | +// 触发文件选择 | ||
| 146 | +const triggerFileInput = () => { | ||
| 147 | + fileInput.value.click(); | ||
| 148 | +}; | ||
| 149 | + | ||
| 150 | +const handleKeydown = (e) => { // 键盘控制 | ||
| 151 | + switch(e.key) { | ||
| 152 | + case 'ArrowUp': | ||
| 153 | + moveImage('up') | ||
| 154 | + break | ||
| 155 | + case 'ArrowDown': | ||
| 156 | + moveImage('down') | ||
| 157 | + break | ||
| 158 | + case 'ArrowLeft': | ||
| 159 | + moveImage('left') | ||
| 160 | + break | ||
| 161 | + case 'ArrowRight': | ||
| 162 | + moveImage('right') | ||
| 163 | + break | ||
| 164 | + case '+': | ||
| 165 | + scaleImage(1.01) | ||
| 166 | + break | ||
| 167 | + case '-': | ||
| 168 | + scaleImage(0.99) | ||
| 169 | + break | ||
| 170 | + case 'r': | ||
| 171 | + rotateMap(10) | ||
| 172 | + break | ||
| 173 | + case 'R': | ||
| 174 | + rotateMap(-10) | ||
| 175 | + break | ||
| 176 | + } | ||
| 177 | +} | ||
| 178 | + | ||
| 113 | onMounted(async () => { | 179 | onMounted(async () => { |
| 114 | loadMap(); | 180 | loadMap(); |
| 181 | + window.addEventListener('keydown', handleKeydown) | ||
| 115 | }); | 182 | }); |
| 116 | 183 | ||
| 184 | +onBeforeUnmount(() => { | ||
| 185 | + window.removeEventListener('keydown', handleKeydown) | ||
| 186 | +}) | ||
| 187 | + | ||
| 117 | function loadMap() { | 188 | function loadMap() { |
| 118 | // 初始化地图 | 189 | // 初始化地图 |
| 119 | map.value = new AMap.Map('map-container', { | 190 | map.value = new AMap.Map('map-container', { |
| ... | @@ -357,6 +428,61 @@ const copyText = (text) => { | ... | @@ -357,6 +428,61 @@ const copyText = (text) => { |
| 357 | console.error('复制失败:', err); | 428 | console.error('复制失败:', err); |
| 358 | }); | 429 | }); |
| 359 | } | 430 | } |
| 431 | + | ||
| 432 | +// 控制对象的状态 | ||
| 433 | +const position = ref({ x: 0, y: 0 }) | ||
| 434 | +const scale = ref(1) | ||
| 435 | +const rotation = ref(0) | ||
| 436 | + | ||
| 437 | +// 移动步长 | ||
| 438 | +const MOVE_STEP = 10 | ||
| 439 | +// 缩放比例 | ||
| 440 | +const ZOOM_FACTOR = 1.2 | ||
| 441 | +// 旋转步长 | ||
| 442 | +const ROTATE_STEP = 30 | ||
| 443 | + | ||
| 444 | +// 移动控制 | ||
| 445 | +const move = (direction) => { | ||
| 446 | + switch(direction) { | ||
| 447 | + case 'up': | ||
| 448 | + position.value.y -= MOVE_STEP | ||
| 449 | + break | ||
| 450 | + case 'down': | ||
| 451 | + position.value.y += MOVE_STEP | ||
| 452 | + break | ||
| 453 | + case 'left': | ||
| 454 | + position.value.x -= MOVE_STEP | ||
| 455 | + break | ||
| 456 | + case 'right': | ||
| 457 | + position.value.x += MOVE_STEP | ||
| 458 | + break | ||
| 459 | + } | ||
| 460 | +} | ||
| 461 | + | ||
| 462 | +// 放大 | ||
| 463 | +const zoomIn = () => { | ||
| 464 | + scale.value *= ZOOM_FACTOR | ||
| 465 | +} | ||
| 466 | + | ||
| 467 | +// 缩小 | ||
| 468 | +const zoomOut = () => { | ||
| 469 | + scale.value /= ZOOM_FACTOR | ||
| 470 | +} | ||
| 471 | + | ||
| 472 | +// 旋转 | ||
| 473 | +const rotate = (angle) => { | ||
| 474 | + rotation.value += angle | ||
| 475 | +} | ||
| 476 | + | ||
| 477 | +// 组合样式 | ||
| 478 | +const objectStyle = computed(() => ({ | ||
| 479 | + transform: ` | ||
| 480 | + translate(${position.value.x}px, ${position.value.y}px) | ||
| 481 | + scale(${scale.value}) | ||
| 482 | + rotate(${rotation.value}deg) | ||
| 483 | + `, | ||
| 484 | + transition: 'transform 0.3s ease-in-out' | ||
| 485 | +})) | ||
| 360 | </script> | 486 | </script> |
| 361 | 487 | ||
| 362 | <style> | 488 | <style> |
| ... | @@ -374,4 +500,60 @@ const copyText = (text) => { | ... | @@ -374,4 +500,60 @@ const copyText = (text) => { |
| 374 | border-radius: 5px; | 500 | border-radius: 5px; |
| 375 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); | 501 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); |
| 376 | } | 502 | } |
| 503 | + | ||
| 504 | + | ||
| 505 | +.controls-container { | ||
| 506 | + position: absolute; | ||
| 507 | + top: 8rem; | ||
| 508 | + right: 10px; | ||
| 509 | + display: flex; | ||
| 510 | + flex-direction: column; | ||
| 511 | + align-items: center; | ||
| 512 | + gap: 2rem; | ||
| 513 | +} | ||
| 514 | + | ||
| 515 | +.remote-control { | ||
| 516 | + display: flex; | ||
| 517 | + gap: 1rem; | ||
| 518 | + padding: 1rem; | ||
| 519 | + background: #f0f0f0; | ||
| 520 | + border-radius: 10px; | ||
| 521 | +} | ||
| 522 | + | ||
| 523 | +.direction-control { | ||
| 524 | + display: flex; | ||
| 525 | + flex-direction: column; | ||
| 526 | + align-items: center; | ||
| 527 | + gap: 5px; | ||
| 528 | +} | ||
| 529 | + | ||
| 530 | +.horizontal { | ||
| 531 | + display: flex; | ||
| 532 | + gap: 5px; | ||
| 533 | +} | ||
| 534 | + | ||
| 535 | +button.z-button { | ||
| 536 | + width: 50px; | ||
| 537 | + height: 50px; | ||
| 538 | + font-size: 20px; | ||
| 539 | + cursor: pointer; | ||
| 540 | + border: 1px solid #ccc; | ||
| 541 | + border-radius: 5px; | ||
| 542 | + background: white; | ||
| 543 | + transition: all 0.2s; | ||
| 544 | +} | ||
| 545 | + | ||
| 546 | +button.z-button:hover { | ||
| 547 | + background: #e0e0e0; | ||
| 548 | +} | ||
| 549 | + | ||
| 550 | +button.z-button:active { | ||
| 551 | + transform: scale(0.95); | ||
| 552 | +} | ||
| 553 | + | ||
| 554 | +.zoom-control, .rotate-control { | ||
| 555 | + display: flex; | ||
| 556 | + flex-direction: column; | ||
| 557 | + gap: 5px; | ||
| 558 | +} | ||
| 377 | </style> | 559 | </style> | ... | ... |
-
Please register or login to post a comment