前端切图学习-自定义范围滑块

Custom Range Slider

Posted by R1NG on August 31, 2021 Viewed Times

自定义范围滑块 Custom Range Slider

1. 概述

项目本体展示了一个可自定义最小值和最大值的滑块.

本项目中涉及的知识点:

  1. 使用 linear-gradient() 实现渐变背景效果.
  2. 在不同的浏览器中自定义滑块样式.

效果:

20210901084931


2. 结构和切图

网页的基本结构如下:

1
2
3
4
5
6
7
<body>
    <h2>Custom Range Slider</h2>
    <div class="range-container">
        <input type="range" id="range" min="0" max="616" step="0.1">
        <label for="range">308</label>
    </div>
</body>


3. 编写 CSS 样式

首先将 body 的样式设为 水平垂直居中:

1
2
3
4
5
6
7
8
9
10
11
body {
    background-image: linear-gradient(135deg, #1f1e33 0%, #c3cfe2 100%);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100vh;
    overflow: hidden;
    margin: 0;
}

随后设定各级文字样式:

1
2
3
4
5
6
7
8
h2 {
    position: absolute;
    top: 10px;
    color: #c3cfe2;
}
label {
    color: #1f1e33;
}

range-container 容器定位方式设为 relative, 使滑块位置提示数字和滑块水平位置相同:

1
2
3
.range-container {
    position: relative;
}

最后设定滑块本身的样式. 注意对不同浏览器兼容性的处理.

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
input[type="range"]{
    width: 300px;
    margin: 18px 0;
    -webkit-appearance: none;
    border-radius: 4px;
}
input[type="range"]:focus {
    outline: none;
}
input[type="range"] + label {
    background-color: #fff;
    position: absolute;
    top: -25px;
    left: 110px;
    width: 80px;
    padding: 5px 0;
    text-align: center;
    border-radius: 4px;
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
}

/* Chrome & Safari */
    input[type='range']::-webkit-slider-runnable-track {
    background: #c3cfe2;
    border-radius: 4px;
    width: 100%;
    height: 10px;
    cursor: pointer;
}

input[type='range']::-webkit-slider-thumb {
    -webkit-appearance: none;
    height: 24px;
    width: 24px;
    background: #fff;
    border-radius: 50%;
    border: 1px solid #1f1e33;
    margin-top: -7px;
    cursor: pointer;

}

/* Firefox */
input[type='range']::-moz-range-track {
    background: #c3cfe2;
    border-radius: 4px;
    width: 100%;
    height: 13px;
    cursor: pointer;
}

input[type='range']::-moz-range-thumb {
    -webkit-appearance: none;
    height: 24px;
    width: 24px;
    background: #fff;
    border-radius: 50%;
    border: 1px solid #1f1e33;
    margin-top: -7px;
    cursor: pointer;
}

/* IE */
input[type='range']::-ms-track {
    background: #c3cfe2;
    border-radius: 4px;
    width: 100%;
    height: 13px;
    cursor: pointer;
}

input[type='range']::-ms-thumb {
    -webkit-appearance: none;
    height: 24px;
    width: 24px;
    background: #fff;
    border-radius: 50%;
    border: 1px solid #c3cfe2;
    margin-top: -7px;
    cursor: pointer;
}

最后, 完整的 CSS 样式表如下:

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
* {
   box-sizing: border-box;
}
body {
   background-image: linear-gradient(135deg, #1f1e33 0%, #c3cfe2 100%);
   font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
   display: flex;
   flex-direction: column;
   align-items: center;
   justify-content: center;
   height: 100vh;
   overflow: hidden;
   margin: 0;
}

h2 {
   position: absolute;
   top: 10px;
   color: #c3cfe2;
}
label {
   color: #1f1e33;
}
.range-container {
   position: relative;
}

input[type="range"]{
   width: 300px;
   margin: 18px 0;
   -webkit-appearance: none;
   border-radius: 4px;
}
input[type="range"]:focus {
   outline: none;
}
input[type="range"] + label {
   background-color: #fff;
   position: absolute;
   top: -25px;
   left: 110px;
   width: 80px;
   padding: 5px 0;
   text-align: center;
   border-radius: 4px;
   box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
}

/* Chrome & Safari */
   input[type='range']::-webkit-slider-runnable-track {
   background: #c3cfe2;
   border-radius: 4px;
   width: 100%;
   height: 10px;
   cursor: pointer;
}

input[type='range']::-webkit-slider-thumb {
   -webkit-appearance: none;
   height: 24px;
   width: 24px;
   background: #fff;
   border-radius: 50%;
   border: 1px solid #1f1e33;
   margin-top: -7px;
   cursor: pointer;

}

/* Firefox */
input[type='range']::-moz-range-track {
   background: #c3cfe2;
   border-radius: 4px;
   width: 100%;
   height: 13px;
   cursor: pointer;
}

input[type='range']::-moz-range-thumb {
   -webkit-appearance: none;
   height: 24px;
   width: 24px;
   background: #fff;
   border-radius: 50%;
   border: 1px solid #1f1e33;
   margin-top: -7px;
   cursor: pointer;
}

/* IE */
input[type='range']::-ms-track {
   background: #c3cfe2;
   border-radius: 4px;
   width: 100%;
   height: 13px;
   cursor: pointer;
}

input[type='range']::-ms-thumb {
   -webkit-appearance: none;
   height: 24px;
   width: 24px;
   background: #fff;
   border-radius: 50%;
   border: 1px solid #c3cfe2;
   margin-top: -7px;
   cursor: pointer;
}


4. JavaScript

最后编写 JavaScript 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const range = document.getElementById('range');

range.addEventListener('input', (e) => {
    const value = +e.target.value;
    const label = e.target.nextElementSibling;

    const range_width = getComputedStyle(e.target).getPropertyValue('width');
    const label_width = getComputedStyle(label).getPropertyValue('width');
    const num_width = +range_width.substring(0, range_width.length-2);
    const num_label_width = +label_width.substring(0, label_width.length-2);

    const max = +e.target.max;
    const min = +e.target.min;

    const left = value * (num_width / max) - num_label_width / 2 + scale(value, min, max, 10, -10);

    label.style.left = `${left}px`;
    label.innerHTML = value;
})

const scale = (num, in_min, in_max, out_min, out_max) => {
    return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

最后, 完整的网页演示可见 此处