• vue中通过JavaScript实现web端鼠标横向滑动&触控板滑动效果-demo


    JavaScript实现web端鼠标横向滑动&触控板滑动效果 

    支持鼠标拖动滑动&触控板滑动效果

    web端实现滑动,就是对鼠标按下、鼠标松开、鼠标移动事件进行监听

    效果图 

     代码

    结构代码

    1. <template>
    2. <div class="swiper">
    3. <div class="container" ref="container">
    4. <div class="box" v-for="num in 40" :key="num">
    5. <img src="@/assets/logo.png" style="width: 58px; height: 58px" />
    6. <span>滑动元素{{ num }}span>
    7. div>
    8. div>
    9. div>
    10. template>

    样式代码

    1. <style lang="scss" scoped>
    2. .swiper {
    3. .container {
    4. width: 90%;
    5. margin: 0 auto;
    6. display: flex;
    7. /* white-space: nowrap; //避免子元素在父元素内换行 */
    8. overflow-x: auto; //显示横向滚动条
    9. /* scroll-snap-type: x mandatory; //自动吸附 */
    10. /* scroll-behavior: smooth; //平滑滚动的效果 */
    11. .box {
    12. width: 100px;
    13. min-height: 100px;
    14. padding: 0 20px;
    15. /* scroll-snap-align: start; //自动吸附 */
    16. }
    17. }
    18. ::-webkit-scrollbar {
    19. width: 0 !important;
    20. }
    21. ::-webkit-scrollbar {
    22. width: 0 !important;
    23. height: 0;
    24. }
    25. }
    26. style>

    业务逻辑代码


    在Vue中实现鼠标横向滑动&触控板滑动效果可以通过以下步骤实现:

    1. 首先在Vue中创建一个父组件,在该组件中引入子组件或者使用slot插入内容。

    2. 在父组件中创建一个div容器,用来包裹滑动内容。

    3. 在该div容器中绑定一个事件监听器,用来监听用户的鼠标或触摸板滑动事件。

    4. 在事件监听器中使用JavaScript获取鼠标或触摸板的滑动距离,并根据该距离计算出需要滑动的内容距离。

    5. 使用Vue的ref属性获取div容器,然后通过Vue的$refs属性访问该容器,并修改其left属性值,实现滑动效果。

    下面是一个简单的示例代码:

    1. <template>
    2. <div class="scroll-container" @mousemove="handleMouseMove"
    3. @touchmove="handleTouchMove">
    4. <div class="scroll-content" ref="content">
    5. <slot>slot>
    6. div>
    7. div>
    8. template>
    9. <script>
    10. export default {
    11. methods: {
    12. handleMouseMove(event) {
    13. const scrollContent = this.$refs.content;
    14. const scrollSpeed = 5; // 滑动速度
    15. scrollContent.style.left = `${-event.pageX / scrollSpeed}px`;
    16. },
    17. handleTouchMove(event) {
    18. const scrollContent = this.$refs.content;
    19. const scrollSpeed = 5; // 滑动速度
    20. scrollContent.style.left = `${-event.touches[0].pageX / scrollSpeed}px`;
    21. },
    22. },
    23. };
    24. script>
    25. <style>
    26. .scroll-container {
    27. width: 100%;
    28. height: 200px;
    29. overflow-x: scroll;
    30. }
    31. .scroll-content {
    32. position: relative;
    33. width: 2000px;
    34. height: 200px;
    35. white-space: nowrap;
    36. font-size: 0;
    37. }
    38. style>

    在上述示例代码中,我们创建了一个scroll-container容器并绑定了鼠标和触摸板的滑动事件监听器,然后使用JavaScript计算出需要滑动的距离,并修改了scroll-content容器的left属性值实现了滑动效果。需要注意的是,由于父组件的高度限制了滑动内容的高度,因此我们在scroll-content中使用了white-space: nowrap和font-size: 0两个CSS样式属性,防止滑动内容换行和出现空白间隙。


    在Vue中实现横向滑动效果可以通过以下步骤实现:

    1. 在Vue组件中定义一个容器div,并设置其样式为横向滚动条,例如:
    1. <div class="scroll-container" ref="scrollContainer">
    2. <div class="scroll-content">
    3. div>
    4. div>
    5. <style>
    6. .scroll-container {
    7. overflow-x: auto;
    8. white-space: nowrap;
    9. -webkit-overflow-scrolling: touch; // 兼容iOS平滑滚动
    10. }
    11. .scroll-content {
    12. display: inline-block;
    13. }
    14. style>

    在组件的created生命周期中,注册滑动事件监听器,并记录开始滑动时的鼠标位置或触摸位置:

    1. created() {
    2. this.$refs.scrollContainer.addEventListener('mousedown', this.handleMouseDown);
    3. this.$refs.scrollContainer.addEventListener('touchstart', this.handleTouchStart, { passive: true });
    4. },
    5. methods: {
    6. handleMouseDown(event) {
    7. this.startX = event.clientX;
    8. },
    9. handleTouchStart(event) {
    10. this.startX = event.touches[0].clientX;
    11. this.touching = true;
    12. }
    13. }

    在组件的mounted生命周期中,注册滑动事件监听器,并根据滑动方向和滑动距离计算出滚动距离,并通过JavaScript控制滚动条的位置:

    1. mounted() {
    2. this.$refs.scrollContainer.addEventListener('mousemove', this.handleMouseMove);
    3. this.$refs.scrollContainer.addEventListener('touchmove', this.handleTouchMove, { passive: false });
    4. this.$refs.scrollContainer.addEventListener('mouseup', this.handleMouseUp);
    5. this.$refs.scrollContainer.addEventListener('touchend', this.handleTouchEnd);
    6. },
    7. methods: {
    8. handleMouseMove(event) {
    9. if (this.startX) {
    10. const distance = event.clientX - this.startX;
    11. this.$refs.scrollContainer.scrollLeft -= distance;
    12. this.startX = event.clientX;
    13. }
    14. },
    15. handleTouchMove(event) {
    16. if (this.startX) {
    17. const distance = event.touches[0].clientX - this.startX;
    18. this.$refs.scrollContainer.scrollLeft -= distance;
    19. this.startX = event.touches[0].clientX;
    20. }
    21. },
    22. handleMouseUp() {
    23. this.startX = null;
    24. },
    25. handleTouchEnd() {
    26. this.startX = null;
    27. }
    28. }

    通过以上步骤,就可以在Vue中实现横向滑动效果,并且支持鼠标和触摸操作。如果需要支持惯性滑动效果,可以在滑动结束时根据滑动速度和滑动方向计算出滚动距离,并通过requestAnimationFrame动画函数实现平滑滚动效果。


    可以通过以下步骤实现该功能:

    绑定事件监听器,在vue组件的mounted生命周期函数或者created生命周期函数中,通过addEventListener方法绑定document的mousemove事件和touchmove事件。

    1. mounted() {
    2. document.addEventListener('mousemove', this.handleMouseMove);
    3. document.addEventListener('touchmove', this.handleMouseMove);
    4. },
    5. methods: {
    6. handleMouseMove(event) {
    7. // 处理鼠标或者触摸板的移动事件
    8. }
    9. }

    在处理移动事件的函数中,根据元素的滑动距离和滑动方向,通过style属性的left或者transform属性改变元素的位置。其中,可以通过computed属性或者ref获取需要滑动的元素的位置和宽度。

    1. handleMouseMove(event) {
    2. const delta = event.clientX - this.lastX;
    3. const direction = delta > 0 ? -1 : 1;
    4. const absDelta = Math.abs(delta);
    5. const containerLeft = this.$refs.container.offsetLeft;
    6. const containerWidth = this.$refs.container.offsetWidth;
    7. const contentWidth = this.$refs.content.offsetWidth;
    8. const maxDelta = contentWidth - containerWidth - containerLeft;
    9. const currentDelta = containerLeft + delta;
    10. if (absDelta > 5 && (currentDelta >= 0 || currentDelta <= maxDelta)) {
    11. // 通过transform改变滑动距离,可以有更好的性能表现
    12. this.$refs.container.style.transform = `translateX(${currentDelta}px)`;
    13. this.lastX = event.clientX;
    14. }
    15. }

    在滑动停止时,判断靠近开始的元素,通过计算元素到左端的距离来确定元素的位置,通过定位或者transform改变元素的位置。

    1. handleMouseMove(event) {
    2. // ...
    3. this.timer = setTimeout(() => {
    4. const containerLeft = this.$refs.container.offsetLeft;
    5. const containerWidth = this.$refs.container.offsetWidth;
    6. const contentWidth = this.$refs.content.offsetWidth;
    7. const maxDelta = contentWidth - containerWidth - containerLeft;
    8. if (containerLeft < 0) {
    9. this.$refs.container.style.transform = `translateX(0)`;
    10. return;
    11. }
    12. if (maxDelta < 0) {
    13. this.$refs.container.style.transform = `translateX(${-maxDelta}px)`;
    14. return;
    15. }
    16. const items = this.$refs.content.children;
    17. let minDelta = Infinity;
    18. let index = 0;
    19. for (let i = 0; i < items.length; i++) {
    20. const itemLeft = items[i].offsetLeft;
    21. const delta = Math.abs(itemLeft - containerLeft);
    22. if (delta < minDelta) {
    23. minDelta = delta;
    24. index = i;
    25. }
    26. }
    27. const itemLeft = items[index].offsetLeft;
    28. const delta = itemLeft - containerLeft;
    29. this.$refs.container.style.transform = `translateX(${-delta}px)`;
    30. }, 100);
    31. }

    注意在组件销毁时,需要清除事件监听器和定时器。

    1. beforeDestroy() {
    2. document.removeEventListener('mousemove', this.handleMouseMove);
    3. document.removeEventListener('touchmove', this.handleMouseMove);
    4. clearTimeout(this.timer);
    5. }

    完整的vue组件代码如下:

    1. <script>
    2. export default {
    3. name: "HorizontalScroll",
    4. data() {
    5. return {
    6. items: ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10"],
    7. lastX: 0,
    8. timer: null,
    9. };
    10. },
    11. mounted() {
    12. document.addEventListener('mousemove', this.handleMouseMove);
    13. document.addEventListener('touchmove', this.handleMouseMove);
    14. },
    15. beforeDestroy() {
    16. document.removeEventListener('mousemove', this.handleMouseMove);
    17. document.removeEventListener('touchmove', this.handleMouseMove);
    18. clearTimeout(this.timer);
    19. },
    20. methods: {
    21. handleMouseMove(event) {
    22. const delta = event.clientX - this.lastX;
    23. const direction = delta > 0 ? -1 : 1;
    24. const absDelta = Math.abs(delta);
    25. const containerLeft = this.$refs.container.offsetLeft;
    26. const containerWidth = this.$refs.container.offsetWidth;
    27. const contentWidth = this.$refs.content.offsetWidth;
    28. const maxDelta = contentWidth - containerWidth - containerLeft;
    29. const currentDelta = containerLeft + delta;
    30. if (absDelta > 5 && (currentDelta >= 0 || currentDelta <= maxDelta)) {
    31. this.$refs.container.style.transform = `translateX(${currentDelta}px)`;
    32. this.lastX = event.clientX;
    33. }
    34. clearTimeout(this.timer);
    35. this.timer = setTimeout(() => {
    36. const containerLeft = this.$refs.container.offsetLeft;
    37. const containerWidth = this.$refs.container.offsetWidth;
    38. const contentWidth = this.$refs.content.offsetWidth;
    39. const maxDelta = contentWidth - containerWidth - containerLeft;
    40. if (containerLeft < 0) {
    41. this.$refs.container.style.transform = `translateX(0)`;
    42. return;
    43. }
    44. if (maxDelta < 0) {
    45. this.$refs.container.style.transform = `translateX(${-maxDelta}px)`;
    46. return;
    47. }
    48. const items = this.$refs.content.children;
    49. let minDelta = Infinity;
    50. let index = 0;
    51. for (let i = 0; i < items.length; i++) {
    52. const itemLeft = items[i].offsetLeft;
    53. const delta = Math.abs(itemLeft - containerLeft);
    54. if (delta < minDelta) {
    55. minDelta = delta;
    56. index = i;
    57. }
    58. }
    59. const itemLeft = items[index].offsetLeft;
    60. const delta = itemLeft - containerLeft;
    61. this.$refs.container.style.transform = `translateX(${-delta}px)`;
    62. }, 100);
    63. },
    64. },
    65. };
    66. script>
    67. <style scoped>
    68. .container {
    69. position: relative;
    70. width: 100%;
    71. height: 80px;
    72. overflow: hidden;
    73. margin: 0 auto;
    74. padding: 0 20px;
    75. }
    76. .content {
    77. position: absolute;
    78. top: 0;
    79. left: 0;
    80. height: 100%;
    81. white-space: nowrap;
    82. }
    83. .item {
    84. display: inline-block;
    85. height: 100%;
    86. line-height: 80px;
    87. padding: 0 10px;
    88. font-size: 16px;
    89. color: #333;
    90. background-color: #ddd;
    91. border-radius: 5px;
    92. margin-right: 10px;
    93. }
    94. style>

  • 相关阅读:
    vue3 - vue3中使用ref来获取dom节点
    重读《纳瓦尔宝典》精彩语录及感悟篇(三)
    Spring Cloud alibaba Ribbon 负载调用说明(4)
    python --opencv图像处理(图像腐蚀与图像膨胀)
    【性能测试】Jmeter性能压测-阶梯式/波浪式场景总结(详细)
    Android平台轻量级RTSP服务模块编码前后数据源对接探究
    Maven 如何打包可运行jar包
    milvus
    sheng的学习笔记-AI-支持向量机(SVM)
    【Python编程】四、python字符串
  • 原文地址:https://blog.csdn.net/JackieDYH/article/details/131965134