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 24 Vue.js
vue实现登录、注册、退出、跳转等功能
Dec 23 Vue.js
vue实现图书管理系统
Dec 29 Vue.js
vue实现防抖的实例代码
Jan 11 Vue.js
Vue使用Ref跨层级获取组件的步骤
Jan 25 Vue.js
Vite和Vue CLI的优劣
Jan 30 Vue.js
vue使用v-model进行跨组件绑定的基本实现方法
Apr 28 Vue.js
如何理解Vue前后端数据交互与显示
May 10 Vue.js
vue组件的路由高亮问题解决方法
May 11 Vue.js
如何理解Vue简单状态管理之store模式
May 15 Vue.js
一文带你理解vue创建一个后台管理系统流程(Vue+Element)
May 18 Vue.js
如何用vue实现网页截图你知道吗
Nov 17 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
广播爱好者需要了解的天线知识
2021/03/01 无线电
收集的PHP中与数组相关的函数
2007/03/22 PHP
php 模拟get_headers函数的代码示例
2013/04/27 PHP
非常全面的php日期时间运算汇总
2015/11/04 PHP
thinkPHP5.0框架模块设计详解
2017/03/18 PHP
PC端微信扫码支付成功之后自动跳转php版代码
2017/07/07 PHP
删除重复数据的算法
2006/11/23 Javascript
JS与框架页的操作代码
2010/01/17 Javascript
JavaScript 编写匿名函数的几种方法
2010/02/21 Javascript
JS实现关闭当前页而不弹出提示框的方法
2016/06/22 Javascript
AngularJS 中文API参考手册
2016/07/28 Javascript
BootStrap Table对前台页面表格的支持实例讲解
2016/12/22 Javascript
nodejs利用http模块实现银行卡所属银行查询和骚扰电话验证示例
2016/12/30 NodeJs
vue.js从安装到搭建过程详解
2017/03/17 Javascript
Vue实现按钮级权限方案
2019/11/21 Javascript
Vue中多元素过渡特效的解决方案
2020/02/05 Javascript
Vue scoped及deep使用方法解析
2020/08/01 Javascript
解决vue net :ERR_CONNECTION_REFUSED报错问题
2020/08/13 Javascript
快速入手Python字符编码
2016/08/03 Python
Python简单网络编程示例【客户端与服务端】
2017/05/26 Python
python3+PyQt5实现支持多线程的页面索引器应用程序
2018/04/20 Python
python中yaml配置文件模块的使用详解
2018/04/27 Python
基于python的BP神经网络及异或实现过程解析
2019/09/30 Python
基于Python实现船舶的MMSI的获取(推荐)
2019/10/21 Python
在python中求分布函数相关的包实例
2020/04/15 Python
6种非常炫酷的CSS3按钮边框动画特效
2016/03/16 HTML / CSS
英国皇家造币厂:The Royal Mint
2018/10/05 全球购物
视光学专业毕业生推荐信
2013/10/28 职场文书
房地产广告策划方案
2014/05/15 职场文书
经典导游欢迎词
2015/01/26 职场文书
客服专员岗位职责
2015/02/10 职场文书
go mod 安装依赖 unkown revision问题的解决方案
2021/05/06 Golang
让文件路径提取变得更简单的Python Path库
2021/05/27 Python
关于antd tree 和父子组件之间的传值问题(react 总结)
2021/06/02 Javascript
超越Nginx的Web服务器caddy优雅用法
2022/06/21 Servers
ORACLE中dbms_output.put_line输出问题的解决过程
2022/06/28 Oracle