如何实现使用鼠标拖动页面模拟页面滚动功能
使用场景
你还记得你在什么样的场景会使用鼠标去拖动页面吗?
在我的印象中有这样几种场景,查看 PDF、使用 Figma 等设计编辑器的时候,我会使用鼠标去拖动页面。
今天这篇文章就来介绍如何实现一个简单的使用鼠标拖动页面的功能。
老样子,话不多说,先看效果。
通过上面的示例可以看到,通过鼠标点击移动,就可以拖动页面滚动。
实现方案
先定义 HTML 结构,我们需要一个滚动的容器。
<div class="container">...</div>
接着定义 CSS 样式,我们需要把鼠标变成一只手的样子,并且让容器可以滚动。
.container {
cursor: grab;
overflow: auto;
}
cursor: grab
表示元素可以点击和拖动。
OK,结构就已经搭建好了,接下来看看逻辑部分。
滚动到指定位置
只要元素是可以滚动的,我们就可以通过设置 scrollTop 或 scrollLeft 属性将其滚动到指定位置。
const ele = document.getElementById('container');
ele.scrollTop = 100;
ele.scrollLeft = 150;
上面的代码表示将 ele 元素在垂直方向滚动 100 像素的距离,在水平方向滚动 150 像素的距离。
拖动鼠标滚动
拖动一个元素的方式之前的几篇文章都有写过,还不清楚的同学建议去看看。
同样,我们先从 mousedown 事件开始。
// 记录鼠标位置
let pos = { top: 0, left: 0, x: 0, y: 0 };
const mouseDownHandler = function (e) {
pos = {
// 当前滚动位置
left: ele.scrollLeft,
top: ele.scrollTop,
// 当前鼠标位置
x: e.clientX,
y: e.clientY,
};
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
};
记录鼠标的位置,方便之后鼠标移动的时候计算移动距离。
在 mousedown 事件的回调方法内,绑定 mousemove 和 mouseup 事件,注意绑定事件的对象是 document 元素。
当你鼠标的时候,实时计算移动的距离,然后将 .container
容器元素滚动相同的距离,到达指定位置。
const mouseMoveHandler = function (e) {
// 鼠标移动距离
const dx = e.clientX - pos.x;
const dy = e.clientY - pos.y;
// 滚动到指定位置
ele.scrollTop = pos.top - dy;
ele.scrollLeft = pos.left - dx;
};
在 mouseup 事件的回调方法内,我们需要移除之前绑定 mousemove 和 mouseup 事件,防止后续再拖动的时候重复注册和计算。注意,这两个事件是绑定在 document 元素上的。
const mouseUpHandler = function () {
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
};
OK,基本的功能实现就已经完成了。
你可以自己再尝试实现一遍,实现的过程中不要再回来看这篇文章,完全凭借自己的记忆和理解,这样才能真正的消化和吸收。
最后,我们还可以对这个功能进行一些优化。
在 mousedown 事件的回调方法内,给 .container
元素添加一些交互样式和优化。
const mouseDownHandler = function (e) {
// 改变鼠标样式
ele.style.cursor = 'grabbing';
// 阻止用户选择页面内容
ele.style.userSelect = 'none';
// ...
};
同样,也需要在 mouseup 事件的回调方法内,移除掉上面代码里加上的交互样式和优化。
const mouseUpHandler = function () {
// ...
ele.style.cursor = 'grab';
ele.style.removeProperty('user-select');
};
全文完,如果觉得这篇文章对你有用,欢迎 点赞 👍、评论 ✍️、收藏 👀
转载自:https://juejin.cn/post/7132463293544792095