基于 mithril.js ,javascript ,scss写一个可拖动的滑块组件,供大家参考,具体内容如下
问题描述:
需求需要实现一个可拖动的滑块组件,但是又不能用UI框架,只好自己动手写一个了。 废话不多说,直接上代码。
技术要求:
需要有mithril.js,javascript,scss技术基础。
js及页面代码。
var m = require(\"mithril\");require(\'./slider.scss\');import slider from \'./slider\';let obj = {colorWidth: 0, // 已拖拽长度clickOpen: false, // 是否开启拖拽sliderDom: \'\', // 绑定的灰条domcolorDom: \'\', // 绑定的有色条domradiusDom: \'\', // 绑定的圆点dommoveEmentRect: null, // 获取灰条dom参数Percentage: 0, // 百分比minWidth: 0, // 拖动区间下限maxWidth: 0, // 拖动区间上限sliderCallback: null, // 参数回调node: [0, 25, 50, 75, 100], // 节点数及占比// 初始化数据initslider:function(){obj.sliderDom = document.getElementsByClassName(\'slider-body\')[0]; // 允许进行开始拖拽的元素obj.colorDom = document.getElementsByClassName(\'slider-section\')[0]; // 允许进行开始拖拽的元素obj.radiusDom = document.getElementsByClassName(\'slider-radius-body\')[0]; // 允许进行开始拖拽的元素obj.moveEmentRect = obj.sliderDom.getBoundingClientRect(); // 获取拖拽父元素的宽度obj.maxWidth = obj.moveEmentRect.width;},// 处理宽度值域handleWidth:function(EV){if (EV <= obj.minWidth) {return obj.minWidth;} else if (EV >= obj.maxWidth) {return obj.maxWidth;} else {return EV;}},// 鼠标点击 拖动开始getMousedown:function(e){if (e.target === obj.sliderDom || e.target === obj.colorDom || e.target === obj.radiusDom) { // 判断是否是可点击拖拽的元素obj.clickOpen = true; // 打开拖拽状态let Width = e.clientX - obj.moveEmentRect.left; // 计算拖拽距离obj.colorWidth = this.handleWidth(Width); // 处理拖拽距离转化为长度console.log(obj.colorWidth, \'拖动开始\')this.sliderCallback && this.sliderCallback({colorWidth : this.getPercentage(), // 将数据回传页面})}},// 拖动中getMoveWidth:function(e){if (obj.clickOpen) {let moveX = e.clientX - obj.moveEmentRect.left;obj.colorWidth = this.handleWidth(moveX);console.log(obj.colorWidth, \'拖动中\')this.sliderCallback && this.sliderCallback({colorWidth : this.getPercentage(), // 将数据回传页面})}},// 鼠标松开 拖动结束getmouseUp:function(){obj.clickOpen = false;console.log(\'拖动结束\')},// 绑定到body上,实现在组件外面可以拖拽getBodyMouse: function(){let body = document.querySelector(\'body\');body.onmousemove = function(e){obj.getMoveWidth(e); // 在body上拖拽组件};body.onmouseup = function(e){obj.getmouseUp(e); // 在body上拖拽结束时关闭可拖拽状态obj.onmouseout(); // 在body上结束拖拽时隐藏百分比}},// 计算拖动的百分比getPercentage: function () {let _P = (Number(obj.colorWidth) / Number(obj.maxWidth)).toFixed(2);this.Percentage = Math.floor((Number(_P || 0) * 100));return Number(_P);},// 鼠标移入显示百分比onmouseover:function(){let _S = document.getElementsByClassName(\'slider-percentage\')[0];_S.style.display = \'block\';},// 鼠标移除隐藏百分比onmouseout:function(){let _S = document.getElementsByClassName(\'slider-percentage\')[0];_S.style.display = \'none\';},// 清除数据closemode: function () {obj.colorWidth = 0; // 已拖拽长度obj.clickOpen = false; // 是否开启拖拽obj.sliderDom = \'\'; // 绑定的灰条domobj.colorDom = \'\'; // 绑定的有色条domobj.radiusDom = \'\'; // 绑定的圆点domobj.moveEmentRect = null; // 获取灰条dom参数obj.Percentage = 0; // 百分比obj.minWidth = 0;obj.maxWidth = 0;obj.sliderCallback = null; // 参数回调},// 百分比选择getNodePer:function () {return obj.node.map((item) => {return m(\'div\',{class:\'slider-node\', style: `left: ${item}%`, onclick: function(){obj.getNodeData(item);}},[])})},getNodeData:function(item){obj.colorWidth = Number(obj.maxWidth) * (item / 100);this.sliderCallback && this.sliderCallback({colorWidth : this.getPercentage(), // 将数据回传页面});},}export default {oninit: function (vnode) {},oncreate: function (vnode) {obj.sliderCallback = vnode.attrs.cb;obj.initslider();obj.onmouseout();obj.getBodyMouse();},view: function (vnode) {return m(\'div\', {class: \'slider\'}, [m(\'div\',{class:\"slider-body\",onmousedown:function(e){obj.getMousedown(e);},onmousemove:function(e){obj.getMoveWidth(e);},onmouseup:function(e){obj.getmouseUp(e);}},[m(\'div\',{class:\"slider-section\", style:`width: ${obj.colorWidth}px`},[m(\'div\',{class:\"slider-radius\",onmouseover:function(){obj.onmouseover();},onmouseout:function(){obj.onmouseout();}},[m(\'div\',{class:\"slider-radius-body\"},[])]),m(\'div\',{class:\"slider-percentage\" , style: `left: ${obj.colorWidth - 25}px`},[obj.Percentage + \'%\']),]),obj.getNodePer(),]),])},onremove: function (vnode) {obj.closemode();},}
scss样式代码。
// 用的是scss预处理样式// $arrowsSize scss变量// var(--primary-lighten)用的是全局颜色,可以直接用颜色值代替// $dark #ligth 为黑夜白天样式,可以不用。$arrowsSize: 6px; // 三角形 大小.slider{width: 100%;.slider-body{width: 100%;height: 6px;margin: 16px 0;border-radius: 5px;position: relative;cursor: pointer;.slider-section{height: 6px;background-color: var(--primary-lighten);// width: 30%;position: absolute;left: 0;border-radius: 5px;.slider-radius{height: 16px;width: 16px;position: absolute;left: 100%;z-index: 999;top: -5px;transform: translateX(-50%);background-color: transparent;text-align: center;user-select: none;line-height: normal;.slider-radius-body{width: 16px;height: 16px;border: 2px solid var(--primary-lighten);background-color: var(--fontwhite-base);border-radius: 50%;transition: .2s;user-select: none;&::after {content: \'\';height: 100%;display: inline-block;vertical-align: middle;}}}.slider-percentage{// display: none;height: 25px;width: 50px;line-height: 25px;border-radius: 5px;background-color: var(--mode-darken);text-align: center;font-size: 14px;color: var(--font-darken);position: absolute;top: -40px;// left: 100%;&::after {content: \'\';display: inline-block;vertical-align: middle;width: 0;height: 0;position: absolute;border-top: solid $arrowsSize;border-left: solid $arrowsSize transparent !important;border-right: solid $arrowsSize transparent !important;border-bottom: solid $arrowsSize transparent !important;top: 25px;left: 35%;color: var(--mode-darken);}}}.slider-node{position: absolute;height: 8px;width: 8px;border-radius: 100%;background-color: var(--fontwhite-base);border: 2px solid var(--primary-lighten);transform: translateX(-50%);top: -1px;}}}#dark .slider-body{background-color: var(--line-darken3);}#light .slider-body{background-color: var(--line-lighten3);}
调用
getSlider: function () {return m(slider, {cb : function(arg){console.log(arg,22222)},});},obj.getSlider(),
说明一下
因为公司项目涉及保密条例,电脑都加了安全限制,无法录制视频或者gif图片,所有只能截图展示了。
效果
可以点击圆点拖动,也可以直接点击灰条进行点选然后拖动,也可以点击灰条上的百分比圆点进行拖动,因为单独又把事件绑定到了body上,所以可以在灰条上拖动开始并且在组件外也可以进行拖动,类似Element UI的slider组件效果。
拖动参数的打印
只为分享写代码过程中的一些心得体会,感谢平台!
以上就是本文的全部内容,希望对大家的学习有所帮助