基于 mithril.js ,javascript ,scss写一个可拖动的滑块组件,供大家参考,具体内容如下
问题描述:
需求需要实现一个可拖动的滑块组件,但是又不能用UI框架,只好自己动手写一个了。 废话不多说,直接上代码。
技术要求:
需要有mithril.js,javascript,scss技术基础。
js及页面代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
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样式代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
// 用的是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: . 2 s;
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-darken 3 );
}
#light .slider-body{
background-color : var(--line-lighten 3 );
}
|
调用
1
2
3
4
5
6
7
8
9
|
getSlider: function () {
return m(slider, {
cb : function (arg){
console.log(arg,22222)
},
});
},
obj.getSlider(),
|
说明一下
因为公司项目涉及保密条例,电脑都加了安全限制,无法录制视频或者gif图片,所有只能截图展示了。
效果
可以点击圆点拖动,也可以直接点击灰条进行点选然后拖动,也可以点击灰条上的百分比圆点进行拖动,因为单独又把事件绑定到了body上,所以可以在灰条上拖动开始并且在组件外也可以进行拖动,类似Element UI的slider组件效果。
拖动参数的打印
只为分享写代码过程中的一些心得体会,感谢平台!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/weixin_45126901/article/details/110531312