自定義range?sliders滑塊實現(xiàn)元素拖動方法
1. 使用原生 range input
這篇文章介紹兩種創(chuàng)建 range slider 滑塊的方法。
老樣子,話不多說,先上菜。
const knob = document.getElementById('knob');
// 左邊的滑條
const leftSide = knob.previousElementSibling;
// 當前鼠標位置
let x = 0;
let y = 0;
let leftWidth = 0;
// 處理 mousedown 事件
const mouseDownHandler = function (e) {
// 獲取當前鼠標位置
x = e.clientX;
y = e.clientY;
leftWidth = leftSide.getBoundingClientRect().width;
// 在 `document` 上添加事件
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
};
knob.addEventListener('mousedown', mouseDownHandler);
const mouseMoveHandler = function (e) {
// 鼠標移動的距離
const dx = e.clientX - x;
const dy = e.clientY - y;
const containerWidth = knob.parentNode.getBoundingClientRect().width;
let newLeftWidth = ((leftWidth + dx) * 100) / containerWidth;
// 限制范圍在 0 - 100
newLeftWidth = Math.max(newLeftWidth, 0);
newLeftWidth = Math.min(newLeftWidth, 100);
leftSide.style.width = `${newLeftWidth}%`;
};
// 當松開鼠標時觸發(fā)
const mouseUpHandler = function () {
// ...
// 移除事件
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
};input 元素本身支持設(shè)置 type 屬性為 range,渲染一個 slider 滑塊。
<input type="range" />

它的兼容性也還不錯,支持所有現(xiàn)代瀏覽器以及 IE10 以上,但是它也有一些限制,比如:
- 你不能自定義把手(中間藍色圓圈)
- 并不是所有現(xiàn)代瀏覽器都支持垂直方向的 slider 滑塊
也就是說,它的自定義性不是很好,如果想要自定義 slider 滑塊的話,這種方式就無法滿足。
另外,兼容性方面我們可以通過下面這段代碼來進行檢測:
const isRangeInputSupported = function () {
const ele = document.createElement('input');
ele.setAttribute('type', 'range');
// 如果當前瀏覽器不支持 `range` input
// `type` 屬性會還原到 `text`
return ele.type !== 'text';
};
利用瀏覽器本身的默認行為機制,來判斷當前瀏覽器是否支持 range input。
2. 創(chuàng)建自定義 range slider
一個 slider 滑塊由 3 部分組成,1 個把手和把手左右兩個的 2 個滑條。
我們先構(gòu)造 HTML 結(jié)構(gòu),代碼如下:
<div class="container"> <div class="left"></div> <div class="knob" id="knob"></div> <div class="right"></div> </div>
這 3 部分元素放置在同一行展示,右邊部分的滑條表示的的是 range input 的可用寬度。所以,我們可以使用如下 CSS 代碼進行布局。
.container {
/* 內(nèi)容水平居中 */
display: flex;
align-items: center;
height: 1.5rem;
}
.right {
/* 可用寬度 */
flex: 1;
height: 2px;
}
HTML 和 CSS 結(jié)構(gòu)有了,我們接著來處理拖動行為。
監(jiān)聽 knob 把手的 mousedown 事件,記錄當前鼠標的位置。
const knob = document.getElementById('knob');
// 左邊的滑條
const leftSide = knob.previousElementSibling;
// 當前鼠標位置
let x = 0;
let y = 0;
let leftWidth = 0;
// 處理 mousedown 事件
const mouseDownHandler = function (e) {
// 獲取當前鼠標位置
x = e.clientX;
y = e.clientY;
leftWidth = leftSide.getBoundingClientRect().width;
// 在 `document` 上添加事件
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
};
knob.addEventListener('mousedown', mouseDownHandler);
上面的代碼要注意,mousedown 事件監(jiān)聽在 knob 元素上,而 mousemove 和 mouseup 事件則是監(jiān)聽在 document 元素上。
document 元素上的監(jiān)聽回調(diào)事件 mouseMoveHandler 和 mouseUpHandler 請看下文。
計算左側(cè)滑條寬度
當 knob 把手移動時,通過當前鼠標位置和記錄的鼠標位置,我們可以知道鼠標移動的距離,這段距離就是左側(cè)滑條的寬度。
const mouseMoveHandler = function (e) {
// 鼠標移動的距離
const dx = e.clientX - x;
const dy = e.clientY - y;
const containerWidth = knob.parentNode.getBoundingClientRect().width;
let newLeftWidth = ((leftWidth + dx) * 100) / containerWidth;
// 限制范圍在 0 - 100
newLeftWidth = Math.max(newLeftWidth, 0);
newLeftWidth = Math.min(newLeftWidth, 100);
leftSide.style.width = `${newLeftWidth}%`;
};
移除 document 元素上的監(jiān)聽事件
當滑動行為結(jié)束,也就是松開鼠標的時候,我們還需要移除掉 document 元素上的監(jiān)聽事件,防止重復監(jiān)聽導致的問題。
// 當松開鼠標時觸發(fā)
const mouseUpHandler = function () {
// ...
// 移除事件
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
};
<div style="display: flex; justify-content: center; padding: 4rem">
<div style="width: 16rem" class="container">
<div class="left"></div>
<div class="knob" id="knob"></div>
<div class="right"></div>
</div>
</div>以上就是自定義range sliders滑塊實現(xiàn)元素拖動方法的詳細內(nèi)容,更多關(guān)于range sliders滑塊元素拖動的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
javascript數(shù)據(jù)類型之原始類型詳解
這篇文章主要為大家介紹了javascript數(shù)據(jù)類型之原始類型詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06
Proxy Facade設(shè)計模式簡化系統(tǒng)訪問的強大工具原理詳解
這篇文章主要為大家介紹了 Proxy Facade設(shè)計模式簡化系統(tǒng)訪問的強大工具原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-10-10
JavaScript?設(shè)計模式之洋蔥模型原理及實踐應用
這篇文章主要介紹了JavaScript?設(shè)計模式之洋蔥模型原理及實踐應用,主要針對項目中遇到的問題,引申到koa-compose原理解析。通過學習洋蔥模式來解決我們實際項目中的問題2022-09-09

