示例
代碼(邏輯請看註釋)
<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, // 拖拽初始化時的x座標
y: 0, // 拖拽初始化時的y座標
left: 0, // 拖拽結束時的x偏移量
top: 0, // 拖拽結束時的y偏移量
});
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 添加鼠標移動事件
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) {
// mac 和 win 上的值不一樣 只能判斷是否大於小於0
// console.log('e.deltaY', e.deltaY);
// console.log('e.wheelDeltaY', e.wheelDeltaY);
// 瀏覽器兼容 chrome 爲e.deltaY firefox 爲e.wheelDeltaY
// 統一向上滾動爲正值,向下滾動爲負值
let dy = -e.deltaY || e.wheelDeltaY;
if (dy < 0) {
// console.log('縮小');
scaleData.scale -= scaleData.scaleNum;
} else {
// console.log('放大');
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項目中鼠標滾輪縮放圖片大小和拖拽效果