前端组件—纵向范围控件(一)

HTML中有 <input type="range"> 这样的一个控件,但是却只能横向,自己就想着做了一个纵向的。废话不多说,上干货

HTML部分:

<div class="gm-vertical-range" data-gm-value="100" data-gm-max="100" data-gm-min="0">
    <div class="gm-vertical-range-slider"></div>
    <div class="gm-vertical-range-track"></div>
</div>

CSS部分:

* {
    margin: 0;
    padding: 0;
}

.gm-vertical-range {
    width: 2px;
    height: 100px;
    border: 1px solid rgb(121, 175, 255);
    position: relative;
    top: 20px;
    left: 20px;
    background-color: rgb(15, 147, 255);
    border-radius: 1px;
    -moz-user-select:none;
    -webkit-user-select:none;
    -ms-user-select:none;
    -khtml-user-select:none;
    user-select:none;
} .gm-vertical-range:focus {
    outline: none;
}

.gm-vertical-range-slider {
    position: relative;
    /* 不要让他在边框上 */
    top: -3px; 
    left: -3px;
    z-index: 999;
    width: 6px;
    height: 6px;
    border-radius: 100%;;
    border: 1px solid rgb(121, 175, 255);
    box-shadow: 0 0 10px 2px rgb(121, 175, 255);
    background-color: #fff;
    cursor: pointer;
}

.gm-vertical-range-track {
    width: 100%;
    height: 100%;
    background-color: rgb(15, 147, 255);
    cursor: pointer;
    position: relative;
    top: -8px;
    left: 0;
}

JS部分(我这里是引用了 jquery 的):

// 获取 DOM 元素
var range = $(".gm-vertical-range");
var slider = $(".gm-vertical-range-slider");
var track = $(".gm-vertical-range-track");

// 定义标识符
var isTopBorder = 0;
var isBottomBorder = 0;
var clickPosition = 0;

// 让组件可以获取焦点
range.attr("tabIndex", 1);

// 点击轨道获取焦点并改变值
track.click(function(e) {
    range.focus();
    slider.css({
        top: (-3+e.offsetY) + "px"
    });
    range.attr("data-gm-value", (100-e.offsetY));
});

// 点击滑块获取焦点
slider.click(function() {
    range.focus();
});

// 获取焦点后用上下左右按键改变值
range.keydown(function(e) {
    var rangeValue = Number(range.attr("data-gm-value"));
    var rangeMax = Number(range.attr("data-gm-max"));
    var rangeMin = Number(range.attr("data-gm-min"));

    if(e.keyCode === 38 || e.keyCode === 39) {
        if(rangeValue < rangeMax) {
            slider.css({
                top: Number(slider.css("top").split("p")[0]) - 1 + "px"
            });
            range.attr("data-gm-value", String(rangeValue + 1));
        }
    }
    
    if(e.keyCode === 37 || e.keyCode === 40) {
        if(rangeValue > rangeMin) {
            slider.css({
                top: Number(slider.css("top").split("p")[0]) + 1 + "px"
            });
            range.attr("data-gm-value", String(rangeValue - 1));
        }
    }
});

// 鼠标按下滑块改变可移动状态并获取点击的位置
slider.mousedown(function(event) {
    clickPosition = event.clientY - slider[0].offsetTop;

    // 给窗口绑定鼠标移动事件
    $(document).mousemove(mouseMoveOnWindow);
});

// 松开鼠标按键改变可移动状态
$(document).mouseup(function() {
    $(document).unbind("mousemove", mouseMoveOnWindow);
});

// 在窗口上滑动改变值
function mouseMoveOnWindow(event) {
    if(isBottomBorder || isTopBorder) {
        borderDrage(event);
    } else {
        trackDrag(event);
    }
}

// 在轨道上滑动
function trackDrag(event) {
    var currentPosition = event.clientY - clickPosition;
    if(currentPosition <= -3) {
        changePosition(-3);
        isTopBorder = 1;
    } else if(currentPosition >= 97) {
        changePosition(97);
        isBottomBorder = 1;
    } else {
        changePosition(currentPosition);
    }
}

// 在边界上滑动
function borderDrage(event) {
    var currentPosition = event.clientY - clickPosition;
    if(isTopBorder) {
        if(currentPosition > -3) {
            changePosition(currentPosition);
            isTopBorder = 0;
        }
    }

    if(isBottomBorder) {
        if(currentPosition < 97) {
            changePosition(currentPosition);
            isBottomBorder = 0;
        }
    }
}

// 改变滑块在轨道中的值
function changePosition(position) {
    slider.css({
        top: position + "px"
    });
    range.attr("data-gm-value", (97 - Number(slider.css("top").split("p")[0])));
}

demo演示地址

目前只兼容了 Chrome,其他的浏览其后续会测试。弄好兼容性之后可能还会有组件的封装,请期待后续~~

后续:前端组件—纵向范围控件(二)

猜你喜欢

转载自blog.csdn.net/qq_39223195/article/details/81234421