Vue根据鼠标位置为中心实现滚轮缩放


在 Vue.js 中实现一个 div 元素根据鼠标位置为中心进行滚轮缩放,可以通过以下步骤完成:

  1. 捕捉鼠标滚轮事件:监听 wheel 事件以检测用户的滚动操作。
  2. 计算缩放比例:根据滚轮的滚动方向和幅度调整缩放比例。
  3. 调整元素的位置:确保缩放中心与鼠标位置对齐,这需要根据鼠标的位置和缩放比例调整 translate 属性。

下面是一个完整的示例,使用 Vue 3 组合式 API 实现该功能:

示例代码

<template>
  <div
    class="zoom-container"
    ref="container"
    @wheel.prevent="handleWheel"
  >
    <div
      class="zoom-content"
      :style="contentStyle"
    >
      <!-- 你的内容在这里 -->
      <p>缩放内容</p>
    </div>
  </div>
</template>

<script>
import { ref, reactive, computed, onMounted } from 'vue';

export default {
  name: 'ZoomableDiv',
  setup() {
    const container = ref(null);
    const state = reactive({
      scale: 1,
      translateX: 0,
      translateY: 0,
    });

    const contentStyle = computed(() => ({
      transform: `translate(${state.translateX}px, ${state.translateY}px) scale(${state.scale})`,
      transformOrigin: '0 0',
      transition: 'transform 0.1s ease-out',
    }));

    const handleWheel = (event) => {
      const delta = -event.deltaY;
      const zoomFactor = 0.001;
      const scaleFactor = 1 + delta * zoomFactor;

      const rect = container.value.getBoundingClientRect();
      const offsetX = event.clientX - rect.left;
      const offsetY = event.clientY - rect.top;

      // 计算新的缩放比例
      const newScale = state.scale * scaleFactor;

      // 计算缩放中心点相对于内容的位置
      const dx = offsetX - state.translateX;
      const dy = offsetY - state.translateY;

      // 计算新的位移以保持缩放中心
      state.translateX -= dx * (scaleFactor - 1);
      state.translateY -= dy * (scaleFactor - 1);

      state.scale = newScale;
    };

    return {
      container,
      contentStyle,
      handleWheel,
    };
  },
};
</script>

<style scoped>
.zoom-container {
  width: 800px;
  height: 600px;
  border: 1px solid #ccc;
  overflow: hidden;
  position: relative;
  cursor: grab;
}

.zoom-content {
  width: 100%;
  height: 100%;
  /* 初始位置 */
  transform: translate(0px, 0px) scale(1);
  transform-origin: 0 0;
}
</style>

详细说明

  1. 模板部分 (template)

    • 创建一个包含 zoom-containerzoom-content 的结构。
    • zoom-container 负责捕捉滚轮事件,并作为 div 的容器。
    • zoom-content 是实际进行缩放和位移的内容区域。
  2. 脚本部分 (script)

    • 使用 Vue 3 的组合式 API (setup) 来管理组件的状态和逻辑。
    • 状态管理
      • scale:当前的缩放比例,初始值为 1
      • translateXtranslateY:当前的平移值,确保缩放以鼠标位置为中心。
    • 计算样式 (contentStyle)
      • 根据 scaletranslate 动态计算 transform 属性,实现缩放和平移。
      • transform-origin 设置为 0 0,这样可以更方便地控制缩放中心。
    • 事件处理 (handleWheel)
      • 阻止默认的滚轮行为(@wheel.prevent)。
      • 根据 deltaY 计算缩放比例(向上滚动放大,向下滚动缩小)。
      • 获取鼠标在容器内的坐标 (offsetX, offsetY)。
      • 计算新的缩放比例。
      • 调整 translateXtranslateY,确保缩放中心与鼠标位置一致。
  3. 样式部分 (style)

    • zoom-container 设置了固定大小、边框和隐藏溢出内容,以便内容可以在其中缩放和平移。
    • zoom-content 初始时没有位移,缩放比例为 1

进一步优化

  • 平滑过渡:可以调整 transition 的时间和缓动函数,使缩放更平滑。
  • 最小/最大缩放限制:为了避免过度缩放,可以在计算 newScale 时添加上下限。
  • 平移限制:防止内容在缩放后被移动到容器外部。
  • 移动支持:添加鼠标拖动功能,允许用户平移内容。

最小/最大缩放限制示例

handleWheel 方法中添加缩放限制:

const handleWheel = (event) => {
  const delta = -event.deltaY;
  const zoomFactor = 0.001;
  let scaleFactor = 1 + delta * zoomFactor;

  // 设置最小和最大缩放比例
  const minScale = 0.5;
  const maxScale = 3;
  const newScale = Math.min(Math.max(state.scale * scaleFactor, minScale), maxScale);
  scaleFactor = newScale / state.scale;

  const rect = container.value.getBoundingClientRect();
  const offsetX = event.clientX - rect.left;
  const offsetY = event.clientY - rect.top;

  const dx = offsetX - state.translateX;
  const dy = offsetY - state.translateY;

  state.translateX -= dx * (scaleFactor - 1);
  state.translateY -= dy * (scaleFactor - 1);

  state.scale = newScale;
};

资源推荐

通过上述方法,你可以在 Vue.js 中实现一个根据鼠标位置为中心进行缩放的 div 元素,提供更好的用户交互体验。

声明:HEUE NOTE|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA 4.0协议进行授权

转载:转载请注明原文链接 - Vue根据鼠标位置为中心实现滚轮缩放