1
+ <!DOCTYPE html>
2
+ < html lang ="en ">
3
+
4
+ < head >
5
+ < meta charset ="UTF-8 ">
6
+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
7
+ < title > 具有透明度和调色板的 HSL 到 RGB 颜色选择器</ title >
8
+ < link rel ="stylesheet " href ="https://www.unpkg.com/ew-message/dist/ew-message.min.css ">
9
+ < style >
10
+ body {
11
+ font-family : Arial, sans-serif;
12
+ padding : 20px ;
13
+ }
14
+
15
+ .container {
16
+ max-width : 800px ;
17
+ margin : 0 auto;
18
+ }
19
+
20
+ input [type = "range" ] {
21
+ width : 60% ;
22
+ min-width : 200px ;
23
+ height : 10px ;
24
+ -webkit-appearance : none;
25
+ appearance : none;
26
+ background : linear-gradient (to right, red, yellow, green, cyan, blue, magenta, red);
27
+ border-radius : 5px ;
28
+ outline : none;
29
+ }
30
+
31
+ .color-box {
32
+ width : 100% ;
33
+ height : 200px ;
34
+ margin-top : 20px ;
35
+ border-radius : 10px ;
36
+ background-color : # fff ;
37
+ }
38
+
39
+ .controls {
40
+ display : flex;
41
+ flex-direction : column;
42
+ margin-bottom : 20px ;
43
+ }
44
+
45
+ .control {
46
+ margin-bottom : 15px ;
47
+ }
48
+
49
+ label {
50
+ margin-right : 10px ;
51
+ }
52
+
53
+ .output {
54
+ margin-top : 10px ;
55
+ }
56
+
57
+ .palette {
58
+ display : flex;
59
+ margin-top : 20px ;
60
+ flex-wrap : wrap;
61
+ }
62
+
63
+ .color-swatch {
64
+ width : 50px ;
65
+ height : 50px ;
66
+ margin : 5px ;
67
+ border-radius : 5px ;
68
+ cursor : pointer;
69
+ border : 2px solid # ccc ;
70
+ outline : none;
71
+ }
72
+
73
+ .color-swatch : hover {
74
+ box-shadow : 0 0 4px # 007bff ;
75
+ }
76
+
77
+ .btn {
78
+ margin-top : 10px ;
79
+ padding : 10px 15px ;
80
+ background-color : # 007bff ;
81
+ color : # fff ;
82
+ border : none;
83
+ border-radius : 5px ;
84
+ cursor : pointer;
85
+ }
86
+
87
+ .btn : hover {
88
+ background-color : # 0056b3 ;
89
+ }
90
+ </ style >
91
+ </ head >
92
+
93
+ < body >
94
+ < div class ="container ">
95
+ < h1 > 具有透明度和调色板的 HSL 到 RGB 颜色选择器</ h1 >
96
+
97
+ < div class ="controls ">
98
+ < div class ="control ">
99
+ < label for ="hsl-hue "> Hue (H):</ label >
100
+ < input type ="range " id ="hsl-hue " min ="0 " max ="360 " value ="0 ">
101
+ < span id ="hue-value "> 0</ span > °
102
+ </ div >
103
+ < div class ="control ">
104
+ < label for ="hsl-saturation "> Saturation (S):</ label >
105
+ < input type ="range " id ="hsl-saturation " min ="0 " max ="100 " value ="50 ">
106
+ < span id ="saturation-value "> 50</ span > %
107
+ </ div >
108
+ < div class ="control ">
109
+ < label for ="hsl-lightness "> Lightness (L):</ label >
110
+ < input type ="range " id ="hsl-lightness " min ="0 " max ="100 " value ="50 ">
111
+ < span id ="lightness-value "> 50</ span > %
112
+ </ div >
113
+ < div class ="control ">
114
+ < label for ="hsl-alpha "> Alpha (A):</ label >
115
+ < input type ="range " id ="hsl-alpha " min ="0 " max ="1 " step ="0.01 " value ="1 ">
116
+ < span id ="alpha-value "> 1</ span >
117
+ </ div >
118
+ </ div >
119
+
120
+ < div class ="color-box " id ="color-box "> </ div >
121
+
122
+ < div class ="output ">
123
+ < p > RGB: < span id ="rgb-value "> rgb(255, 255, 255)</ span > </ p >
124
+ < p > RGBA: < span id ="rgba-value "> rgba(255, 255, 255, 1)</ span > </ p >
125
+ </ div >
126
+
127
+ < h3 > 保存的颜色:</ h3 >
128
+ < div class ="palette " id ="color-palette "> </ div >
129
+
130
+ < button class ="btn " id ="save-palette " type ="button "> 保存颜色</ button >
131
+ < button class ="btn " id ="copy-palette " type ="button "> 复制颜色</ button >
132
+ < button class ="btn " id ="clear-palette " type ="button "> 清除调色板</ button >
133
+ </ div >
134
+
135
+ < script src ="https://www.unpkg.com/ew-message/dist/ew-message.min.js "> </ script >
136
+ < script src ="https://www.eveningwater.com/static/plugin/popbox.min.js "> </ script >
137
+ < script >
138
+ const copyHandler = ( str ) => {
139
+ const confirm = ( title = '温馨提示' , content = '已复制到剪切板' ) => {
140
+ ewConfirm ( {
141
+ title,
142
+ content,
143
+ showCancel : false
144
+ } ) ;
145
+ } ;
146
+ const baseCopy = ( copyText ) =>
147
+ new Promise ( ( resolve , reject ) => {
148
+ if ( navigator . clipboard && window . isSecureContext ) {
149
+ navigator . clipboard
150
+ . writeText ( copyText )
151
+ . then ( ( ) => {
152
+ resolve ( ) ;
153
+ } )
154
+ . catch ( ( ) => {
155
+ reject ( new Error ( '复制失败' ) ) ;
156
+ } ) ;
157
+ } else {
158
+ const input = this . create ( 'input' ) ;
159
+ input . value = copyText ;
160
+ input . style . position = 'absolute' ;
161
+ input . style . left = '-9999px' ;
162
+ input . style . top = '-9999px' ;
163
+ document . body . append ( input ) ;
164
+ input . focus ( ) ;
165
+ input . select ( ) ;
166
+ if ( document . execCommand ) {
167
+ document . execCommand ( 'copy' ) ;
168
+ resolve ( ) ;
169
+ } else {
170
+ reject ( new Error ( '复制失败' ) ) ;
171
+ }
172
+ input . remove ( ) ;
173
+ }
174
+ } ) ;
175
+ baseCopy ( str )
176
+ . then ( ( ) => confirm ( ) )
177
+ . catch ( ( ) => confirm ( '温馨提示' , '复制失败' ) ) ;
178
+ }
179
+ const HSLToRGB = ( h , s , l ) => {
180
+ s /= 100 ;
181
+ l /= 100 ;
182
+ const k = ( n ) => ( n + h / 30 ) % 12 ;
183
+ const a = s * Math . min ( l , 1 - l ) ;
184
+ const f = ( n ) => l - a * Math . max ( - 1 , Math . min ( k ( n ) - 3 , 9 - k ( n ) , 1 ) ) ;
185
+ return [ 255 * f ( 0 ) , 255 * f ( 8 ) , 255 * f ( 4 ) ] ;
186
+ } ;
187
+
188
+ const hueSlider = document . getElementById ( 'hsl-hue' ) ;
189
+ const saturationSlider = document . getElementById ( 'hsl-saturation' ) ;
190
+ const lightnessSlider = document . getElementById ( 'hsl-lightness' ) ;
191
+ const alphaSlider = document . getElementById ( 'hsl-alpha' ) ;
192
+ const colorBox = document . getElementById ( 'color-box' ) ;
193
+ const rgbValue = document . getElementById ( 'rgb-value' ) ;
194
+ const rgbaValue = document . getElementById ( 'rgba-value' ) ;
195
+ const hueValue = document . getElementById ( 'hue-value' ) ;
196
+ const saturationValue = document . getElementById ( 'saturation-value' ) ;
197
+ const lightnessValue = document . getElementById ( 'lightness-value' ) ;
198
+ const alphaValue = document . getElementById ( 'alpha-value' ) ;
199
+ const colorPalette = document . getElementById ( 'color-palette' ) ;
200
+ const clearPaletteButton = document . getElementById ( 'clear-palette' ) ;
201
+ const savePaletteButton = document . getElementById ( 'save-palette' ) ;
202
+ const copyPaletteButton = document . getElementById ( 'copy-palette' ) ;
203
+
204
+
205
+ const savedColors = [ ] ;
206
+
207
+ const updateColor = ( ) => {
208
+ const h = parseInt ( hueSlider . value ) ;
209
+ const s = parseInt ( saturationSlider . value ) ;
210
+ const l = parseInt ( lightnessSlider . value ) ;
211
+ const a = parseFloat ( alphaSlider . value ) ;
212
+
213
+ hueValue . textContent = h ;
214
+ saturationValue . textContent = s ;
215
+ lightnessValue . textContent = l ;
216
+ alphaValue . textContent = a . toFixed ( 2 ) ;
217
+
218
+ const [ r , g , b ] = HSLToRGB ( h , s , l ) . map ( item => item . toFixed ( 0 ) ) ;
219
+ const rgba = `rgba(${ r } , ${ g } , ${ b } , ${ a } )` ;
220
+
221
+ colorBox . style . backgroundColor = rgba ;
222
+ rgbValue . textContent = `rgb(${ r } , ${ g } , ${ b } )` ;
223
+ rgbaValue . textContent = rgba ;
224
+ } ;
225
+
226
+ const saveColor = ( ) => {
227
+ const h = parseInt ( hueSlider . value ) ;
228
+ const s = parseInt ( saturationSlider . value ) ;
229
+ const l = parseInt ( lightnessSlider . value ) ;
230
+ const a = parseFloat ( alphaSlider . value ) ;
231
+
232
+ const [ r , g , b ] = HSLToRGB ( h , s , l ) . map ( item => item . toFixed ( 0 ) ) ;
233
+ const rgba = `rgba(${ r } , ${ g } , ${ b } , ${ a } )` ;
234
+
235
+ savedColors . push ( rgba ) ;
236
+
237
+ const colorSwatch = document . createElement ( 'div' ) ;
238
+ colorSwatch . classList . add ( 'color-swatch' ) ;
239
+ colorSwatch . style . backgroundColor = rgba ;
240
+ colorSwatch . addEventListener ( 'click' , ( ) => {
241
+ const [ hue , saturation , lightness ] = [ h , s , l ] ;
242
+ hueSlider . value = hue ;
243
+ saturationSlider . value = saturation ;
244
+ lightnessSlider . value = lightness ;
245
+ alphaSlider . value = a ;
246
+
247
+ updateColor ( ) ;
248
+ } ) ;
249
+
250
+ colorPalette . appendChild ( colorSwatch ) ;
251
+ } ;
252
+
253
+ const clearPalette = ( ) => {
254
+ savedColors . length = 0 ;
255
+ colorPalette . innerHTML = '' ;
256
+ } ;
257
+
258
+ hueSlider . addEventListener ( 'input' , updateColor ) ;
259
+ saturationSlider . addEventListener ( 'input' , updateColor ) ;
260
+ lightnessSlider . addEventListener ( 'input' , updateColor ) ;
261
+ alphaSlider . addEventListener ( 'input' , updateColor ) ;
262
+
263
+ clearPaletteButton . addEventListener ( 'click' , clearPalette ) ;
264
+ savePaletteButton . addEventListener ( 'click' , saveColor ) ;
265
+ copyPaletteButton . addEventListener ( 'click' , ( ) => {
266
+ if ( savedColors . length ) {
267
+ copyHandler ( JSON . stringify ( savedColors ) ) ;
268
+ } else {
269
+ ewMessage . warning ( "请先保存当前颜色再点击复制!" )
270
+ }
271
+ } )
272
+
273
+ updateColor ( ) ;
274
+ </ script >
275
+ </ body >
276
+
277
+ </ html >
0 commit comments