我找到了this并尝试对其进行修复,因为其背后的逻辑与我要实现的逻辑相似。我已经设法通过最少的编辑工作了。但它没有按预期工作。
注意:我已将点击功能注释掉,因为它可以正常工作。
怎么了
如果单击volumeBtn
并在向左或向右滑动时不小心将光标移出了volumeRange
div高度或宽度,则当您停止单击鼠标时,不会执行mouseup
事件侦听器。
像1一样,单击volumeBtn
后,一旦volumeBtn
超出`volumeRange'div之外,就不能向左或向右拖动。
从第零位置到所需位置存在闪烁。
我想发生什么
如果单击volumeBtn
然后停止单击鼠标,则即使光标不再位于mouseup
上,也应执行volumeRange
事件。
如果单击volumeBtn
,则即使光标不再位于volumeBtn
上,您也应该能够向左或向右拖动volumeRange
。
const volume = document.querySelector('.volume');
const volumeRange = document.querySelector('.volume-range');
const volumeBtn = document.querySelector('.volume-button');
// volumeRange.addEventListener("click", volumeClick );
// function volumeClick(event) {
// let x = event.offsetX;
// volume.style.width = (Math.floor(x) + 10) + 'px';
// }
let mouseIsDown = false;
volumeBtn.addEventListener("mouseup", up);
volumeBtn.addEventListener("mousedown", down);
volumeRange.addEventListener("mousemove", volumeSlide);
function down(){ mouseIsDown = true; }
function up(){ mouseIsDown = false; }
function volumeSlide(event) {
if (mouseIsDown) {
let x = event.offsetX;
console.log(x);
volume.style.width = Math.floor(x + 10) + 'px';
}
}
body {
background-color: #2a2a2a;
}
.volume-range {
margin-top: 80px;
height: 5px;
width: 250px;
background: #555;
border-radius: 15px;
}
.volume-range>.volume {
height: 5px;
width: 50px;
background: #2ecc71;
border: none;
border-radius: 10px;
outline: none;
position: relative;
}
.volume-range>.volume>.volume-button {
width: 20px;
height: 20px;
border-radius: 20px;
background: #FFF;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
outline: none;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Volume</title <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
</head>
<style>
</style>
<body>
<div class="volume-range">
<div class="volume">
<div class="volume-button"></div>
</div>
</div>
</body>
</html>
最佳答案
为什么它不起作用
这是按照您描述的方式进行的,因为仅当鼠标位于连接了侦听器的元素内部时,才会触发鼠标事件。
对此的一种直接(但不是很好)的解决方案是将“ mouseup”和“ mousemove”的侦听器从volumeBtn / volumeRange移到window对象。这不是很好,因为如果以后需要删除此元素,则还应该从window对象中删除侦听器。
更好的解决方案
最好将滑块封装在另一个元素内,这将给它提供一些填充,然后将事件侦听器放在该“容器”元素上。当您移出元素之外时,它仍然会停止移动,但是至少所有内容都是独立的。
以下代码段显示了该代码:
const volume = document.querySelector('.volume');
const volumeRange = document.querySelector('.volume-range');
const volumeContainer = document.querySelector('.volume-container');
const volumeBtn = document.querySelector('.volume-button');
// volumeRange.addEventListener("click", volumeClick );
// function volumeClick(event) {
// let x = event.offsetX;
// volume.style.width = (Math.floor(x) + 10) + 'px';
// }
let mouseIsDown = false;
volumeContainer.addEventListener("mouseup", up);
volumeBtn.addEventListener("mousedown", down);
volumeContainer.addEventListener("mousemove", volumeSlide, true);
function down(){ mouseIsDown = true; }
function up(){ mouseIsDown = false; }
const volumeRangeWidth = volumeRange.getBoundingClientRect().width; // This will be the volume limit (100%)
function volumeSlide(event) {
if (mouseIsDown) {
let x = event.offsetX;
if (event.target.className == "volume-container") {
x = Math.floor(x);
if (x < 0) x = 0; // check if it's too low
if (x > volumeRangeWidth) x = volumeRangeWidth; // check if it's too high
volume.style.width = (x+10) + 'px';
}
}
}
body {
background-color: #2a2a2a;
}
.volume-container {
padding: 40px 0px;
margin: 0px 20px;
}
.volume-range {
height: 5px;
width: 250px;
background: #555;
border-radius: 15px;
}
.volume-range>.volume {
height: 5px;
width: 50px;
background: #2ecc71;
border: none;
border-radius: 10px;
outline: none;
position: relative;
}
.volume-range>.volume>.volume-button {
width: 20px;
height: 20px;
border-radius: 20px;
background: #FFF;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
outline: none;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Volume</title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
</head>
<style>
</style>
<body>
<div class="volume-container">
<div class="volume-range">
<div class="volume">
<div class="volume-button"></div>
</div>
</div>
</div>
</body>
</html>
其他问题
在小提琴中,还显示了如何避免体积超出容器。