为了美观,很多业务场景会把下拉控件改成滑动控件,如下图中的“贷款期限”和“年利率”就是很典型的案例。
博主就在业务项目中,将该功能抽离出来,做成一个通用的组件,这样大家再遇到类似功能,就不用耗时费力的重头开发了。
HTML结构相当简单,只有3个标签:
<div class="bar">
<i class="len" data-value="7个月"><a class="g">7个月</a></i>
</div>
对应的CSS如下:
.bar {
border-radius: 4px;
background-color: rgba(220,220,220,0.4);
margin-top: 25px;
height: 8px;
.len {
float: left;
border-radius: 4px;
height: 8px;
background: url(../img/bar.png) no-repeat right center #ffcb65;
position: relative;
.g {
position: absolute;
top: -7px;
right: -30px;
width: 4em;
padding-top: 30px;
background: url(../img/bar-btn.png) no-repeat center top;
font-size: 14px;
color: #ffffcc;
text-align: center;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
}
}
JavaScript实现代码如下:
/**
* 计算器滑动模块
* @param {object} options
* @param {jQuery} options.bar 进度条
* @param {jQuery} options.btn 按钮
* @param {Array} options.data 进度条上的数据
*/
class Slider {
constructor(options) {
this.options = options;
this.init();
}
init() {
let ins = this;
if (ins.options.steps) {
return; // 只init一次-
}
// 将整个bar分隔成N个宽度-
let steps = [];
let w = (ins.options.bar[0].offsetWidth - 10) / (ins.options.data.length - 1);
ins.options.data.forEach(function (v, i) {
steps[i] = w * i;
});
ins.options.steps = steps;
let $v = ins.options.btn.parent();
let val = $v.data('value');
if (!val) {
val = ins.options.data[0];
}
ins.setValue(val);
ins.options.data.forEach(function (v, i) {
if (val == v) {
$v.width(ins.options.steps[i]);
}
});
// 绑定btn事件-
ins.bindEvent();
};
setValue(value) {
this.options.btn.html(value).parent().data('value', value);
};
bindEvent() {
let ins = this;
let $b = ins.options.btn;
let $v = $b.parent();
let x0 = 0, // 鼠标按下位置-
x1 = 0, // 鼠标移动过程的位置-
w0 = 0, // 滑动前的value大小-
w2 = ins.options.bar[0].offsetWidth;
$b.on('mousedown touchstart', function (event) {
x0 = event.clientX || event.touches[0].clientX;
w0 = $v.width();
}).on('mousemove touchmove', function (event) {
if (x0 == 0) return;
x1 = event.clientX || event.touches[0].clientX;
let w1 = w0 + x1 - x0;
if (w1 > w2) return;
$v.width(w1);
let val = getNewValue(w1);
if (val != $v.data('value')) {
ins.setValue(val);
}
}).on('mouseup touchend', function (event) {
x0 = x1 = 0;
});
// 根据当前value宽度获取对应的data-
function getNewValue(w) {
let max = 0;
ins.options.steps.forEach(function (v, i) {
if (w > v) max = i;
});
return ins.options.data[max];
}
};
}
export default Slider;
该组件同时支持PC端和移动端,JavaScript功能代码不受html结构影响,调用组件时只需要将关键元素传入即可。
作者:朱会震