前言
项目需求为页面上实现拖拽节点和可以在页面中通过滑动滚轮来缩放节点显示(以鼠标位置为缩放中心点)从而放大到可以看到详细的信息,节点有10000个。特此记录下实现细节
效果图
js
初始化变量
const container = document.querySelector('.container');
const ul = document.querySelector('.ul');
// 变量
let result,
x = 0,
y = 0,
scale = 1,
ulWidth = 1500,
ulHeight = 1200,
minScale = 1,
maxScale = 4,
isDown = false, // 按下标识
diff = { x: 0, y: 0 }, // 相对于上一次lastPointermove移动差值
lastPointermove = { x: 0, y: 0 }; // 用于计算diff
ul.style.width = ulWidth + 'px';
ul.style.height = ulHeight + 'px';
ul.style.transform = 'matrix(1, 0, 0, 1, 0, 0)';
为节点绑定拖拽事件,拖拽事件的边界使用
Math
进行判断,比起if
判断更加清晰快捷。
鼠标抬起采用document全局判断,避免鼠标移动到节点外未触发鼠标抬起事件
// 绑定鼠标点击
ul.addEventListener('mousedown', function (e) {
e.preventDefault();
e.stopPropagation();
isDown = true;
lastPointermove = { x: e.clientX, y: e.clientY };
});
// 绑定鼠标移动
ul.addEventListener('mousemove', function (e) {
e.preventDefault();
e.stopPropagation();
if (isDown) {
const current1 = { x: e.clientX, y: e.clientY };
diff.x = current1.x - lastPointermove.x;
diff.y = current1.y - lastPointermove.y;
lastPointermove = { x: current1.x, y: current1.y };
x += diff.x;
y += diff.y;
//边界判断
let offsetX = Math.min(Math.max(x, ulWidth - ulWidth * (scale + 1) / 2), + ulWidth * (scale - 1) / 2);
let offsetY = Math.min(Math.max(y, ulHeight - ulHeight * (scale + 1) / 2), + ulHeight * (scale - 1) / 2);
ul.style.transform = `matrix(${scale}, 0, 0, ${scale}, ${offsetX}, ${offsetY})`;
}
});
// 绑定鼠标抬起
document.addEventListener('mouseup', () => {
isDown = false;
})
滚轮缩放、放大逻辑
X轴的(window.innerWidth - ulWidth) * 0.5)主要判断节点距离左边边距,y轴同样
同样采用Math
判断边界
ul.addEventListener('wheel', function (e) {
let ratio = 1.1;
// 缩小
if (e.deltaY > 0) {
ratio = 1 / 1.1;
}
// 限制缩放倍数
const onscale = scale * ratio;
if (onscale > maxScale) {
ratio = maxScale / scale;
scale = maxScale;
} else if (onscale < minScale) {
ratio = minScale / scale;
scale = minScale;
} else {
scale = onscale;
}
const origin = {
x: (ratio - 1) * ulWidth * 0.5,
y: (ratio - 1) * ulHeight * 0.5
};
// 计算偏移量
x -= (ratio - 1) * (e.clientX - x - (window.innerWidth - ulWidth) * 0.5) - origin.x;
y -= (ratio - 1) * (e.clientY - y) - origin.y;
let offsetX = Math.min(Math.max(x, ulWidth - ulWidth * (scale + 1) / 2), ulWidth * (scale - 1) / 2);
let offsetY = Math.min(Math.max(y, ulHeight - ulHeight * (scale + 1) / 2), + ulHeight * (scale - 1) / 2);
x = offsetX;
y = offsetY;
ul.style.transform = `matrix(${scale}, 0, 0, ${scale}, ${offsetX}, ${offsetY})`;
});
总结
自此功能开发完毕,使用原生方法实现也是加深对js的理解,基本上js上面能实现的移植到React、Vue也是一样的道理。小弟才疏学浅,大佬们见笑了,有帮到你的小伙伴可以点个赞,谢谢。文章来源:https://www.toymoban.com/news/detail-511637.html
全部代码文章来源地址https://www.toymoban.com/news/detail-511637.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
body {
margin: 0;
padding: 0;
}
.main {
width: 100%;
display: flex;
justify-content: center;
}
ul {
width: 1500px;
height: 1200px;
background-color: antiquewhite;
list-style: none;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: 0;
padding: 0;
}
li {
width: 100px;
height: 80px;
background-color: orange;
margin-right: 20px;
}
li:nth-child(12n) {
margin-right: 0px;
}
li:hover {
background-color: darkblue;
}
.container {
position: relative;
width: 1500px;
height: 1200px;
overflow: hidden;
}
</style>
<body>
<div class="main">
<div class="container">
<ul class="ul">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
</body>
<script>
const container = document.querySelector('.container');
const ul = document.querySelector('.ul');
// 变量
let result,
x = 0,
y = 0,
scale = 1,
ulWidth = 1500,
ulHeight = 1200,
minScale = 1,
maxScale = 4,
isDown = false, // 按下标识
diff = { x: 0, y: 0 }, // 相对于上一次lastPointermove移动差值
lastPointermove = { x: 0, y: 0 }; // 用于计算diff
ul.style.width = ulWidth + 'px';
ul.style.height = ulHeight + 'px';
ul.style.transform = 'matrix(1, 0, 0, 1, 0, 0)';
// 拖拽查看
// 绑定鼠标点击
ul.addEventListener('mousedown', function (e) {
e.preventDefault();
e.stopPropagation();
isDown = true;
lastPointermove = { x: e.clientX, y: e.clientY };
});
// 绑定鼠标移动
ul.addEventListener('mousemove', function (e) {
e.preventDefault();
e.stopPropagation();
if (isDown) {
const current1 = { x: e.clientX, y: e.clientY };
diff.x = current1.x - lastPointermove.x;
diff.y = current1.y - lastPointermove.y;
lastPointermove = { x: current1.x, y: current1.y };
x += diff.x;
y += diff.y;
//边界判断
let offsetX = Math.min(Math.max(x, ulWidth - ulWidth * (scale + 1) / 2), + ulWidth * (scale - 1) / 2);
let offsetY = Math.min(Math.max(y, ulHeight - ulHeight * (scale + 1) / 2), + ulHeight * (scale - 1) / 2);
ul.style.transform = `matrix(${scale}, 0, 0, ${scale}, ${offsetX}, ${offsetY})`;
}
});
// 绑定鼠标抬起
document.addEventListener('mouseup', () => {
isDown = false;
})
// 滚轮缩放、放大逻辑
ul.addEventListener('wheel', function (e) {
// e.preventDefault();
let ratio = 1.1;
// 缩小
if (e.deltaY > 0) {
ratio = 1 / 1.1;
}
// 限制缩放倍数
const onscale = scale * ratio;
if (onscale > maxScale) {
ratio = maxScale / scale;
scale = maxScale;
} else if (onscale < minScale) {
ratio = minScale / scale;
scale = minScale;
} else {
scale = onscale;
}
const origin = {
x: (ratio - 1) * ulWidth * 0.5,
y: (ratio - 1) * ulHeight * 0.5
};
// 计算偏移量
x -= (ratio - 1) * (e.clientX - x - (window.innerWidth - ulWidth) * 0.5) - origin.x;
y -= (ratio - 1) * (e.clientY - y) - origin.y;
let offsetX = Math.min(Math.max(x, ulWidth - ulWidth * (scale + 1) / 2), ulWidth * (scale - 1) / 2);
let offsetY = Math.min(Math.max(y, ulHeight - ulHeight * (scale + 1) / 2), + ulHeight * (scale - 1) / 2);
x = offsetX;
y = offsetY;
ul.style.transform = `matrix(${scale}, 0, 0, ${scale}, ${offsetX}, ${offsetY})`;
});
</script>
</html>
到了这里,关于js 以鼠标滚轮位置为中心缩放、放大以及边界判断的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!