1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<script setup lang="ts">
import { ref, reactive } from 'vue';
const imgUrl = ref('https://w.wallhaven.cc/full/kx/wallhaven-kx98xd.jpg');
const standard = ref(100);
const state = reactive({
zoomVal: 1,
left: 0,
top: 0,
});
function onMousedown(e: any) {
let oDiv = e.target; // 获取当前元素
// 算出鼠标相对元素的位置
let disX = e.clientX - oDiv.offsetLeft;
let disY = e.clientY - oDiv.offsetTop;
document.onmousemove = function (e: any) {
// 用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
let left = e.clientX - disX;
let top = e.clientY - disY;
// oDiv.style.left = left + 'px';
// oDiv.style.top = top + 'px';
state.left = left;
state.top = top;
};
//为document绑定一个鼠标抬起事件,鼠标松开时,将box固定在当前位置
document.onmouseup = function () {
//取消document的onmousemove事件
document.onmousemove = null;
//取消document的onmouseup事件
document.onmouseup = null;
};
}
function onWheel(e: any) {
let direction = e.deltaY > 0 ? 'down' : 'up';
let val = state.zoomVal;
if (direction === 'up') {
// 滑轮向上滚动
val += 0.1;
if (val >= 2) {
val = 2;
}
} else {
// 滑轮向下滚动
val -= 0.1;
if (val <= 0.2) {
val = 0.2;
}
}
let diffScale = val - state.zoomVal;
let diffX = e.offsetX * diffScale;
let diffY = e.offsetY * diffScale;
state.zoomVal = val;
standard.value = Number((val * 100).toFixed(2));
state.left -= diffX;
state.top -= diffY;
}
function sliderUpdate(value: any) {
state.zoomVal = value / 100;
}
</script>
<template>
<div class="box q-ma-md">
<div class="tool-box">
<q-slider
v-model="standard"
:inner-min="20"
:min="0"
:max="200"
label
:label-value="standard + '%'"
@update:model-value="sliderUpdate"
/>
</div>
<div class="img-box">
<div
class="img-mask"
@mousedown.prevent="onMousedown"
@mousewheel.prevent="onWheel"
:style="{
backgroundImage: `url(${imgUrl})`,
transform: `scale(${state.zoomVal})`,
left: state.left + 'px',
top: state.top + 'px',
}"
></div>
</div>
</div>
</template>
<style lang="scss" scoped>
.box {
width: 800px;
height: 500px;
}
.tool-box {
box-sizing: border-box;
height: 40px;
border-top: 1px solid rgba(180, 180, 180, 0.3);
border-left: 1px solid rgba(180, 180, 180, 0.3);
border-right: 1px solid rgba(180, 180, 180, 0.3);
display: flex;
align-items: center;
padding: 0 16px;
}
.img-box {
height: calc(500px - 40px);
width: 100%;
border: 1px solid rgba(180, 180, 180, 0.3);
overflow: hidden;
position: relative;
.img-mask {
position: absolute;
box-sizing: border-box;
background-color: #dadada;
width: 100%;
height: 100%;
top: 0;
left: 0;
transform-origin: 0 0;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
}
</style>