hookehuyr

优化图片操作控制方式

...@@ -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" />&nbsp;
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 }}&nbsp;&nbsp;&nbsp;<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 }}&nbsp;&nbsp;&nbsp;<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>
......