Vue 实现一个简单的鼠标拖拽滚动效果插件


Posted in Vue.js onDecember 10, 2020

最近开源了一个 Vue 组件,还不够完善,欢迎大家来一起完善它,也希望大家能给个 star 支持一下,谢谢各位了。

github 地址:github.com/qq449245884…

最近在做一个新的项目,有个需要是这样的:

Vue 实现一个简单的鼠标拖拽滚动效果插件

简单描述一下,就是鼠标拖动页面,整个页面会随着的鼠标的拖拽而移动,如果页面有内容,里面的内容也需要跟着拖动的外层整体移到。

一开始没啥思路,所以就发了个朋友圈,得到的答案挺多的,主要还是用拖拽之类的,但这个拖拽只是单个元素的拖动,我想要的整个视图的拖动。

这里线索又断了。

于是又回到飞书有类似功能的页面,然后仔细检查一下它页面的 DOM 结构,如下所示:

Vue 实现一个简单的鼠标拖拽滚动效果插件

发现有这一层,它把页面设置的很宽,很高,为了隐藏滚动条,所以设置overflow: hidden;,看了这一设置,突然灵光一现,难道它是用拖拽来触发滚动条的滚动,在细想,哇靠,这思路可行的,NB。

准备上手试试

创建一个 vue 项目,这个就不细说的,我已经把原码发布到 github 上了,有兴趣自己看看:

https://github.com/qq449245884/vue-drag-scroll

首先给外层加个大大的宽和高:

<div class="vue-drag-scroll-wrapper" :style="zoomStye">
 // 这里省略一些不太重要的代码
</div>

<script>
export default {
 name: 'VueDragScroll',
 props: {
  msg: String
 },
 data () {
  return {
   scale: 100
  }
 },
 computed: {
  zoomStye () {
   const INIT_WIDTH = 2208
   const INIT_HEIGHT = 1206
   const width = INIT_WIDTH * (1 + (100 - this.scale)/100)
   const height = INIT_HEIGHT * (1 + (100 - this.scale)/100)
   console.log(width)
   console.log(height)
   return {
    width: `${width}px`,
    height: `${height}px`,
    transform: `scale(${this.scale/100})`
   }
  }
 }
}
</script>

这里设置了一个计算属性 zoomStye,主要使用就是给外层加一个在的宽,和高,这里我还设置了一个缩放比较,为了是能放大缩小页面,下面讲。运行效果:

Vue 实现一个简单的鼠标拖拽滚动效果插件

接着,我们需要监听鼠标的拖拽来触发滚动条效果,因为需要对 dom 的操作,所以这里把拖拽处理逻辑用 vue 指令封装起来,这样后面有需要,只要使用该指令即可。

注意:在 vue 中如果需要对 dom 进行多次操作,最好是把它封装在指令中。

指令代码如下:

import Vue from 'vue'

Vue.directive('dragscroll', function (el) {
 el.onmousedown = function (ev) {
  console.log(el)
  const disX = ev.clientX
  const disY = ev.clientY
  const originalScrollLeft = el.scrollLeft
  const originalScrollTop = el.scrollTop
  const originalScrollBehavior = el.style['scroll-behavior']
  const originalPointerEvents = el.style['pointer-events']
  // auto: 默认值,表示滚动框立即滚动到指定位置。
  el.style['scroll-behavior'] = 'auto'
  el.style['cursor'] = 'grabbing'
  // 鼠标移动事件是监听的整个document,这样可以使鼠标能够在元素外部移动的时候也能实现拖动
  document.onmousemove = function (ev) {
   ev.preventDefault()
   // 计算拖拽的偏移距离
   const distanceX = ev.clientX - disX
   const distanceY = ev.clientY - disY

   el.scrollTo(originalScrollLeft - distanceX, originalScrollTop - distanceY)
   console.log(originalScrollLeft - distanceX, originalScrollTop - distanceY)
   // 在鼠标拖动的时候将点击事件屏蔽掉
   el.style['pointer-events'] = 'none'
   document.body.style['cursor'] = 'grabbing'
  }
  document.onmouseup = function () {
   document.onmousemove = null
   document.onmouseup = null
   el.style['scroll-behavior'] = originalScrollBehavior
   el.style['pointer-events'] = originalPointerEvents
   el.style['cursor'] = 'grab'
  }
 }
})

这里的主要思路就是利用 el.scrollTo 来触发滚动条的移到。

有了 dragscroll 指令,我们来使用一下,首先我们需要在增加一层外层:

<div v-dragscroll class="vue-drag-scroll-out-wrapper">
 <div class="vue-drag-scroll-wrapper" :style="zoomStye">
  // 这里省略一些不太重要的代码
 </div>
</div>

<style scoped>
.vue-drag-scroll-out-wrapper{
  overflow-x: hidden;
  width: 100%;
  height: 100%;
  cursor: grab;
  position: absolute;
  top:0;
  left: 0;
  &::-webkit-scrollbar { width: 0 !important } // 隐藏垂直方向的滚动条
}
</style>

这里需要注意的在 .vue-drag-scroll-out-wrapper 要设置 overflow 值,否则无法滚动(测试出来的)。

这样拖拽效果就出来啦:

Vue 实现一个简单的鼠标拖拽滚动效果插件

增加缩放

这里,我们增加一个视图的放大和缩小,所以增加两个按钮:

<div class="tolbox-zoom-wrapper">
 <div class="zoom-inner">
 <span class="iconfont iconsuoxiao"
  :class="{'disabled': scale === 25}" style="font-size:22px"
  @click="handleReduce"
 />
 <span class="iconfont iconfangda"
  :class="{'disabled': scale === 100}"
  @click="handleEnlarge" 
 />
 <div class="scale-text">{{scale}}%</div>
 </div>
