示例
![image](https://img2023.cnblogs.com/blog/2002005/202302/2002005-20230224140635228-131160040.gif)
代码(逻辑请看注释)
<template>
<div class="wapper" :ref="refs.wrpapper" @wheel.prevent="scale($event)">
<div
class="box"
:ref="refs.box"
@mousedown="dragstart($event)"
>
缩放拖拽
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue';
const refs = {
box: ref<HTMLElement | null>(null),
wrapper: ref<HTMLElement | null>(null),
};
const dragData = reactive({
x: 0,
y: 0,
left: 0,
top: 0,
});
const scaleData = reactive({
scale: 1,
scaleNum: 0.1,
scaleMax: 100,
scaleMin: 0,
});
function dragstart(e: MouseEvent) {
refs.box.value.style.transition = 'none';
e.preventDefault();
const box = refs.box.value as HTMLElement;
const wrapper = refs.wrapper.value as HTMLElement;
dragData.x = e.pageX - box.offsetLeft;
dragData.y = e.pageY - box.offsetTop;
document.addEventListener('mousemove', move);
function move(event: any) {
dragData.left = event.pageX - dragData.x;
dragData.top = event.pageY - dragData.y;
box.style.left = dragData.left + 'px';
box.style.top = dragData.top + 'px';
}
document.addEventListener('mouseup', function () {
document.removeEventListener('mousemove', move);
});
document.addEventListener('mouseout', function () {
document.removeEventListener('mousemove', move);
});
}
function scale(e: any) {
let dy = -e.deltaY || e.wheelDeltaY;
if (dy < 0) {
scaleData.scale -= scaleData.scaleNum;
} else {
scaleData.scale += scaleData.scaleNum;
}
if (scaleData.scale >= scaleData.scaleMax) {
scaleData.scale = scaleData.scaleMax;
return;
}
if (scaleData.scale <= scaleData.scaleMin) {
scaleData.scale = scaleData.scaleMin;
return;
}
refs.box.value.style.transition = 'none';
refs.box.value.style.transform = `translate(-50%, -50%) scale(${scaleData.scale})`;
return false;
}
const rollBtn = (action: 'enlarge' | 'zoomin') => {
if (action === 'enlarge') {
scaleData.scale += 0.5;
} else {
scaleData.scale -= 0.5;
}
if (scaleData.scale >= scaleData.scaleMax) {
scaleData.scale = scaleData.scaleMax;
return;
}
if (scaleData.scale <= scaleData.scaleMin) {
scaleData.scale = scaleData.scaleMin;
return;
}
refs.box.value.style.transition = `all 0.3s ease-in-out`;
refs.box.value.style.transform = `translate(-50%, -50%) scale(${scaleData.scale})`;
};
</script>
<style scoped lang="scss">
.wapper {
width: 500px;
height: 500px;
background: #ccc;
position: relative;
overflow: hidden;
.box {
width: 100px;
height: 100px;
background-color: red;
cursor: move;
user-select: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
</style>
参考博客
手把手教你学会用vue实现元素拖拽移动+滚轮缩放功能
vue项目中鼠标滚轮缩放图片大小和拖拽效果
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步