【Vue】vue3 元素在某區域內縮放拖拽 附加按鈕縮放

示例

image

代碼(邏輯請看註釋)

<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項目中鼠標滾輪縮放圖片大小和拖拽效果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章