suneditor 3.0.0-beta.2 → 3.0.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +186 -184
- package/LICENSE +21 -21
- package/README.md +157 -180
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +126 -123
- package/src/assets/design/color.css +131 -121
- package/src/assets/design/index.css +3 -3
- package/src/assets/design/size.css +37 -35
- package/src/assets/design/typography.css +37 -37
- package/src/assets/icons/defaultIcons.js +247 -232
- package/src/assets/suneditor-contents.css +779 -778
- package/src/assets/suneditor.css +43 -35
- package/src/core/base/eventHandlers/handler_toolbar.js +135 -135
- package/src/core/base/eventHandlers/handler_ww_clipboard.js +56 -56
- package/src/core/base/eventHandlers/handler_ww_dragDrop.js +115 -113
- package/src/core/base/eventHandlers/handler_ww_key_input.js +1200 -1200
- package/src/core/base/eventHandlers/handler_ww_mouse.js +194 -194
- package/src/core/base/eventManager.js +1550 -1484
- package/src/core/base/history.js +355 -355
- package/src/core/class/char.js +163 -162
- package/src/core/class/component.js +856 -842
- package/src/core/class/format.js +3433 -3422
- package/src/core/class/html.js +1927 -1890
- package/src/core/class/menu.js +357 -346
- package/src/core/class/nodeTransform.js +424 -424
- package/src/core/class/offset.js +858 -891
- package/src/core/class/selection.js +710 -620
- package/src/core/class/shortcuts.js +98 -98
- package/src/core/class/toolbar.js +438 -430
- package/src/core/class/ui.js +424 -422
- package/src/core/class/viewer.js +750 -750
- package/src/core/editor.js +1810 -1708
- package/src/core/section/actives.js +268 -241
- package/src/core/section/constructor.js +1348 -1661
- package/src/core/section/context.js +102 -102
- package/src/core/section/documentType.js +582 -561
- package/src/core/section/options.js +367 -0
- package/src/core/util/instanceCheck.js +59 -0
- package/src/editorInjector/_classes.js +36 -36
- package/src/editorInjector/_core.js +92 -92
- package/src/editorInjector/index.js +75 -75
- package/src/events.js +634 -622
- package/src/helper/clipboard.js +59 -59
- package/src/helper/converter.js +586 -564
- package/src/helper/dom/domCheck.js +304 -304
- package/src/helper/dom/domQuery.js +677 -669
- package/src/helper/dom/domUtils.js +618 -557
- package/src/helper/dom/index.js +12 -12
- package/src/helper/env.js +249 -240
- package/src/helper/index.js +25 -25
- package/src/helper/keyCodeMap.js +183 -183
- package/src/helper/numbers.js +72 -72
- package/src/helper/unicode.js +47 -47
- package/src/langs/ckb.js +231 -231
- package/src/langs/cs.js +231 -231
- package/src/langs/da.js +231 -231
- package/src/langs/de.js +231 -231
- package/src/langs/en.js +230 -230
- package/src/langs/es.js +231 -231
- package/src/langs/fa.js +231 -231
- package/src/langs/fr.js +231 -231
- package/src/langs/he.js +231 -231
- package/src/langs/hu.js +230 -230
- package/src/langs/index.js +28 -28
- package/src/langs/it.js +231 -231
- package/src/langs/ja.js +230 -230
- package/src/langs/km.js +230 -230
- package/src/langs/ko.js +230 -230
- package/src/langs/lv.js +231 -231
- package/src/langs/nl.js +231 -231
- package/src/langs/pl.js +231 -231
- package/src/langs/pt_br.js +231 -231
- package/src/langs/ro.js +231 -231
- package/src/langs/ru.js +231 -231
- package/src/langs/se.js +231 -231
- package/src/langs/tr.js +231 -231
- package/src/langs/uk.js +231 -231
- package/src/langs/ur.js +231 -231
- package/src/langs/zh_cn.js +231 -231
- package/src/modules/ApiManager.js +191 -191
- package/src/modules/Browser.js +669 -667
- package/src/modules/ColorPicker.js +364 -362
- package/src/modules/Controller.js +474 -454
- package/src/modules/Figure.js +1620 -1617
- package/src/modules/FileManager.js +359 -359
- package/src/modules/HueSlider.js +577 -565
- package/src/modules/Modal.js +346 -346
- package/src/modules/ModalAnchorEditor.js +643 -643
- package/src/modules/SelectMenu.js +549 -549
- package/src/modules/_DragHandle.js +17 -17
- package/src/modules/index.js +14 -14
- package/src/plugins/browser/audioGallery.js +83 -83
- package/src/plugins/browser/fileBrowser.js +103 -103
- package/src/plugins/browser/fileGallery.js +83 -83
- package/src/plugins/browser/imageGallery.js +81 -81
- package/src/plugins/browser/videoGallery.js +103 -103
- package/src/plugins/command/blockquote.js +61 -60
- package/src/plugins/command/exportPDF.js +134 -134
- package/src/plugins/command/fileUpload.js +456 -456
- package/src/plugins/command/list_bulleted.js +149 -148
- package/src/plugins/command/list_numbered.js +152 -151
- package/src/plugins/dropdown/align.js +157 -155
- package/src/plugins/dropdown/backgroundColor.js +108 -104
- package/src/plugins/dropdown/font.js +141 -137
- package/src/plugins/dropdown/fontColor.js +109 -105
- package/src/plugins/dropdown/formatBlock.js +170 -178
- package/src/plugins/dropdown/hr.js +152 -152
- package/src/plugins/dropdown/layout.js +83 -83
- package/src/plugins/dropdown/lineHeight.js +131 -130
- package/src/plugins/dropdown/list.js +123 -122
- package/src/plugins/dropdown/paragraphStyle.js +138 -138
- package/src/plugins/dropdown/table.js +4110 -4000
- package/src/plugins/dropdown/template.js +83 -83
- package/src/plugins/dropdown/textStyle.js +149 -149
- package/src/plugins/field/mention.js +242 -242
- package/src/plugins/index.js +120 -120
- package/src/plugins/input/fontSize.js +414 -410
- package/src/plugins/input/pageNavigator.js +71 -70
- package/src/plugins/modal/audio.js +677 -677
- package/src/plugins/modal/drawing.js +537 -531
- package/src/plugins/modal/embed.js +886 -886
- package/src/plugins/modal/image.js +1377 -1376
- package/src/plugins/modal/link.js +248 -240
- package/src/plugins/modal/math.js +563 -563
- package/src/plugins/modal/video.js +1226 -1226
- package/src/plugins/popup/anchor.js +224 -222
- package/src/suneditor.js +114 -107
- package/src/themes/dark.css +132 -122
- package/src/typedef.js +132 -130
- package/types/assets/icons/defaultIcons.d.ts +8 -0
- package/types/core/base/eventManager.d.ts +29 -4
- package/types/core/class/char.d.ts +2 -1
- package/types/core/class/component.d.ts +1 -2
- package/types/core/class/format.d.ts +8 -1
- package/types/core/class/html.d.ts +8 -0
- package/types/core/class/menu.d.ts +8 -0
- package/types/core/class/offset.d.ts +24 -26
- package/types/core/class/selection.d.ts +2 -0
- package/types/core/class/toolbar.d.ts +6 -0
- package/types/core/class/ui.d.ts +1 -1
- package/types/core/editor.d.ts +34 -12
- package/types/core/section/constructor.d.ts +5 -638
- package/types/core/section/documentType.d.ts +12 -2
- package/types/core/section/options.d.ts +740 -0
- package/types/core/util/instanceCheck.d.ts +50 -0
- package/types/editorInjector/_core.d.ts +5 -5
- package/types/editorInjector/index.d.ts +2 -2
- package/types/events.d.ts +2 -0
- package/types/helper/converter.d.ts +9 -0
- package/types/helper/dom/domQuery.d.ts +5 -5
- package/types/helper/dom/domUtils.d.ts +8 -0
- package/types/helper/env.d.ts +6 -1
- package/types/helper/index.d.ts +4 -1
- package/types/index.d.ts +122 -120
- package/types/langs/_Lang.d.ts +194 -194
- package/types/modules/ColorPicker.d.ts +5 -1
- package/types/modules/Controller.d.ts +8 -4
- package/types/modules/Figure.d.ts +2 -1
- package/types/modules/HueSlider.d.ts +4 -1
- package/types/modules/SelectMenu.d.ts +1 -1
- package/types/plugins/command/blockquote.d.ts +1 -0
- package/types/plugins/command/list_bulleted.d.ts +1 -0
- package/types/plugins/command/list_numbered.d.ts +1 -0
- package/types/plugins/dropdown/align.d.ts +1 -0
- package/types/plugins/dropdown/backgroundColor.d.ts +1 -0
- package/types/plugins/dropdown/font.d.ts +1 -0
- package/types/plugins/dropdown/fontColor.d.ts +1 -0
- package/types/plugins/dropdown/formatBlock.d.ts +3 -2
- package/types/plugins/dropdown/lineHeight.d.ts +1 -0
- package/types/plugins/dropdown/list.d.ts +1 -0
- package/types/plugins/dropdown/table.d.ts +6 -0
- package/types/plugins/input/fontSize.d.ts +1 -0
- package/types/plugins/modal/drawing.d.ts +4 -0
- package/types/plugins/modal/link.d.ts +32 -15
- package/types/suneditor.d.ts +13 -9
- package/types/typedef.d.ts +8 -0
package/src/modules/HueSlider.js
CHANGED
|
@@ -1,565 +1,577 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Implements HueSlider.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { dom, env } from '../helper';
|
|
6
|
-
import Controller from './Controller';
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
|
|
10
|
-
const SIZE = 240;
|
|
11
|
-
const BAR_H = 28;
|
|
12
|
-
const MIDDLE = SIZE / 2;
|
|
13
|
-
const LIGHTNESS_CONT_VALUE = 50;
|
|
14
|
-
const CLOSE_TO_CENTER_THRESHOLD = 3;
|
|
15
|
-
const FIXED_DEC = 10;
|
|
16
|
-
const SATURATION = 1;
|
|
17
|
-
const GRADIENT_RADIUS = 14;
|
|
18
|
-
const DEFAULT_COLOR_VALUE = { hex: '#FFFFFF', r: 255, g: 255, b: 255, h: 0, s: 1, l: 1 };
|
|
19
|
-
|
|
20
|
-
let LIGHTNESS = 0;
|
|
21
|
-
let isWheelragging = false;
|
|
22
|
-
let isBarDragging = false;
|
|
23
|
-
let wheelX = SIZE / 2;
|
|
24
|
-
let wheelY = SIZE / 2;
|
|
25
|
-
let finalColor = DEFAULT_COLOR_VALUE;
|
|
26
|
-
let ctx;
|
|
27
|
-
|
|
28
|
-
function CreateSliderCtx() {
|
|
29
|
-
const offscreenCanvas = document.createElement('canvas');
|
|
30
|
-
offscreenCanvas.width = SIZE;
|
|
31
|
-
offscreenCanvas.height = SIZE;
|
|
32
|
-
|
|
33
|
-
const html = /*html*/ `
|
|
34
|
-
<div class="se-hue-slider-container" style="width: ${SIZE}px; height: ${SIZE}px;">
|
|
35
|
-
<canvas class="se-hue-wheel" width="${SIZE}" height="${SIZE}"></canvas>
|
|
36
|
-
<div class="se-hue-wheel-pointer"></div>
|
|
37
|
-
</div>
|
|
38
|
-
<div class="se-hue-gradient-container">
|
|
39
|
-
<canvas class="se-hue-gradient" width="${SIZE}" height="${BAR_H}"></canvas>
|
|
40
|
-
<div class="se-hue-gradient-pointer"></div>
|
|
41
|
-
</div>
|
|
42
|
-
<div class="se-hue-final-hex" style="width:${SIZE}px; height: ${BAR_H}px;">
|
|
43
|
-
<div style="flex: 3; line-height: 1.5;">${DEFAULT_COLOR_VALUE.hex}</div>
|
|
44
|
-
<div style="flex: 1; height: 100%; border: 1px solid #fff; outline: 1px solid #000;"></div>
|
|
45
|
-
</div>
|
|
46
|
-
`;
|
|
47
|
-
|
|
48
|
-
const slider = dom.utils.createElement('DIV', { class: 'se-hue-slider' }, html);
|
|
49
|
-
const wheelCanvas = /** @type {HTMLCanvasElement} */ (slider.querySelector('.se-hue-wheel'));
|
|
50
|
-
const gradientBarCanvas = /** @type {HTMLCanvasElement} */ (slider.querySelector('.se-hue-gradient'));
|
|
51
|
-
const currentColors = slider.querySelector('.se-hue-final-hex').children;
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
slider,
|
|
55
|
-
offscreenCanvas,
|
|
56
|
-
offscreenCtx: offscreenCanvas.getContext('2d'),
|
|
57
|
-
wheel: wheelCanvas,
|
|
58
|
-
wheelCtx: wheelCanvas.getContext('2d'),
|
|
59
|
-
wheelPointer: /** @type {HTMLElement} */ (slider.querySelector('.se-hue-wheel-pointer')),
|
|
60
|
-
gradientBar: gradientBarCanvas,
|
|
61
|
-
gradientPointer: /** @type {HTMLElement} */ (slider.querySelector('.se-hue-gradient-pointer')),
|
|
62
|
-
fanalColorHex: /** @type {HTMLElement} */ (currentColors[0]),
|
|
63
|
-
fanalColorBackground: /** @type {HTMLElement} */ (currentColors[1])
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* @typedef {import('../modules/Controller').ControllerParams} ControllerParams_hueSlider
|
|
69
|
-
*/
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* @typedef {Object} HueSliderColor
|
|
73
|
-
* @property {string} hex - HEX color
|
|
74
|
-
* @property {number} r - Red color value
|
|
75
|
-
* @property {number} g - Green color value
|
|
76
|
-
* @property {number} b - Blue color value
|
|
77
|
-
* @property {number} h - Hue color value
|
|
78
|
-
* @property {number} s - Saturation color value
|
|
79
|
-
* @property {number} l - Lightness color value
|
|
80
|
-
*/
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* @typedef {Object} HueSliderParams
|
|
84
|
-
* @property {Node} [form] The form element to attach the hue slider.
|
|
85
|
-
* @property {boolean} [isNewForm] Whether to create a new form element.
|
|
86
|
-
* @property {ControllerParams_hueSlider} [controllerOptions] Controller options
|
|
87
|
-
*/
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* @class
|
|
91
|
-
* @description Create a Hue slider. (only create one at a time)
|
|
92
|
-
* - When you call the .attach() method, the hue slider is appended to the form element.
|
|
93
|
-
* It must be called every time it is used.
|
|
94
|
-
*/
|
|
95
|
-
class HueSlider {
|
|
96
|
-
/**
|
|
97
|
-
* @constructor
|
|
98
|
-
* @param {*} inst The instance object that called the constructor.
|
|
99
|
-
* @param {HueSliderParams} [params={}] Hue slider options
|
|
100
|
-
* @param {string} [className=""] The class name of the hue slider.
|
|
101
|
-
*/
|
|
102
|
-
constructor(inst, params, className) {
|
|
103
|
-
if (!params) params = {};
|
|
104
|
-
|
|
105
|
-
this.editor = inst.editor;
|
|
106
|
-
this.eventManager = inst.eventManager;
|
|
107
|
-
this.inst = inst;
|
|
108
|
-
|
|
109
|
-
// members
|
|
110
|
-
this.form = params.form;
|
|
111
|
-
this.ctx = {
|
|
112
|
-
wheelX: wheelX,
|
|
113
|
-
wheelY: wheelY,
|
|
114
|
-
lightness: LIGHTNESS,
|
|
115
|
-
wheelPointerX: '50%',
|
|
116
|
-
wheelPointerY: '50%',
|
|
117
|
-
gradientPointerX: 'calc(100% - 14px)',
|
|
118
|
-
color: DEFAULT_COLOR_VALUE
|
|
119
|
-
};
|
|
120
|
-
this.isOpen = false;
|
|
121
|
-
this.controlle = null;
|
|
122
|
-
this.__globalMouseDown = null;
|
|
123
|
-
this.
|
|
124
|
-
this.__globalMouseUp = null;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
this.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
this.close();
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
this.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
this.isOpen =
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
function
|
|
299
|
-
if (
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
//
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
//
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
wheelCtx.
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
wheelCtx.
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Implements HueSlider.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { dom, env } from '../helper';
|
|
6
|
+
import Controller from './Controller';
|
|
7
|
+
|
|
8
|
+
const { isTouchDevice } = env;
|
|
9
|
+
|
|
10
|
+
const SIZE = 240;
|
|
11
|
+
const BAR_H = 28;
|
|
12
|
+
const MIDDLE = SIZE / 2;
|
|
13
|
+
const LIGHTNESS_CONT_VALUE = 50;
|
|
14
|
+
const CLOSE_TO_CENTER_THRESHOLD = 3;
|
|
15
|
+
const FIXED_DEC = 10;
|
|
16
|
+
const SATURATION = 1;
|
|
17
|
+
const GRADIENT_RADIUS = 14;
|
|
18
|
+
const DEFAULT_COLOR_VALUE = { hex: '#FFFFFF', r: 255, g: 255, b: 255, h: 0, s: 1, l: 1 };
|
|
19
|
+
|
|
20
|
+
let LIGHTNESS = 0;
|
|
21
|
+
let isWheelragging = false;
|
|
22
|
+
let isBarDragging = false;
|
|
23
|
+
let wheelX = SIZE / 2;
|
|
24
|
+
let wheelY = SIZE / 2;
|
|
25
|
+
let finalColor = DEFAULT_COLOR_VALUE;
|
|
26
|
+
let ctx;
|
|
27
|
+
|
|
28
|
+
function CreateSliderCtx() {
|
|
29
|
+
const offscreenCanvas = document.createElement('canvas');
|
|
30
|
+
offscreenCanvas.width = SIZE;
|
|
31
|
+
offscreenCanvas.height = SIZE;
|
|
32
|
+
|
|
33
|
+
const html = /*html*/ `
|
|
34
|
+
<div class="se-hue-slider-container" style="width: ${SIZE}px; height: ${SIZE}px;">
|
|
35
|
+
<canvas class="se-hue-wheel" width="${SIZE}" height="${SIZE}"></canvas>
|
|
36
|
+
<div class="se-hue-wheel-pointer"></div>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="se-hue-gradient-container">
|
|
39
|
+
<canvas class="se-hue-gradient" width="${SIZE}" height="${BAR_H}"></canvas>
|
|
40
|
+
<div class="se-hue-gradient-pointer"></div>
|
|
41
|
+
</div>
|
|
42
|
+
<div class="se-hue-final-hex" style="width:${SIZE}px; height: ${BAR_H}px;">
|
|
43
|
+
<div style="flex: 3; line-height: 1.5;">${DEFAULT_COLOR_VALUE.hex}</div>
|
|
44
|
+
<div style="flex: 1; height: 100%; border: 1px solid #fff; outline: 1px solid #000;"></div>
|
|
45
|
+
</div>
|
|
46
|
+
`;
|
|
47
|
+
|
|
48
|
+
const slider = dom.utils.createElement('DIV', { class: 'se-hue-slider' }, html);
|
|
49
|
+
const wheelCanvas = /** @type {HTMLCanvasElement} */ (slider.querySelector('.se-hue-wheel'));
|
|
50
|
+
const gradientBarCanvas = /** @type {HTMLCanvasElement} */ (slider.querySelector('.se-hue-gradient'));
|
|
51
|
+
const currentColors = slider.querySelector('.se-hue-final-hex').children;
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
slider,
|
|
55
|
+
offscreenCanvas,
|
|
56
|
+
offscreenCtx: offscreenCanvas.getContext('2d'),
|
|
57
|
+
wheel: wheelCanvas,
|
|
58
|
+
wheelCtx: wheelCanvas.getContext('2d'),
|
|
59
|
+
wheelPointer: /** @type {HTMLElement} */ (slider.querySelector('.se-hue-wheel-pointer')),
|
|
60
|
+
gradientBar: gradientBarCanvas,
|
|
61
|
+
gradientPointer: /** @type {HTMLElement} */ (slider.querySelector('.se-hue-gradient-pointer')),
|
|
62
|
+
fanalColorHex: /** @type {HTMLElement} */ (currentColors[0]),
|
|
63
|
+
fanalColorBackground: /** @type {HTMLElement} */ (currentColors[1])
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @typedef {import('../modules/Controller').ControllerParams} ControllerParams_hueSlider
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @typedef {Object} HueSliderColor
|
|
73
|
+
* @property {string} hex - HEX color
|
|
74
|
+
* @property {number} r - Red color value
|
|
75
|
+
* @property {number} g - Green color value
|
|
76
|
+
* @property {number} b - Blue color value
|
|
77
|
+
* @property {number} h - Hue color value
|
|
78
|
+
* @property {number} s - Saturation color value
|
|
79
|
+
* @property {number} l - Lightness color value
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @typedef {Object} HueSliderParams
|
|
84
|
+
* @property {Node} [form] The form element to attach the hue slider.
|
|
85
|
+
* @property {boolean} [isNewForm] Whether to create a new form element.
|
|
86
|
+
* @property {ControllerParams_hueSlider} [controllerOptions] Controller options
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @class
|
|
91
|
+
* @description Create a Hue slider. (only create one at a time)
|
|
92
|
+
* - When you call the .attach() method, the hue slider is appended to the form element.
|
|
93
|
+
* It must be called every time it is used.
|
|
94
|
+
*/
|
|
95
|
+
class HueSlider {
|
|
96
|
+
/**
|
|
97
|
+
* @constructor
|
|
98
|
+
* @param {*} inst The instance object that called the constructor.
|
|
99
|
+
* @param {HueSliderParams} [params={}] Hue slider options
|
|
100
|
+
* @param {string} [className=""] The class name of the hue slider.
|
|
101
|
+
*/
|
|
102
|
+
constructor(inst, params, className) {
|
|
103
|
+
if (!params) params = {};
|
|
104
|
+
|
|
105
|
+
this.editor = inst.editor;
|
|
106
|
+
this.eventManager = inst.eventManager;
|
|
107
|
+
this.inst = inst;
|
|
108
|
+
|
|
109
|
+
// members
|
|
110
|
+
this.form = params.form;
|
|
111
|
+
this.ctx = {
|
|
112
|
+
wheelX: wheelX,
|
|
113
|
+
wheelY: wheelY,
|
|
114
|
+
lightness: LIGHTNESS,
|
|
115
|
+
wheelPointerX: '50%',
|
|
116
|
+
wheelPointerY: '50%',
|
|
117
|
+
gradientPointerX: 'calc(100% - 14px)',
|
|
118
|
+
color: DEFAULT_COLOR_VALUE
|
|
119
|
+
};
|
|
120
|
+
this.isOpen = false;
|
|
121
|
+
this.controlle = null;
|
|
122
|
+
this.__globalMouseDown = null;
|
|
123
|
+
this.__globalTouchMove = null;
|
|
124
|
+
this.__globalMouseUp = null;
|
|
125
|
+
this.__globalMouseMove = null;
|
|
126
|
+
this.__globalTouchStart = null;
|
|
127
|
+
this.__globalTouchEnd = null;
|
|
128
|
+
|
|
129
|
+
// init default controller
|
|
130
|
+
if (!params.isNewForm) {
|
|
131
|
+
const hueController = CreateHTML_basicControllerForm(inst.editor, className);
|
|
132
|
+
this.form = hueController.querySelector('.se-hue');
|
|
133
|
+
this.controller = new Controller(this, hueController, { position: 'top', isWWTarget: false, ...params.controllerOptions });
|
|
134
|
+
|
|
135
|
+
// buttons
|
|
136
|
+
this.eventManager.addEvent(hueController.querySelector('.se-btn-success'), 'click', () => {
|
|
137
|
+
inst.hueSliderAction(this.get());
|
|
138
|
+
this.close();
|
|
139
|
+
});
|
|
140
|
+
this.eventManager.addEvent(hueController.querySelector('.se-btn-danger'), 'click', () => {
|
|
141
|
+
this.close();
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @description Get the current color information.
|
|
148
|
+
* @returns {HueSliderColor} color information
|
|
149
|
+
*/
|
|
150
|
+
get() {
|
|
151
|
+
return finalColor;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @description Open the hue slider.
|
|
156
|
+
* @param {Node} target The element to attach the hue slider.
|
|
157
|
+
*/
|
|
158
|
+
open(target) {
|
|
159
|
+
this.attach();
|
|
160
|
+
this.controller.open(target, null, { isWWTarget: false, initMethod: null, addOffset: null });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* @description Reset information and close the hue slider.
|
|
165
|
+
*/
|
|
166
|
+
off() {
|
|
167
|
+
this.ctx = {
|
|
168
|
+
gradientPointerX: gradientPointer.style.left,
|
|
169
|
+
wheelPointerX: wheelPointer.style.left,
|
|
170
|
+
wheelPointerY: wheelPointer.style.top,
|
|
171
|
+
wheelX: wheelX,
|
|
172
|
+
wheelY: wheelY,
|
|
173
|
+
lightness: LIGHTNESS,
|
|
174
|
+
color: ctx?.color || getWheelColor(wheelCtx)
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
this.controller.close();
|
|
178
|
+
this.init();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @description Close the hue slider. (include off method)
|
|
183
|
+
* - Call the instance's hueSliderCancelAction method.
|
|
184
|
+
*/
|
|
185
|
+
close() {
|
|
186
|
+
this.off();
|
|
187
|
+
this.inst.hueSliderCancelAction();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* @description Attach the hue slider to the form element.
|
|
192
|
+
* @param {?Node=} form The element to attach the hue slider.
|
|
193
|
+
*/
|
|
194
|
+
attach(form) {
|
|
195
|
+
// drow
|
|
196
|
+
this.init();
|
|
197
|
+
(form || this.form).appendChild(slider);
|
|
198
|
+
ctx = this.ctx;
|
|
199
|
+
if (ctx) {
|
|
200
|
+
wheelX = ctx.wheelX;
|
|
201
|
+
wheelY = ctx.wheelY;
|
|
202
|
+
LIGHTNESS = ctx.lightness;
|
|
203
|
+
wheelPointer.style.left = ctx.wheelPointerX;
|
|
204
|
+
wheelPointer.style.top = ctx.wheelPointerY;
|
|
205
|
+
gradientPointer.style.left = ctx.gradientPointerX;
|
|
206
|
+
setHex(ctx.color.hex);
|
|
207
|
+
|
|
208
|
+
drawColorWheel();
|
|
209
|
+
createGradientBar(getDefaultColor());
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// touch event
|
|
213
|
+
if (isTouchDevice) {
|
|
214
|
+
// mobile name
|
|
215
|
+
this.__globalTouchStart = this.eventManager.addGlobalEvent('touchstart', OnTouchstart, { passive: false, capture: true });
|
|
216
|
+
this.__globalTouchMove = this.eventManager.addGlobalEvent('touchmove', OnTouchmove, true);
|
|
217
|
+
this.__globalTouchEnd = this.eventManager.addGlobalEvent(
|
|
218
|
+
'touchend',
|
|
219
|
+
() => {
|
|
220
|
+
isWheelragging = false;
|
|
221
|
+
isBarDragging = false;
|
|
222
|
+
},
|
|
223
|
+
true
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// mouse event
|
|
228
|
+
this.__globalMouseDown = this.eventManager.addGlobalEvent('mousedown', OnMousedown, { passive: false, capture: true });
|
|
229
|
+
this.__globalMouseMove = this.eventManager.addGlobalEvent('mousemove', OnMousemove, true);
|
|
230
|
+
this.__globalMouseUp = this.eventManager.addGlobalEvent(
|
|
231
|
+
'mouseup',
|
|
232
|
+
() => {
|
|
233
|
+
isWheelragging = false;
|
|
234
|
+
isBarDragging = false;
|
|
235
|
+
},
|
|
236
|
+
true
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
// open
|
|
240
|
+
this.isOpen = true;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* @description Initialize the hue slider information.
|
|
245
|
+
*/
|
|
246
|
+
init() {
|
|
247
|
+
this.isOpen = false;
|
|
248
|
+
isWheelragging = false;
|
|
249
|
+
isBarDragging = false;
|
|
250
|
+
|
|
251
|
+
if (this.__globalMouseDown) this.__globalMouseDown = this.eventManager.removeGlobalEvent(this.__globalMouseDown);
|
|
252
|
+
if (this.__globalMouseMove) this.__globalMouseMove = this.eventManager.removeGlobalEvent(this.__globalMouseMove);
|
|
253
|
+
if (this.__globalMouseUp) this.__globalMouseUp = this.eventManager.removeGlobalEvent(this.__globalMouseUp);
|
|
254
|
+
|
|
255
|
+
if (this.__globalTouchStart) this.__globalTouchStart = this.eventManager.removeGlobalEvent(this.__globalTouchStart);
|
|
256
|
+
if (this.__globalTouchMove) this.__globalTouchMove = this.eventManager.removeGlobalEvent(this.__globalTouchMove);
|
|
257
|
+
if (this.__globalTouchEnd) this.__globalTouchEnd = this.eventManager.removeGlobalEvent(this.__globalTouchEnd);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// init
|
|
262
|
+
const { slider, offscreenCanvas, offscreenCtx, wheel, wheelCtx, wheelPointer, gradientBar, gradientPointer, fanalColorHex, fanalColorBackground } = CreateSliderCtx();
|
|
263
|
+
|
|
264
|
+
// mobile
|
|
265
|
+
function OnTouchstart(event) {
|
|
266
|
+
const { target, touches } = event;
|
|
267
|
+
const clientX = touches[0].clientX;
|
|
268
|
+
const clientY = touches[0].clientY;
|
|
269
|
+
|
|
270
|
+
if (target === wheel) {
|
|
271
|
+
event.preventDefault();
|
|
272
|
+
isBarDragging = false;
|
|
273
|
+
isWheelragging = true;
|
|
274
|
+
updatePointer_wheel(clientX, clientY);
|
|
275
|
+
} else if (target === gradientBar) {
|
|
276
|
+
event.preventDefault();
|
|
277
|
+
isBarDragging = true;
|
|
278
|
+
isWheelragging = false;
|
|
279
|
+
updatePointer_bar(clientX);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function OnTouchmove(event) {
|
|
284
|
+
event.preventDefault();
|
|
285
|
+
|
|
286
|
+
const { touches } = event;
|
|
287
|
+
const clientX = touches[0].clientX;
|
|
288
|
+
const clientY = touches[0].clientY;
|
|
289
|
+
|
|
290
|
+
if (isWheelragging) {
|
|
291
|
+
updatePointer_wheel(clientX, clientY);
|
|
292
|
+
} else if (isBarDragging) {
|
|
293
|
+
updatePointer_bar(clientX);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// pc
|
|
298
|
+
function OnMousedown({ target, clientX, clientY }) {
|
|
299
|
+
if (target === wheel) {
|
|
300
|
+
isBarDragging = false;
|
|
301
|
+
isWheelragging = true;
|
|
302
|
+
updatePointer_wheel(clientX, clientY);
|
|
303
|
+
} else if (target === gradientBar) {
|
|
304
|
+
isBarDragging = true;
|
|
305
|
+
isWheelragging = false;
|
|
306
|
+
updatePointer_bar(clientX);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function OnMousemove({ clientX, clientY }) {
|
|
311
|
+
if (isWheelragging) {
|
|
312
|
+
updatePointer_wheel(clientX, clientY);
|
|
313
|
+
} else if (isBarDragging) {
|
|
314
|
+
updatePointer_bar(clientX);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function updatePointer_wheel(x, y) {
|
|
319
|
+
const rect = wheel.getBoundingClientRect();
|
|
320
|
+
x = x - rect.left - MIDDLE;
|
|
321
|
+
y = y - rect.top - MIDDLE;
|
|
322
|
+
|
|
323
|
+
const angle = (Math.atan2(y, x) * 180) / Math.PI;
|
|
324
|
+
const distance = Math.min(Math.sqrt(x * x + y * y), MIDDLE);
|
|
325
|
+
|
|
326
|
+
const posX = MIDDLE + distance * Math.cos((angle * Math.PI) / 180);
|
|
327
|
+
const posY = MIDDLE + distance * Math.sin((angle * Math.PI) / 180);
|
|
328
|
+
|
|
329
|
+
wheelPointer.style.left = `${posX}px`;
|
|
330
|
+
wheelPointer.style.top = `${posY}px`;
|
|
331
|
+
|
|
332
|
+
wheelPickedColor(posX, posY);
|
|
333
|
+
setFinalColor();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function updatePointer_bar(x) {
|
|
337
|
+
const rect = gradientBar.getBoundingClientRect();
|
|
338
|
+
let posX = x - rect.left;
|
|
339
|
+
posX = Math.max(GRADIENT_RADIUS, Math.min(posX, rect.width - GRADIENT_RADIUS));
|
|
340
|
+
|
|
341
|
+
gradientPointer.style.left = `${posX}px`;
|
|
342
|
+
|
|
343
|
+
selectGradientColor(x);
|
|
344
|
+
setFinalColor();
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function wheelPickedColor(posX, posY) {
|
|
348
|
+
wheelX = posX;
|
|
349
|
+
wheelY = posY;
|
|
350
|
+
createGradientBar(getDefaultColor());
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function createGradientBar(color) {
|
|
354
|
+
const gradientBarCtx = gradientBar.getContext('2d');
|
|
355
|
+
const gradient = gradientBarCtx.createLinearGradient(0, 0, gradientBar.width, 0);
|
|
356
|
+
|
|
357
|
+
gradient.addColorStop(0, 'black'); // 왼쪽은 검은색
|
|
358
|
+
gradient.addColorStop(1, color.hex); // 오른쪽은 선택한 색상
|
|
359
|
+
|
|
360
|
+
gradientBarCtx.fillStyle = gradient;
|
|
361
|
+
gradientBarCtx.fillRect(0, 0, gradientBar.width, gradientBar.height);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function getDefaultColor() {
|
|
365
|
+
return getWheelColor(offscreenCtx);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function setFinalColor() {
|
|
369
|
+
ctx.color = finalColor = getWheelColor(wheelCtx);
|
|
370
|
+
setHex(finalColor.hex);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function setHex(hex) {
|
|
374
|
+
fanalColorBackground.style.backgroundColor = fanalColorHex.textContent = hex;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function getWheelColor(wCtx) {
|
|
378
|
+
const pixel = wCtx.getImageData(wheelX, wheelY, 1, 1).data;
|
|
379
|
+
// eslint-disable-next-line prefer-const
|
|
380
|
+
let [h, s, l] = rgbToHsl(pixel);
|
|
381
|
+
|
|
382
|
+
// Calculate distance from the center of the wheel
|
|
383
|
+
const dx = wheelX - MIDDLE;
|
|
384
|
+
const dy = wheelY - MIDDLE;
|
|
385
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
386
|
+
|
|
387
|
+
if (distance < CLOSE_TO_CENTER_THRESHOLD) {
|
|
388
|
+
l = 1 - LIGHTNESS;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (l > 1) l = 1;
|
|
392
|
+
if (l < 0) l = 0;
|
|
393
|
+
|
|
394
|
+
// Adjust lightness based on LIGHTNESS value
|
|
395
|
+
const { r, g, b } = hslToRgb([h, s, l]);
|
|
396
|
+
|
|
397
|
+
// Convert RGB to HEX
|
|
398
|
+
const hex = `#${rgbToHex({ r, g, b })}`;
|
|
399
|
+
|
|
400
|
+
return {
|
|
401
|
+
hex,
|
|
402
|
+
r,
|
|
403
|
+
g,
|
|
404
|
+
b,
|
|
405
|
+
h,
|
|
406
|
+
s,
|
|
407
|
+
l: roundNumber(l)
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function selectGradientColor(x) {
|
|
412
|
+
const boundingRect = gradientBar.getBoundingClientRect();
|
|
413
|
+
let posX = x - boundingRect.left;
|
|
414
|
+
|
|
415
|
+
if (posX < 0) posX = 0;
|
|
416
|
+
if (posX > boundingRect.width) posX = boundingRect.width;
|
|
417
|
+
|
|
418
|
+
const tolerance = GRADIENT_RADIUS;
|
|
419
|
+
|
|
420
|
+
// If a click occurs near the end, the value is corrected all the way to the end.
|
|
421
|
+
if (posX >= gradientBar.width - tolerance) {
|
|
422
|
+
posX = gradientBar.width;
|
|
423
|
+
} else if (posX <= tolerance) {
|
|
424
|
+
posX = 0;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const normalizedLightness = 1 - posX / boundingRect.width; // 1 ~ 0
|
|
428
|
+
LIGHTNESS = normalizedLightness; // 0 ~ 1
|
|
429
|
+
|
|
430
|
+
drawColorWheel();
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function drawColorWheel() {
|
|
434
|
+
// init main canvas
|
|
435
|
+
wheelCtx.clearRect(0, 0, SIZE, SIZE);
|
|
436
|
+
|
|
437
|
+
// copy offscreen to main canvas
|
|
438
|
+
wheelCtx.drawImage(offscreenCanvas, 0, 0);
|
|
439
|
+
|
|
440
|
+
// drow dark wheel
|
|
441
|
+
drawWheelGradient();
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function drawWheelGradient() {
|
|
445
|
+
wheelCtx.globalAlpha = LIGHTNESS; // 0: white, 1: black
|
|
446
|
+
wheelCtx.fillStyle = 'black';
|
|
447
|
+
wheelCtx.beginPath();
|
|
448
|
+
wheelCtx.arc(MIDDLE, MIDDLE, MIDDLE, 0, 2 * Math.PI);
|
|
449
|
+
wheelCtx.fill();
|
|
450
|
+
wheelCtx.globalAlpha = 1.0;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function drawColorWheelToContext(context) {
|
|
454
|
+
if (!context) throw new Error('Context not found.');
|
|
455
|
+
|
|
456
|
+
const fixedSaturation = SATURATION * 100;
|
|
457
|
+
|
|
458
|
+
for (let h = 0; h <= 360; h += 0.5) {
|
|
459
|
+
for (let distance = 0; distance <= MIDDLE; distance += 1) {
|
|
460
|
+
context.beginPath();
|
|
461
|
+
|
|
462
|
+
const dynamicLightness = LIGHTNESS_CONT_VALUE + ((MIDDLE - distance) / MIDDLE) * 50;
|
|
463
|
+
|
|
464
|
+
context.fillStyle = `hsl(${h}, ${fixedSaturation}%, ${dynamicLightness}%)`;
|
|
465
|
+
|
|
466
|
+
const posX = MIDDLE + Math.cos(degreeToRadian(h)) * distance;
|
|
467
|
+
const posY = MIDDLE - Math.sin(degreeToRadian(h)) * distance;
|
|
468
|
+
|
|
469
|
+
context.arc(posX, posY, 1.5, 0, 2 * Math.PI);
|
|
470
|
+
context.fill();
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function degreeToRadian(deg) {
|
|
476
|
+
return (deg * Math.PI) / 180;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function rgbToHsl([r, g, b]) {
|
|
480
|
+
r /= 255;
|
|
481
|
+
g /= 255;
|
|
482
|
+
b /= 255;
|
|
483
|
+
|
|
484
|
+
const max = Math.max(r, g, b),
|
|
485
|
+
min = Math.min(r, g, b);
|
|
486
|
+
let h, s;
|
|
487
|
+
const l = (max + min) / 2;
|
|
488
|
+
|
|
489
|
+
if (max === min) {
|
|
490
|
+
h = s = 0; // achromatic
|
|
491
|
+
} else {
|
|
492
|
+
const d = max - min;
|
|
493
|
+
s = l > 0.5 ? d / (2.0 - max - min) : d / (max + min);
|
|
494
|
+
|
|
495
|
+
switch (max) {
|
|
496
|
+
case r:
|
|
497
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
498
|
+
break;
|
|
499
|
+
case g:
|
|
500
|
+
h = (b - r) / d + 2;
|
|
501
|
+
break;
|
|
502
|
+
case b:
|
|
503
|
+
h = (r - g) / d + 4;
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
h /= 6;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
return [roundNumber(h), roundNumber(s), roundNumber(l)];
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function hslToRgb([h, s, l]) {
|
|
514
|
+
let r, g, b;
|
|
515
|
+
|
|
516
|
+
if (s === 0) {
|
|
517
|
+
r = g = b = l; // achromatic
|
|
518
|
+
} else {
|
|
519
|
+
const hue2rgb = function hue2rgb(p, q, t) {
|
|
520
|
+
if (t < 0) t += 1;
|
|
521
|
+
if (t > 1) t -= 1;
|
|
522
|
+
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
523
|
+
if (t < 1 / 2) return q;
|
|
524
|
+
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
525
|
+
return p;
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
529
|
+
const p = 2 * l - q;
|
|
530
|
+
r = hue2rgb(p, q, h + 1 / 3);
|
|
531
|
+
g = hue2rgb(p, q, h);
|
|
532
|
+
b = hue2rgb(p, q, h - 1 / 3);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
return {
|
|
536
|
+
r: Math.round(r * 255),
|
|
537
|
+
g: Math.round(g * 255),
|
|
538
|
+
b: Math.round(b * 255)
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
function rgbToHex({ r, g, b }) {
|
|
543
|
+
let hexR = Math.floor(r).toString(16);
|
|
544
|
+
if (r < 16) hexR = `0${hexR}`;
|
|
545
|
+
let hexG = Math.floor(g).toString(16);
|
|
546
|
+
if (g < 16) hexG = `0${hexG}`;
|
|
547
|
+
let hexB = Math.floor(b).toString(16);
|
|
548
|
+
if (b < 16) hexB = `0${hexB}`;
|
|
549
|
+
return `${hexR}${hexG}${hexB}`.toUpperCase();
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
function roundNumber(num) {
|
|
553
|
+
const factor = Math.pow(10, FIXED_DEC);
|
|
554
|
+
return Math.round(num * factor) / factor;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// create
|
|
558
|
+
drawColorWheelToContext(offscreenCtx);
|
|
559
|
+
drawColorWheel();
|
|
560
|
+
|
|
561
|
+
function CreateHTML_basicControllerForm({ lang, icons }, className) {
|
|
562
|
+
const hueController = dom.utils.createElement(
|
|
563
|
+
'DIV',
|
|
564
|
+
{ class: `se-controller ${className}` },
|
|
565
|
+
/*html*/ `
|
|
566
|
+
<div class="se-hue"></div>
|
|
567
|
+
<div class="se-form-group se-form-w0 se-form-flex-btn">
|
|
568
|
+
<button type="button" class="se-btn se-btn-success" title="${lang.submitButton}" aria-label="${lang.submitButton}">${icons.checked}</button>
|
|
569
|
+
<button type="button" class="se-btn se-btn-danger" title="${lang.close}" aria-label="${lang.close}">${icons.cancel}</button>
|
|
570
|
+
</div>
|
|
571
|
+
`
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
return hueController;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
export default HueSlider;
|