前言
項目需求為頁面上實現(xiàn)拖拽節(jié)點和可以在頁面中通過滑動滾輪來縮放節(jié)點顯示(以鼠標(biāo)位置為縮放中心點)從而放大到可以看到詳細(xì)的信息,節(jié)點有10000個。特此記錄下實現(xiàn)細(xì)節(jié)
效果圖
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, // 按下標(biāo)識
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)';
為節(jié)點綁定拖拽事件,拖拽事件的邊界使用
Math
進(jìn)行判斷,比起if
判斷更加清晰快捷。
鼠標(biāo)抬起采用document全局判斷,避免鼠標(biāo)移動到節(jié)點外未觸發(fā)鼠標(biāo)抬起事件
// 綁定鼠標(biāo)點擊
ul.addEventListener('mousedown', function (e) {
e.preventDefault();
e.stopPropagation();
isDown = true;
lastPointermove = { x: e.clientX, y: e.clientY };
});
// 綁定鼠標(biāo)移動
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})`;
}
});
// 綁定鼠標(biāo)抬起
document.addEventListener('mouseup', () => {
isDown = false;
})
滾輪縮放、放大邏輯
X軸的(window.innerWidth - ulWidth) * 0.5)主要判斷節(jié)點距離左邊邊距,y軸同樣
同樣采用Math
判斷邊界
ul.addEventListener('wheel', function (e) {
let ratio = 1.1;
// 縮小
if (e.deltaY > 0) {
ratio = 1 / 1.1;
}
// 限制縮放倍數(shù)
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})`;
});
總結(jié)
自此功能開發(fā)完畢,使用原生方法實現(xiàn)也是加深對js的理解,基本上js上面能實現(xiàn)的移植到React、Vue也是一樣的道理。小弟才疏學(xué)淺,大佬們見笑了,有幫到你的小伙伴可以點個贊,謝謝。文章來源:http://www.zghlxwxcb.cn/news/detail-511637.html
全部代碼文章來源地址http://www.zghlxwxcb.cn/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, // 按下標(biāo)識
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)';
// 拖拽查看
// 綁定鼠標(biāo)點擊
ul.addEventListener('mousedown', function (e) {
e.preventDefault();
e.stopPropagation();
isDown = true;
lastPointermove = { x: e.clientX, y: e.clientY };
});
// 綁定鼠標(biāo)移動
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})`;
}
});
// 綁定鼠標(biāo)抬起
document.addEventListener('mouseup', () => {
isDown = false;
})
// 滾輪縮放、放大邏輯
ul.addEventListener('wheel', function (e) {
// e.preventDefault();
let ratio = 1.1;
// 縮小
if (e.deltaY > 0) {
ratio = 1 / 1.1;
}
// 限制縮放倍數(shù)
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>
到了這里,關(guān)于js 以鼠標(biāo)滾輪位置為中心縮放、放大以及邊界判斷的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!