拖拽滚动视图(一)
鼠标拖拽
事件
container.addEventListener("touchstart", dragStart, false);// 进入
container.addEventListener("touchend", dragEnd, false); // 离开
container.addEventListener("touchmove", drag, false); // 移动
container.addEventListener("mousedown", dragStart, false); // 进入
container.addEventListener("mouseup", dragEnd, false); // 离开
container.addEventListener("mousemove", drag, false);// 移动
Element.getBoundingClientRect()
返回元素的大小及其相对视口的位置,以css设置宽高作为衡量准备
offset(只读)
Element.offsetWidth
css宽度,包括border,padding,scrollbar(水平滚动条),width
Element.offsetHeight
css 高度,包括 border,padding,scrollbar(垂直滚动条),height
Element.offsetLeft
左边的偏移值
Element.offsetTop
距离顶部的偏移值
Element.offsetParent
- 如果父级有定位,返回带有定位的父级dom
- 如果父级没有定位,返回body
client(只读)
可视区域
MouseEvent.clientWidth
元素内部宽度(包括padding
,不包括scrollBar,border,margin
)
MouseEvent.clientHeight
元素内部高度(包括padding
,不包括scrollBar,border,margin
)
MouseEvent.clientX
鼠标距离可视区域左边的距离
MouseEvent.clientY
... 上边的距离
Element.clientTop
dom 上边框(border
)的宽度
Element.clientLeft
dom 左边框(border
)的宽度
scroll
距离: 可视区域+滚动隐藏的部分
Element.scrollTop
读取设置, 距离顶部的距离
Element.scrollLeft
读取设置, 距离元素left的距离
拖拽效果
代码映射结构
// 按下
box.onmousedown = function (event) {
console.log(1);
// 移动
box.onmousemove=function () {
console.log(2);
}
// 抬起
box.onmouseup=function () {
console.log(3);
}
}
逻辑
- 鼠标按下,获取鼠标点击时获取相对位置
- 鼠标移动,元素的位置=鼠标的位置-刚刚的差值
- 鼠标放下,给鼠标移动和鼠标放下设置为null
<style>
.box {
width: 100%;
height: 80vh;
/*display: flex;*/
/*justify-content: center;*/
/*align-items: center;*/
position: relative;
border: 2px solid red;
}
.aaa {
position: absolute;
width: 50px;
height: 50px;
background-color: rgb(245, 230, 99);
border: 10px solid rgba(136, 136, 136, .5);
border-radius: 50%;
}
.aaa:hover {
cursor: pointer;
border-width: 20px;
}
.aaa:active {
background-color: rgba(168, 218, 220, 1.00);
}
</style>
<div class="box" id="box">
<div id="ccc" class="aaa"></div>
</div>
<script>
/* mousedown 鼠标进入
* mousemove 鼠标移动
* mouseup 鼠标离开
* */
let ccc = document.querySelector("#ccc");
let box = document.querySelector("#box");
// 按下
ccc.onmousedown = function (event) {
let x = event.clientX - this.offsetLeft
let y = event.clientY - this.offsetTop
// 移动
document.onmousemove = function (e) {
ccc.style.left = e.pageX - x + 'px';
ccc.style.top = e.pageY - y + 'px';
}
// 抬起
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
}
}
</script>
拖拽范围限制
/* mousedown 鼠标进入
* mousemove 鼠标移动
* mouseup 鼠标离开
* */
let box = document.querySelector("#box");
let ccc = document.querySelector("#ccc");
ccc.onmousedown = function (event) {
// 子盒子
let w = ccc.getBoundingClientRect().width / 2;
let h = ccc.getBoundingClientRect().height / 2;
// 大盒子-小盒子
let width = box.getBoundingClientRect().width - w;
let height = box.getBoundingClientRect().height - h;
// 按下的位置距离左侧的差值
let x = event.clientX - this.offsetLeft
let y = event.clientY - this.offsetTop
// 移动
document.onmousemove = function (e) {
// 移动的坐标-左侧的坐标=子盒子的坐标
let x1 = e.pageX - x
let y1 = e.pageY - y;
if (-w < x1 && x1 < width) {
ccc.style.left = x1 + 'px';
}
if (-h < y1 && y1 < height) {
ccc.style.top = y1 + 'px';
}
}
// 抬起
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
}
}
我们发现出现滚动条的一些问题
发现了会出现,滚动条的bug, 那肯定是有些东西被隐藏点了
滚动条隐藏的解决方案
document.documentElement.scrollTop
window.pageYOffset
如果是对应的子盒子出现了滚动条,可以在对应的添加
关键代码修改
// 按下的位置距离左侧的差值
let x =(window.pageXOffset+ event.clientX) - this.offsetLeft
let y = (window.pageYOffset+event.clientY) - this.offsetTop
思考如何让视图跟着拖拽移动呢
首先理解一个比较基础的问题
滚动的长度 scrollTop
scrollHeight=scrollTop+clientHeight
同理
scrollWidth=scrollLeft+clientWidth
scrollLeft的距离其实就是等于:里面大盒子的长度- 视口的长度
scrollLeft就是相当于移动的距离
科普: 滚动的相对距离
scrollBy(x,y)
x和y指定滚动的相对量
案例
整体逻辑就一句话
移动的距离/总移动的距离=鼠标移动的距离/总长度
具体点就是
滚动条移动的距离/滚动条移动的总距离=鼠标移动的比较/总盒子可以移动的距离
上代码
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.box-over {
width: 60%;
height: 60vh;
overflow: auto;
}
.box {
width: 140%;
height: 150vh;
margin: 200px auto;
position: relative;
border: 2px solid red;
}
.aaa {
position: absolute;
width: 50px;
height: 50px;
background-color: rgb(245, 230, 99);
border: 10px solid rgba(136, 136, 136, .5);
border-radius: 50%;
}
.aaa:hover {
cursor: pointer;
border-width: 20px;
}
.aaa:active {
background-color: rgba(168, 218, 220, 1.00);
}
</style>
</head>
<body>
<div class="box-over">
<div class="box" id="box">
<div id="ccc" class="aaa"></div>
</div>
</div>
<script>
/* mousedown 鼠标进入
* mousemove 鼠标移动
* mouseup 鼠标离开
* */
let box = document.querySelector("#box");
let ccc = document.querySelector("#ccc");
let over = document.querySelector('.box-over');
ccc.onmousedown = function (event) {
//计算大盒子内部的宽高
let overW = box.getBoundingClientRect().width;
let overH = box.getBoundingClientRect().height;
//大盒子滚动条移动的距离
let overs = {
x: over.scrollWidth - over.clientWidth,
y: over.scrollHeight - over.clientHeight,
}
// 子盒子
let w = ccc.getBoundingClientRect().width / 2;
let h = ccc.getBoundingClientRect().height / 2;
// 大盒子-小盒子
let width = box.getBoundingClientRect().width - w;
let height = box.getBoundingClientRect().height - h;
// 按下的位置距离左侧的差值
let x = (window.pageXOffset + event.clientX) - this.offsetLeft
let y = (window.pageYOffset + event.clientY) - this.offsetTop
// 移动
document.onmousemove = function (e) {
// 移动的坐标-左侧的坐标=子盒子的坐标
let x1 = e.pageX - x
let y1 = e.pageY - y;
if (-w < x1 && x1 < width) {
ccc.style.left = x1 + 'px';
}
if (-h < y1 && y1 < height) {
ccc.style.top = y1 + 'px';
}
// 移动的距离/总距离=鼠标移动的距离/总长度
// 滚动条移动的距离/滚动条移动的总距离=鼠标移动的比较/总盒子可以移动的距离
over.scrollLeft = x1 / overW * overs.x
over.scrollTop = y1 / overH * overs.y
}
// 抬起
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
}
}
</script>
</body>
</html>
决定自己的高度的是你的态度,而不是你的才能
记得我们是终身初学者和学习者
总有一天我也能成为大佬