dom实现缩放和拖拽功能

169 阅读1分钟

项目中有个需求,需要实现div的拖动和缩放功能,可以通过监听鼠标事件、计算位移和缩放比例,并更新div的样式来实现。

思路:

1、要实现拖拽功能,需要监听鼠标的按下、移动和松开事件。在拖动过程中,需要计算鼠标的位移并更新div的位置。

  const dragging = ref(false);
  const position = ref({ x: 0, y: 0 }); 
  const startMousePos = ref({ x: 0, y: 0 }); 
  const startElementPos = ref({ x: 0, y: 0 }); 

  const onMouseDown = (event) => {
    dragging.value = true;
    startMousePos.value = { x: event.clientX, y: event.clientY };
    startElementPos.value = { x: position.value.x, y: position.value.y };
    document.addEventListener('mousemove', onMouseMove);
    document.addEventListener('mouseup', onMouseUp);
  };

  const onMouseMove = (event) => {
    if (!dragging.value) return;
    const deltaX = event.clientX - startMousePos.value.x;
    const deltaY = event.clientY - startMousePos.value.y;
    console.log(deltaX, deltaY);
    position.value = {
      x: startElementPos.value.x + deltaX,
      y: startElementPos.value.y + deltaY,
    };
  };

  const onMouseUp = () => {
    dragging.value = false;
    document.removeEventListener('mousemove', onMouseMove);
    document.removeEventListener('mouseup', onMouseUp);
  };

2、缩放比较简单,可以监听鼠标滚轮事件,根据滚轮的滚动方向来调整div的缩放比例。

  const scaling = ref(false);
  const scale = ref(1); 
  const scaleSteps = ref(0.2); 
  const scaleHandle = (event) => {
    scaling.value = true;
    //获取滚轮滚动方向
    let delta = Math.sign(event.deltaY);
    scale.value += delta * scaleSteps.value;
    // 设置缩放范围
    if (scale.value < 0.5) scale.value = 0.5;
    if (scale.value > 2) scale.value = 2;
    scaling.value = false;
  };

附完整代码(基于vue开发)

<template>
  <div
    class="drag-scale-container"
    @mousedown="onMouseDown"
    @wheel.prevent="scaleHandle"
    :style="{ left: `${position.x}px`, top: `${position.y}px`, transform: `scale(${scale})` }"
  >
    <slot></slot>
  </div>
</template>

<script setup lang="ts">
  import { ref } from 'vue';
  /**
   * 设置拖拽功能
   */
  const dragging = ref(false);
  const position = ref({ x: 0, y: 0 }); //dom现在坐标
  const startMousePos = ref({ x: 0, y: 0 }); //鼠标按下去的坐标
  const startElementPos = ref({ x: 0, y: 0 }); //dom上次的坐标

  const onMouseDown = (event) => {
    dragging.value = true;
    startMousePos.value = { x: event.clientX, y: event.clientY };
    startElementPos.value = { x: position.value.x, y: position.value.y };
    document.addEventListener('mousemove', onMouseMove);
    document.addEventListener('mouseup', onMouseUp);
  };

  const onMouseMove = (event) => {
    if (!dragging.value) return;
    const deltaX = event.clientX - startMousePos.value.x;
    const deltaY = event.clientY - startMousePos.value.y;
    console.log(deltaX, deltaY);
    position.value = {
      x: startElementPos.value.x + deltaX,
      y: startElementPos.value.y + deltaY,
    };
  };

  const onMouseUp = () => {
    dragging.value = false;
    document.removeEventListener('mousemove', onMouseMove);
    document.removeEventListener('mouseup', onMouseUp);
  };

  /**
   * 设置拖拽功能
   */
  const scaling = ref(false);
  const scale = ref(1); //缩放比例
  const scaleSteps = ref(0.2); //缩放系数
  const scaleHandle = (event) => {
    if (dragging.value) return;
    scaling.value = true;
    //获取滚轮滚动方向
    let delta = Math.sign(event.deltaY);
    scale.value += delta * scaleSteps.value;
    // 设置缩放范围
    if (scale.value < 0.5) scale.value = 0.5;
    if (scale.value > 2) scale.value = 2;
    scaling.value = false;
  };
</script>

<style lang="less" scoped>
  .drag-scale-container {
    position: absolute;
    cursor: move;
    transform-origin: center;
  }
</style>