</div>

效果:

Vue 实现一个简单的鼠标拖拽滚动效果插件

这里的放大和缩小的逻辑就是通过我们增加减少 scale 来实现

handleReduce () {
 if (this.scale === 25) return
 this.scale -= 25
},
handleEnlarge () {
 if (this.scale === 100) return
 this.scale += 25
}

缩放比例的关系就是开关给出的代码:

const INIT_WIDTH = 2208
const INIT_HEIGHT = 1206
const width = INIT_WIDTH * (1 + (100 - this.scale)/100)
const height = INIT_HEIGHT * (1 + (100 - this.scale)/100)

这个比例是我自己定的,比如现在减少到 75% ,那么最外层的高和宽就要对应的增加原来的 25%,因为缩放就是视野上的缩小,对应的距离就是拉宽。

最后就是使用 CSS 的 transform 来做缩放:

transform: `scale(${this.scale/100})`

最终的效果:

Vue 实现一个简单的鼠标拖拽滚动效果插件

当前这个只是简单的一个排版,大家根据自己需要布局,这里主要还是分享一些思路,如果大家有好的思路,欢迎留言分享。

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。

以上就是Vue 实现一个简单的鼠标拖拽滚动效果插件的详细内容,更多关于vue 鼠标拖拽滚动插件的资料请关注三水点靠木其它相关文章!

Vue.js 相关文章推荐
vue实现下载文件流完整前后端代码
Nov 17 Vue.js
Vue组件生命周期运行原理解析
Nov 25 Vue.js
Vue Elenent实现表格相同数据列合并
Nov 30 Vue.js
vue使用require.context实现动态注册路由
Dec 25 Vue.js
浅析vue中的nextTick
Dec 28 Vue.js
Vue中inheritAttrs的使用实例详解
Dec 31 Vue.js
vue调用微信JSDK 扫一扫,相册等需要注意的事项
Jan 03 Vue.js
vue-element-admin项目导入和导出的实现
May 21 Vue.js
vue基于Teleport实现Modal组件
May 31 Vue.js
Element-ui Layout布局(Row和Col组件)的实现
Dec 06 Vue.js
vue @click.native 绑定原生点击事件
Apr 22 Vue.js
vue使用element-ui按需引入
May 20 Vue.js
vuex页面刷新导致数据丢失的解决方案
Dec 10 #Vue.js
详解vue-cli项目在IE浏览器打开报错解决方法
Dec 10 #Vue.js
Vue+element-ui添加自定义右键菜单的方法示例
Dec 08 #Vue.js
vue添加自定义右键菜单的完整实例
Dec 08 #Vue.js
vue中如何自定义右键菜单详解
Dec 08 #Vue.js
基于vue与element实现创建试卷相关功能(实例代码)
Dec 07 #Vue.js
vue祖孙组件之间的数据传递案例
Dec 07 #Vue.js
You might like
DSP接收机前端设想
2021/03/02 无线电
PHP setTime 设置当前时间的代码
2012/08/27 PHP
PHP无法访问远程mysql的问题分析及解决
2013/05/16 PHP
PHP模拟QQ登录的方法
2015/07/29 PHP
php获取开始与结束日期之间所有日期的方法
2016/11/29 PHP
php设计模式之原型模式分析【星际争霸游戏案例】
2020/03/23 PHP
(转载)JavaScript中匿名函数,函数直接量和闭包
2007/05/08 Javascript
event.X和event.clientX的区别分析
2011/10/06 Javascript
用jquery模仿的a的title属性(兼容ie6/7)
2013/01/21 Javascript
js获取class的所有元素
2013/03/28 Javascript
js实现遮罩层弹出框的方法
2015/01/15 Javascript
JS实现点击文字对应DIV层不停闪动效果的方法
2015/03/02 Javascript
深入理解JavaScript系列(33):设计模式之策略模式详解
2015/03/03 Javascript
基于JS代码实现图片在页面中旋转效果
2016/06/16 Javascript
JavaScript实战之菜单特效
2016/08/16 Javascript
利用Vue实现移动端图片轮播组件的方法实例
2017/08/23 Javascript
vue+elementUi图片上传组件使用详解
2019/08/20 Javascript
小程序实现横向滑动日历效果
2019/10/21 Javascript
vue 使用v-for进行循环的实例代码详解
2020/02/19 Javascript
[01:09:50]VP vs Pain 2018国际邀请赛小组赛BO2 第二场
2018/08/20 DOTA
在Python的框架中为MySQL实现restful接口的教程
2015/04/08 Python
Python解析最简单的验证码
2016/01/07 Python
python验证码识别的实例详解
2016/09/09 Python
Python设计模式之解释器模式原理与用法实例分析
2019/01/10 Python
详解Python函数式编程—高阶函数
2019/03/29 Python
Python shutil模块用法实例分析
2019/10/02 Python
Python3.5 win10环境下导入kera/tensorflow报错的解决方法
2019/12/19 Python
keras 回调函数Callbacks 断点ModelCheckpoint教程
2020/06/18 Python
能源工程专业应届生求职信
2014/03/01 职场文书
社区四风存在问题及整改措施
2014/10/26 职场文书
2015年路政工作总结
2015/05/22 职场文书
2015年幼儿园德育工作总结
2015/05/25 职场文书
家庭聚会祝酒词
2015/08/11 职场文书
导游词之安徽巢湖
2019/12/26 职场文书
关于mysql中string和number的转换问题
2022/06/14 MySQL
Python中的socket网络模块介绍
2022/07/23 Python