merge
parent
683824e42e
commit
a75ab14d47
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 431 B |
Binary file not shown.
|
After Width: | Height: | Size: 542 B |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,237 @@
|
||||
<template>
|
||||
<div class="image-preview-container" id="imagePreviewContainer">
|
||||
<img id="zoomableImage" draggable="false" :src="imageUrl" />
|
||||
<div class="operation-container">
|
||||
<div>
|
||||
<UndoOutlined />
|
||||
</div>
|
||||
<div>
|
||||
<ZoomInOutlined @click="bigScale" />
|
||||
</div>
|
||||
<div>
|
||||
<ZoomOutOutlined @click="smallScale"/>
|
||||
</div>
|
||||
<div>
|
||||
<RedoOutlined @click="transform" />
|
||||
</div>
|
||||
<div>
|
||||
<CloseOutlined @click="closePreview"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ZoomInOutlined, ZoomOutOutlined, RedoOutlined, UndoOutlined, CloseOutlined } from '@ant-design/icons-vue';
|
||||
import {ref,onMounted,defineEmits,inject,defineProps} from 'vue';
|
||||
|
||||
const emits = defineEmits(["closeImagePreview"])
|
||||
|
||||
const props = defineProps({
|
||||
globalImagePreviewUrl:{
|
||||
type:String
|
||||
}
|
||||
})
|
||||
|
||||
const imageUrl = props.globalImagePreviewUrl
|
||||
|
||||
|
||||
let isDragging = false;
|
||||
let initialMouseX;
|
||||
let initialMouseY;
|
||||
let initialImageX;
|
||||
let initialImageY;
|
||||
|
||||
|
||||
onMounted(()=>{
|
||||
|
||||
const draggableImage = document.getElementById('zoomableImage');
|
||||
const imageContainer = document.getElementById('imagePreviewContainer');
|
||||
|
||||
|
||||
|
||||
|
||||
const zoomableImage = document.getElementById("zoomableImage");
|
||||
// zoomableImage.addEventListener('wheel', handleWheel);
|
||||
|
||||
|
||||
var scale = 1;
|
||||
var minScale = 0.5;
|
||||
var maxScale = 3;
|
||||
var scaleFactor = 0.1;
|
||||
|
||||
var containerRect = imageContainer.getBoundingClientRect();
|
||||
|
||||
imageContainer.addEventListener('wheel', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
var mouseX = event.clientX - containerRect.left; // 鼠标相对于容器的X坐标
|
||||
var mouseY = event.clientY - containerRect.top; // 鼠标相对于容器的Y坐标
|
||||
|
||||
var delta = -Math.max(-1, Math.min(1, (event.deltaY || -event.detail)));
|
||||
var zoomFactor = Math.exp(delta * scaleFactor);
|
||||
console.log("delta",delta,zoomFactor);
|
||||
|
||||
|
||||
var oldWidth = zoomableImage.clientWidth;
|
||||
var oldHeight = zoomableImage.clientHeight;
|
||||
|
||||
var newWidth = Math.min(Math.max(oldWidth * zoomFactor, containerRect.width * minScale), containerRect.width * maxScale);
|
||||
var newHeight = Math.min(Math.max(oldHeight * zoomFactor, containerRect.height * minScale), containerRect.height * maxScale);
|
||||
|
||||
var widthDiff = newWidth - oldWidth;
|
||||
var heightDiff = newHeight - oldHeight;
|
||||
|
||||
var mouseXPercent = mouseX / containerRect.width;
|
||||
var mouseYPercent = mouseY / containerRect.height;
|
||||
|
||||
var translateX = widthDiff * mouseXPercent;
|
||||
var translateY = heightDiff * mouseYPercent;
|
||||
|
||||
scale *= zoomFactor;
|
||||
|
||||
zoomableImage.style.transformOrigin = mouseXPercent * 100 + '% ' + mouseYPercent * 100 + '%';
|
||||
zoomableImage.style.transform = 'scale(' + scale + ') translate(' + translateX + 'px, ' + translateY + 'px)';
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
draggableImage.addEventListener('mousedown', function(event) {
|
||||
isDragging = true;
|
||||
initialMouseX = event.clientX;
|
||||
initialMouseY = event.clientY;
|
||||
initialImageX = draggableImage.offsetLeft;
|
||||
initialImageY = draggableImage.offsetTop;
|
||||
draggableImage.style.cursor = 'grabbing';
|
||||
});
|
||||
|
||||
document.addEventListener('mousemove', function(event) {
|
||||
if (isDragging) {
|
||||
const deltaX = event.clientX - initialMouseX;
|
||||
const deltaY = event.clientY - initialMouseY;
|
||||
draggableImage.style.left = initialImageX + deltaX + 'px';
|
||||
draggableImage.style.top = initialImageY + deltaY + 'px';
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('mouseup', function() {
|
||||
isDragging = false;
|
||||
draggableImage.style.cursor = 'default';
|
||||
});
|
||||
|
||||
|
||||
})
|
||||
|
||||
function handleWheel(event) {
|
||||
// event.preventDefault();
|
||||
// const delta = Math.sign(event.deltaY);
|
||||
// if (delta > 0) {
|
||||
// if(scale > 0.2){
|
||||
// scale -= scaleStep;
|
||||
// }else if(scale>1.6){
|
||||
// scale -= 0.2;
|
||||
// }
|
||||
// } else {
|
||||
// if(scale>1.6){
|
||||
// scale += 0.2;
|
||||
// }else{
|
||||
// scale += scaleStep;
|
||||
// }
|
||||
|
||||
// }
|
||||
// zoomableImage.style.transform = `scale(${scale})`;
|
||||
const imageContainer = document.getElementById('imagePreviewContainer');
|
||||
let containerRect = imageContainer.getBoundingClientRect();
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
var mouseX = event.clientX - containerRect.left; // 鼠标相对于容器的X坐标
|
||||
var mouseY = event.clientY - containerRect.top; // 鼠标相对于容器的Y坐标
|
||||
|
||||
var delta = Math.max(-1, Math.min(1, (event.deltaY || -event.detail)));
|
||||
|
||||
var zoomFactor = Math.exp(delta * scaleFactor);
|
||||
|
||||
var oldWidth = zoomableImage.clientWidth;
|
||||
var oldHeight = zoomableImage.clientHeight;
|
||||
|
||||
var newWidth = Math.min(Math.max(oldWidth * zoomFactor, containerRect.width * minScale), containerRect.width * maxScale);
|
||||
var newHeight = Math.min(Math.max(oldHeight * zoomFactor, containerRect.height * minScale), containerRect.height * maxScale);
|
||||
|
||||
var widthDiff = newWidth - oldWidth;
|
||||
var heightDiff = newHeight - oldHeight;
|
||||
|
||||
var mouseXPercent = mouseX / containerRect.width;
|
||||
var mouseYPercent = mouseY / containerRect.height;
|
||||
|
||||
var translateX = widthDiff * mouseXPercent;
|
||||
var translateY = heightDiff * mouseYPercent;
|
||||
|
||||
scale *= zoomFactor;
|
||||
|
||||
zoomableImage.style.transformOrigin = mouseXPercent * 100 + '% ' + mouseYPercent * 100 + '%';
|
||||
zoomableImage.style.transform = 'scale(' + scale + ') translate(' + translateX + 'px, ' + translateY + 'px)';
|
||||
}
|
||||
|
||||
function smallScale():void {
|
||||
if(scale>0.4){
|
||||
scale-=0.4;
|
||||
}
|
||||
zoomableImage.style.transform = `scale(${scale})`;
|
||||
}
|
||||
|
||||
function bigScale():void {
|
||||
scale+=0.4;
|
||||
zoomableImage.style.transform = `scale(${scale})`;
|
||||
}
|
||||
|
||||
function closePreview():void{
|
||||
emits("closeImagePreview");
|
||||
}
|
||||
|
||||
</script>
|
||||
<style type="less" scoped>
|
||||
.image-preview-container{
|
||||
position:absolute;
|
||||
z-index:99999999;
|
||||
top:0px;
|
||||
left:0px;
|
||||
width:100%;
|
||||
height: 100%;
|
||||
margin:0px auto;
|
||||
background:rgba(0,0,0,0.4);
|
||||
overflow: hidden;
|
||||
#zoomableImage {
|
||||
position:relative;
|
||||
top:0px;
|
||||
left:20%;
|
||||
width:60%;
|
||||
cursor:default;
|
||||
display: block;
|
||||
max-width: none;
|
||||
max-height: none;
|
||||
transition: transform 0.2s ease-out; /* 添加平滑过渡效果 */
|
||||
}
|
||||
.operation-container{
|
||||
padding:0px 100px;
|
||||
width: calc( 100% - 0px);
|
||||
height:60px;
|
||||
position:absolute;
|
||||
bottom:0px;
|
||||
left:0px;
|
||||
background:rgba(0,0,0,0.3);
|
||||
display: flex;
|
||||
line-height: 60px;
|
||||
color:#fff;
|
||||
div {
|
||||
flex:1;
|
||||
text-align: center;
|
||||
cursor:pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<div class="image-preview-container" id="imagePreviewContainer">
|
||||
<img id="zoomableImage" draggable="false" src="http://192.168.10.102:9023//20240629\2024062914291178850041.jpg" />
|
||||
<div class="operation-container">
|
||||
<div>
|
||||
<UndoOutlined />
|
||||
</div>
|
||||
<div>
|
||||
<ZoomInOutlined @click="bigScale" />
|
||||
</div>
|
||||
<div>
|
||||
<ZoomOutOutlined @click="smallScale"/>
|
||||
</div>
|
||||
<div>
|
||||
<RedoOutlined @click="transform" />
|
||||
</div>
|
||||
<div>
|
||||
<CloseOutlined @click="closePreview"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ZoomInOutlined, ZoomOutOutlined, RedoOutlined, UndoOutlined, CloseOutlined } from '@ant-design/icons-vue';
|
||||
import {ref,onMounted,defineEmits,} from 'vue';
|
||||
|
||||
const emits = defineEmits(["defineEmits"])
|
||||
|
||||
|
||||
let scale = 1.0;
|
||||
const scaleStep = 0.15;
|
||||
|
||||
let isDragging = false;
|
||||
let initialMouseX;
|
||||
let initialMouseY;
|
||||
let initialImageX;
|
||||
let initialImageY;
|
||||
|
||||
|
||||
|
||||
onMounted(()=>{
|
||||
const zoomableImage = document.getElementById("zoomableImage");
|
||||
zoomableImage.addEventListener('wheel', handleWheel);
|
||||
|
||||
|
||||
const draggableImage = document.getElementById('zoomableImage');
|
||||
const imageContainer = document.getElementById('imagePreviewContainer');
|
||||
|
||||
draggableImage.addEventListener('mousedown', function(event) {
|
||||
isDragging = true;
|
||||
initialMouseX = event.clientX;
|
||||
initialMouseY = event.clientY;
|
||||
initialImageX = draggableImage.offsetLeft;
|
||||
initialImageY = draggableImage.offsetTop;
|
||||
draggableImage.style.cursor = 'grabbing';
|
||||
});
|
||||
|
||||
document.addEventListener('mousemove', function(event) {
|
||||
if (isDragging) {
|
||||
const deltaX = event.clientX - initialMouseX;
|
||||
const deltaY = event.clientY - initialMouseY;
|
||||
draggableImage.style.left = initialImageX + deltaX + 'px';
|
||||
draggableImage.style.top = initialImageY + deltaY + 'px';
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('mouseup', function() {
|
||||
isDragging = false;
|
||||
draggableImage.style.cursor = 'default';
|
||||
});
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
function handleWheel(event) {
|
||||
event.preventDefault();
|
||||
const delta = Math.sign(event.deltaY);
|
||||
if (delta > 0) {
|
||||
if(scale > 0.2){
|
||||
scale -= scaleStep;
|
||||
}else if(scale>1.6){
|
||||
scale -= 0.2;
|
||||
}
|
||||
} else {
|
||||
if(scale>1.6){
|
||||
scale += 0.2;
|
||||
}else{
|
||||
scale += scaleStep;
|
||||
}
|
||||
|
||||
}
|
||||
zoomableImage.style.transform = `scale(${scale})`;
|
||||
}
|
||||
|
||||
function smallScale():void {
|
||||
if(scale>0.4){
|
||||
scale-=0.4;
|
||||
}
|
||||
zoomableImage.style.transform = `scale(${scale})`;
|
||||
}
|
||||
|
||||
function bigScale():void {
|
||||
scale+=0.4;
|
||||
zoomableImage.style.transform = `scale(${scale})`;
|
||||
}
|
||||
|
||||
function closePreview():void{
|
||||
emits("defineEmits");
|
||||
}
|
||||
</script>
|
||||
<style type="less" scoped>
|
||||
.image-preview-container{
|
||||
position:absolute;
|
||||
z-index:99999;
|
||||
width:500px;
|
||||
height:500px;
|
||||
margin:0px auto;
|
||||
background:rgba(0,0,0,0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#zoomableImage{
|
||||
width:100%;
|
||||
position:absolute;
|
||||
cursor:default;
|
||||
}
|
||||
.operation-container{
|
||||
padding:0px 100px;
|
||||
width: calc( 100% - 200px);
|
||||
height:60px;
|
||||
position:absolute;
|
||||
bottom:0px;
|
||||
left:0px;
|
||||
background:rgba(0,0,0,0.2);
|
||||
display: flex;
|
||||
line-height: 60px;
|
||||
color:#fff;
|
||||
}
|
||||
.operation-container div{
|
||||
flex:1;
|
||||
text-align: center;
|
||||
cursor:pointer;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,46 @@
|
||||
import type {
|
||||
ProjectConfig,
|
||||
HeaderSetting,
|
||||
MenuSetting,
|
||||
TransitionSetting,
|
||||
MultiTabsSetting,
|
||||
} from '#/config';
|
||||
import type { BeforeMiniState, ApiAddress } from '#/store';
|
||||
|
||||
import { defineStore } from 'pinia';
|
||||
import { store } from '@/store';
|
||||
|
||||
import { resetRouter } from '@/router';
|
||||
import { deepMerge } from '@/utils';
|
||||
|
||||
interface FormFile {
|
||||
url:String
|
||||
}
|
||||
|
||||
export const userFormFileStore = defineStore({
|
||||
id: 'formfileurl',
|
||||
state: (): FormFile => ({
|
||||
url:""
|
||||
}),
|
||||
getters: {
|
||||
getUrl(state): boolean {
|
||||
return state.url;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setUrl(url:string): void {
|
||||
this.url = url;
|
||||
},
|
||||
},
|
||||
mutations:{
|
||||
setUrl(url:string): void {
|
||||
this.url = url;
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
// Need to be used outside the setup
|
||||
export function useAppStoreWithOut() {
|
||||
return userFormFileStore(store);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue