基于 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: '', // 绑定的灰条dom colorDom: '', // 绑定的有色条dom radiusDom: '', // 绑定的圆点dom moveEmentRect: 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 = ''; // 绑定的灰条dom obj.colorDom = ''; // 绑定的有色条dom obj.radiusDom = ''; // 绑定的圆点dom obj.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组件效果。
拖动参数的打印
只为分享写代码过程中的一些心得体会,感谢平台!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
暂无评论...
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
2024年11月05日
2024年11月05日
- 雨林唱片《赏》新曲+精选集SACD版[ISO][2.3G]
- 罗大佑与OK男女合唱团.1995-再会吧!素兰【音乐工厂】【WAV+CUE】
- 草蜢.1993-宝贝对不起(国)【宝丽金】【WAV+CUE】
- 杨培安.2009-抒·情(EP)【擎天娱乐】【WAV+CUE】
- 周慧敏《EndlessDream》[WAV+CUE]
- 彭芳《纯色角3》2007[WAV+CUE]
- 江志丰2008-今生为你[豪记][WAV+CUE]
- 罗大佑1994《恋曲2000》音乐工厂[WAV+CUE][1G]
- 群星《一首歌一个故事》赵英俊某些作品重唱企划[FLAC分轨][1G]
- 群星《网易云英文歌曲播放量TOP100》[MP3][1G]
- 方大同.2024-梦想家TheDreamer【赋音乐】【FLAC分轨】
- 李慧珍.2007-爱死了【华谊兄弟】【WAV+CUE】
- 王大文.2019-国际太空站【环球】【FLAC分轨】
- 群星《2022超好听的十倍音质网络歌曲(163)》U盘音乐[WAV分轨][1.1G]
- 童丽《啼笑姻缘》头版限量编号24K金碟[低速原抓WAV+CUE][1.1G]