当前位置: 首页 > news >正文

Vue3 + TypeScript 实现 PC 端鼠标横向拖动滚动

功能说明

​​拖动功能​​:

  • 鼠标按下时记录初始位置和滚动位置
  • 拖动过程中计算移动距离并更新滚动位置
  • 松开鼠标后根据速度实现惯性滚动

​​滚动控制​​:

  • 支持鼠标滚轮横向滚动(通过 wheel 事件)
  • 自动边界检测防止滚动超出内容范围

实现代码

<template><div ref="scrollContainer" class="horizontal-scroll-container"@mousedown="startDrag"@mousemove="onDrag"@mouseup="stopDrag"@mouseleave="stopDrag"><div class="scroll-content"><div v-for="(item, index) in items" :key="index" class="item">{{ item }}</div></div></div>
</template><script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'// 定义滚动容器引用
const scrollContainer = ref<HTMLElement | null>(null)// 定义滚动内容数据
const items = ref<string[]>(Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`))// 拖动状态变量
let isDragging = false
let startX = 0
let scrollLeft = 0
let lastTime = 0
let velocity = 0// 开始拖动
const startDrag = (e: MouseEvent): void => {if (!scrollContainer.value) returnisDragging = truestartX = e.pageX - scrollContainer.value.getBoundingClientRect().leftscrollLeft = scrollContainer.value.scrollLeftlastTime = performance.now()scrollContainer.value.style.cursor = 'grabbing'
}// 拖动中
const onDrag = (e: MouseEvent): void => {if (!isDragging || !scrollContainer.value) returnconst x = e.pageX - scrollContainer.value.getBoundingClientRect().leftconst walk = (x - startX) * 1.5 // 调整滚动速度系数scrollContainer.value.scrollLeft = scrollLeft - walk// 计算速度(用于惯性滚动)const now = performance.now()velocity = (x - startX) / (now - lastTime)lastTime = now
}// 停止拖动
const stopDrag = (): void => {if (!isDragging || !scrollContainer.value) returnisDragging = falseif (Math.abs(velocity) > 0.1) {requestAnimationFrame(inertiaScroll)}scrollContainer.value.style.cursor = 'grab'
}// 惯性滚动
const inertiaScroll = (): void => {if (!scrollContainer.value || Math.abs(velocity) < 0.01) returnscrollContainer.value.scrollLeft += velocity * 10velocity *= 0.95 // 摩擦系数requestAnimationFrame(inertiaScroll)
}// 边界检测
const checkBounds = (): void => {if (!scrollContainer.value) returnconst containerWidth = scrollContainer.value.clientWidthconst contentWidth = scrollContainer.value.scrollWidthif (scrollContainer.value.scrollLeft < 0) {scrollContainer.value.scrollLeft = 0} else if (scrollContainer.value.scrollLeft > contentWidth - containerWidth) {scrollContainer.value.scrollLeft = contentWidth - containerWidth}
}// 鼠标滚轮横向滚动
const handleWheel = (e: WheelEvent): void => {if (!scrollContainer.value) returne.preventDefault()scrollContainer.value.scrollLeft += e.deltaYcheckBounds()
}// 生命周期钩子
onMounted(() => {if (scrollContainer.value) {scrollContainer.value.addEventListener('wheel', handleWheel, { passive: false })}
})onUnmounted(() => {if (scrollContainer.value) {scrollContainer.value.removeEventListener('wheel', handleWheel)}
})
</script><style scoped>
.horizontal-scroll-container {width: 100%;overflow-x: auto;white-space: nowrap;cursor: grab;height: 220px; /* 确保容器有固定高度 */border: 1px solid #eee;border-radius: 8px;padding: 10px;box-sizing: border-box;
}.horizontal-scroll-container:active {cursor: grabbing;
}.scroll-content {display: inline-block;
}.item {display: inline-block;width: 200px;height: 200px;margin-right: 10px;background: #f0f0f0;display: flex;align-items: center;justify-content: center;font-size: 20px;border: 1px solid #ddd;box-sizing: border-box;border-radius: 4px;transition: transform 0.2s ease, box-shadow 0.2s ease;
}.item:hover {transform: scale(1.02);box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
</style>

相关文章:

  • ModStartCMS v9.4.0 AI
  • 【Linux调整FTP端口】
  • 【人脸去遮挡前沿】三阶段级联引导学习如何突破真实场景遮挡难题?
  • java代码混淆
  • 国产化海光C86架构服务器安装windows实录
  • Elasticsearch:没有 “AG” 的 RAG?
  • 【AI论文】CipherBank:通过密码学挑战探索LLM推理能力的边界
  • 高级测试工程师 的面试题汇总
  • STM32printf重定向到串口含armcc和gcc两种方案
  • Cline原理分析-prompt
  • 【AI平台】n8n入门5:创建MCP服务,及vscode调用MCP测试
  • 解决在Mac上无法使用“ll”命令
  • 《系统分析师-第三阶段—总结(八)》
  • 免费在Colab运行Qwen3-0.6B——轻量高性能实战
  • 瑞芯微芯片算法开发初步实践
  • Seaborn
  • 基于SpringBoot的旅游网站的设计与实现
  • GEO vs SEO:从搜索引擎到生成引擎的优化新思路
  • MATLAB绘制饼图(二维/三维)
  • 基于ESP32 S3 + PVDF采集呼吸心率
  • 大学2025丨对话深大人工智能学院负责人李坚强:产学研生态比“造天才”更重要
  • 中央网信办部署开展“清朗·整治AI技术滥用”专项行动
  • 辽宁辽阳火灾3名伤者无生命危险
  • 太好玩了!坐进大卫·霍克尼的敞篷车进入他画笔下的四季
  • 四川省社科联期刊:不建议在读硕士、博士将导师挂名为第一作者
  • 科学时代重读“老子”的意义——对谈《老子智慧八十一讲》