滑动组件

为了美观,很多业务场景会把下拉控件改成滑动控件,如下图中的“贷款期限”和“年利率”就是很典型的案例。

博主就在业务项目中,将该功能抽离出来,做成一个通用的组件,这样大家再遇到类似功能,就不用耗时费力的重头开发了。

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结构影响,调用组件时只需要将关键元素传入即可。

作者:朱会震

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值