How to use this.nativeClick method in Appium Xcuitest Driver

Best JavaScript code snippet using appium-xcuitest-driver

Run Appium Xcuitest Driver automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Sign up Free
_

com-color-picker.js

Source: com-color-picker.js Github

copy
1import './com-button.js';
2import './com-popover.js';
3import message from './com-message.js';
4import { rgbToHsv, hslToHsv, parseToHSVA } from '../color.js';
5import { HSVaColor } from '../hsvacolor.js';
6
7const Material_colors = ['#f44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3', '#03A9F4', '#15bbf2', '#00BCD4', '#009688', '#4CAF50', '#8BC34A',
8    '#CDDC39', '#FFEB3B', '#FFC107', '#FF9800', '#FF5722', '#795548', '#9E9E9E', '#607D8B', 'rgba(0,0,0,.65)', 'transparent']
9
10class ComColorPane extends HTMLElement {
11
12    constructor() {
13        super();
14        const shadowRoot = this.attachShadow({ mode: 'open' });
15        shadowRoot.innerHTML = `
16        <style>
17            :host{
18                display: block;
19                min-width: 300px;
20            }
21            .color-pane{
22                padding:.8em;
23            }
24            .color-palette{
25                position:relative;
26                height:150px;
27                background:linear-gradient(to top, hsla(0,0%,0%,calc(var(--a))), transparent), linear-gradient(to left, hsla(calc(var(--h)),100%,50%,calc(var(--a))),hsla(0,0%,100%,calc(var(--a)))),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
28                background-position:0 0, 0 0,0 0,5px 5px;
29                background-size:100% 100%, 100% 100%, 10px 10px, 10px 10px;
30                user-select: none;
31                cursor: crosshair;
32                opacity:1;
33                transition:opacity .1s;
34            }
35            .color-palette:active{
36                opacity:.99;
37            }
38            .color-palette::after{
39                pointer-events:none;
40                position:absolute;
41                content:'';
42                box-sizing:border-box;
43                width:10px;
44                height:10px;
45                border-radius:50%;
46                border:2px solid #fff;
47                left:calc(var(--s) * 1%);
48                top:calc((100 - var(--v)) * 1%);
49                transform:translate(-50%,-50%);
50            }
51            .color-chooser{
52                display:flex;
53                padding:10px 0;
54            }
55            .color-show{
56                display:flex;
57                position: relative;
58                width:32px;
59                height:32px;
60                background:var(--c);
61                transition:none;
62                border-radius:50%;
63                overflow:hidden;
64                cursor:pointer;
65            }
66            .color-show .icon-file{
67                width:1em;
68                height:1em;
69                margin: auto;
70                fill: hsl(0, 0%, calc( ((2 - var(--s) / 100) * var(--v) / 200 * var(--a) - 0.6 ) * -999999%  ));
71                opacity: 0;
72                transition: var(--transitionTime,.3s);
73            }
74            .color-show:hover .icon-file{
75                opacity:1;
76            }
77            .color-show input{
78                position:absolute;
79                clip:rect(0,0,0,0);
80            }
81            .color-show::after{
82                content:'';
83                position:absolute;
84                width:32px;
85                height:32px;
86                background:linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
87                background-position:0 0,5px 5px;
88                background-size:10px 10px;
89                z-index:-1;
90            }
91            .color-range{
92                flex:1;
93                margin-left:10px;
94            }
95            input[type="range"]{
96                display: block;
97                pointer-events:all;
98                width:100%;
99                -webkit-appearance: none;
100                outline : 0;
101                height: 10px;
102                border-radius:5px;
103                margin:0;
104            }
105            input[type="range"]::-webkit-slider-runnable-track{
106                display: flex;
107                align-items: center;
108                position: relative;
109            }
110            input[type="range"]::-webkit-slider-thumb{
111                -webkit-appearance: none;
112                position: relative;
113                width:10px;
114                height:10px;
115                transform:scale(1.2);
116                border-radius: 50%;
117                box-shadow: 0 0 10px rgba(0,0,0,0.1);
118                background:#fff;
119                transition:.2s cubic-bezier(.12, .4, .29, 1.46);
120            }
121            input[type="range"]::-moz-range-thumb{
122                box-sizing:border-box;
123                pointer-events:none;
124                position: relative;
125                width:10px;
126                height:10px;
127                transform:scale(1.2);
128                border-radius: 50%;
129                border:0;
130                box-shadow: 0 0 10px rgba(0,0,0,0.1);
131                background:#fff;
132                transition:.2s cubic-bezier(.12, .4, .29, 1.46);
133            }
134            input[type="range"]::-webkit-slider-thumb:active,
135            input[type="range"]:focus::-webkit-slider-thumb{
136                transform:scale(1.5);
137            }
138            input[type="range"]::-moz-range-thumb:active,
139            input[type="range"]:focus::-moz-range-thumb{
140                transform:scale(1.5);
141            }
142            input[type="range"]+input[type="range"]{
143                margin-top:10px;
144            }
145            .color-hue{
146                background:linear-gradient(to right, red, yellow, lime, cyan, blue, magenta, red)
147            }
148            .color-opacity{
149                background:linear-gradient(to right, hsla(calc(var(--h)),100%,50%,0), hsla(calc(var(--h)),100%,50%,1)),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
150                background-position:0 0,0 0,5px 5px;
151                background-size:100% 100%,10px 10px,10px 10px;
152            }
153            .color-label{
154                position:absolute;
155                display:flex;
156                visibility:hidden;
157                opacity:0;
158                left:0;
159                right:0;
160                top:0;
161                bottom:0;
162                transition: .3s;
163            }
164            .color-label input{
165                flex:1;
166                margin-right:.8em;
167                outline:0;
168                min-width:0;
169                width: 0;
170                border-radius:var(--borderRadius,.25em);
171                border:1px solid #ddd;
172                padding:0 5px;
173                line-height:28px;
174                text-align:center;
175                -moz-appearance: textfield;
176                transition:.3s;
177            }
178            input[type="number"]::-webkit-inner-spin-button{
179                display:none;
180            }
181            ::-moz-focus-inner,::-moz-focus-outer{
182                border:0;
183                outline : 0;
184            }
185            .color-label input:focus{
186                border-color:var(--themeColor,#15bbf2);
187            }
188            .color-footer{
189                display:flex
190            }
191            .btn-switch{
192                position:relative;
193                border-radius:var(--borderRadius,.25em);
194                background:none;
195                border:0;
196                outline:0;
197                line-height:30px;
198                width: 60px;
199                padding: 0;
200                color:var(--themeColor,#15bbf2);
201                overflow:hidden;
202            }
203            .btn-switch::before{
204                content:'';
205                position:absolute;
206                left:0;
207                top:0;
208                right:0;
209                bottom:0;
210                background:var(--themeBackground,var(--themeColor,#15bbf2));
211                opacity:.2;
212                transition:.3s;
213            }
214            .btn-switch:hover::before,.btn-switch:focus::before{
215                opacity:.3;
216            }
217            .color-input{
218                position:relative;
219                flex:1;
220                height:30px;
221                overflow:hidden;
222            }
223            .color-footer[data-type="HEXA"] .color-label:nth-child(1),
224            .color-footer[data-type="RGBA"] .color-label:nth-child(2),
225            .color-footer[data-type="HSLA"] .color-label:nth-child(3){
226                opacity:1;
227                visibility:inherit;
228                z-index:2;
229            }
230            .color-sign{
231                padding-top:10px;
232                display:grid;
233                grid-template-columns: repeat(auto-fit, minmax(15px, 1fr));
234                grid-gap: 10px;
235            }
236            .color-sign>button{
237                position:relative;
238                cursor:pointer;
239                width:100%;
240                padding-bottom:0;
241                padding-top:100%;
242                border-radius:4px;
243                border:0;
244                outline:0;
245            }
246            .color-sign>button::before{
247                content:'';
248                position:absolute;
249                left:0;
250                top:0;
251                width:100%;
252                height:100%;
253                z-index:-1;
254                background:linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
255                background-position:0 0,5px 5px;
256                background-size:10px 10px;
257                border-radius: 4px;
258            }
259            .color-sign>button::after{
260                content:'';
261                position:absolute;
262                opacity:.5;
263                z-index:-2;
264                left:0;
265                top:0;
266                width:100%;
267                height:100%;
268                background:inherit;
269                border-radius:4px;
270                transition:.3s;
271            }
272            .color-sign>button:hover::after,.color-sign>button:focus::after{
273                transform:translate(2px,2px)
274            }
275        </style>
276        <div class="color-pane" id="color-pane">
277            <div class="color-palette" id="color-palette"></div>
278            <div class="color-chooser">
279                <a class="color-show" id="copy-btn"><svg class="icon-file" viewBox="0 0 1024 1024"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32z"></path><path d="M704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg><input></a>
280                <div class="color-range">
281                    <input class="color-hue" value="0" min="0" max="360" type="range" id="range-hue">
282                    <input class="color-opacity" value="1" min="0" max="1" step="0.01" type="range" id="range-opacity">
283                </div>
284            </div>
285            <div class="color-footer" data-type="HEXA">
286                <div class="color-input">
287                    <div class="color-label" id="color-hexa">
288                        <input spellcheck="false" />
289                    </div>
290                    <div class="color-label" id="color-rgba">
291                        <input type="number" min="0" max="255" spellcheck="false" />
292                        <input type="number" min="0" max="255" spellcheck="false" />
293                        <input type="number" min="0" max="255" spellcheck="false" />
294                        <input type="number" min="0" max="1" step="0.01" spellcheck="false" />
295                    </div>
296                    <div class="color-label" id="color-hlsa">
297                        <input type="number" min="0" max="360" spellcheck="false" />
298                        <input type="number" min="0" max="100" spellcheck="false" />
299                        <input type="number" min="0" max="100" spellcheck="false" />
300                        <input type="number" min="0" max="1" step="0.01" spellcheck="false" />
301                    </div>
302                </div>
303                <button class="btn-switch" id="btn-switch" type="flat">HEXA</button>
304            </div>
305            <div class="color-sign" id="colors">
306                ${
307            Material_colors.map(el => '<button style="background-color:' + el + '" data-color=' + el + '></button>').join('')
308            }
309            </div>
310        </div>
311        `
312    }
313
314    choose(ev) {
315        const { x, y, width: w, height: h } = this.palette.getBoundingClientRect();
316        const value = [...this.$value];
317        const _x = Math.min(Math.max(0, (ev.clientX - x) / w * 100), 100);
318        const _y = Math.min(Math.max(0, (ev.clientY - y) / h * 100), 100);
319        value[1] = _x;
320        value[2] = 100 - _y;
321        this.value = `hsva(${value[0]}, ${value[1]}%, ${value[2]}%, ${value[3]})`;
322    }
323
324    connectedCallback() {
325        this.type = ['HEXA', 'RGBA', 'HSLA'];
326        this.typeindex = 0;
327        this.palette = this.shadowRoot.getElementById('color-palette');
328        this.colors = this.shadowRoot.getElementById('colors');
329        this.pane = this.shadowRoot.getElementById('color-pane');
330        this.rangeHue = this.shadowRoot.getElementById('range-hue');
331        this.rangeOpacity = this.shadowRoot.getElementById('range-opacity');
332        this.copyBtn = this.shadowRoot.getElementById('copy-btn');
333        this.copyinfo = this.copyBtn.querySelector('input');
334        this.switch = this.shadowRoot.getElementById('btn-switch');
335        this.colorHexa = this.shadowRoot.getElementById('color-hexa').querySelectorAll('input');
336        this.colorRgba = this.shadowRoot.getElementById('color-rgba').querySelectorAll('input');
337        this.colorHlsa = this.shadowRoot.getElementById('color-hlsa').querySelectorAll('input');
338        this.value = this.defaultvalue;
339        this.rangeHue.addEventListener('input', () => {
340            const value = [...this.$value];
341            value[0] = Number(this.rangeHue.value);
342            this.nativeclick = true;
343            this.value = `hsva(${value[0]}, ${value[1]}%, ${value[2]}%, ${value[3]})`;
344        })
345        this.palette.addEventListener('mousedown', (ev) => {
346            this.start = true;
347            this.choose(ev);
348        })
349        document.addEventListener('mousemove', (ev) => {
350            if (this.start) {
351                this.choose(ev);
352            }
353        })
354        document.addEventListener('mouseup', (ev) => {
355            if (getComputedStyle(this.palette).opacity !== 1 && this.start) {
356                this.dispatchEvent(new CustomEvent('change', {
357                    detail: {
358                        value: this.value,
359                        color: this.color
360                    }
361                }));
362            }
363            this.start = false;
364        })
365        this.rangeOpacity.addEventListener('input', () => {
366            const value = [...this.$value];
367            value[3] = Number(this.rangeOpacity.value);
368            this.nativeclick = true;
369            this.value = `hsva(${value[0]}, ${value[1]}%, ${value[2]}%, ${value[3]})`;
370        })
371        this.colors.addEventListener('click', (ev) => {
372            const item = ev.target.closest('button');
373            if (item) {
374                this.nativeclick = true;
375                this.value = item.dataset.color;
376            }
377        })
378        this.switch.addEventListener('click', () => {
379            this.typeindex++;
380            this.typeindex %= 3;
381            this.switch.textContent = this.type[this.typeindex];
382            this.nativeclick = true;
383            this.value = this.value;
384            this.switch.parentNode.dataset.type = this.type[this.typeindex];
385        })
386        this.copyBtn.addEventListener('click', () => {
387            this.copyinfo.select();
388            if (document.execCommand('copy')) {
389                document.execCommand('copy');
390                message.success(this.value);
391            }
392        })
393        this.colorHexa.forEach(el => {
394            el.addEventListener('change', () => {
395                this.nativeclick = true;
396                this.value = el.value;
397            })
398        })
399        this.colorRgba.forEach((el, i) => {
400            el.addEventListener('change', () => {
401                const value = HSVaColor(...this.$value).toRGBA();
402                value[i] = Number(el.value);
403                this.nativeclick = true;
404                this.value = `rgba(${value[0]}, ${value[1]}, ${value[2]}, ${value[3]})`;
405            })
406        })
407        this.colorHlsa.forEach((el, i) => {
408            el.addEventListener('change', () => {
409                const value = HSVaColor(...this.$value).toHSLA();
410                value[i] = Number(el.value);
411                this.nativeclick = true;
412                this.value = `hsla(${value[0]}, ${value[1]}%, ${value[2]}%, ${value[3]})`;
413            })
414        })
415    }
416
417    get value() {
418        return HSVaColor(...this.$value)['to' + this.type[this.typeindex]]().toString();
419    }
420
421    get color() {
422        return HSVaColor(...this.$value);
423    }
424
425    get defaultvalue() {
426        return this.getAttribute('defaultvalue') || '#ff0000';
427    }
428
429    set defaultvalue(value) {
430        this.setAttribute("defaultvalue", value);
431    }
432
433    set value(value) {
434        this.$value = parseToHSVA(value).values;
435        //[h,s,v,a]
436        const [h, s, v, a = 1] = this.$value;
437        this.pane.style.setProperty('--h', h);
438        this.pane.style.setProperty('--s', s);
439        this.pane.style.setProperty('--v', v);
440        this.pane.style.setProperty('--a', a);
441        this.pane.style.setProperty('--c', this.value);
442        this.copyinfo.value = this.value;
443        this.rangeHue.value = h;
444        this.rangeOpacity.value = a.toFixed(2);
445        const COLOR = HSVaColor(...this.$value);
446        this.colorHexa[0].value = COLOR.toHEXA().toString();
447        const RGBA = COLOR.toRGBA();
448        this.colorRgba[0].value = RGBA[0].toFixed(0);
449        this.colorRgba[1].value = RGBA[1].toFixed(0);
450        this.colorRgba[2].value = RGBA[2].toFixed(0);
451        this.colorRgba[3].value = RGBA[3].toFixed(2);
452        const HSLA = COLOR.toHSLA();
453        this.colorHlsa[0].value = HSLA[0].toFixed(0);
454        this.colorHlsa[1].value = HSLA[1].toFixed(0);
455        this.colorHlsa[2].value = HSLA[2].toFixed(0);
456        this.colorHlsa[3].value = HSLA[3].toFixed(2);
457        if (this.nativeclick) {
458            this.nativeclick = false;
459            this.dispatchEvent(new CustomEvent('change', {
460                detail: {
461                    value: this.value,
462                    color: this.color
463                }
464            }));
465        }
466    }
467
468}
469
470customElements.define('com-color-pane', ComColorPane);
471
472export default class ComColorPicker extends HTMLElement {
473
474    static get observedAttributes() { return ['disabled', 'dir'] }
475
476    constructor() {
477        super();
478        const shadowRoot = this.attachShadow({ mode: 'open' });
479
480        shadowRoot.innerHTML = `
481        <style>
482        :host{
483            display:inline-block;
484            width:30px;
485            height:30px;
486            font-size:14px;
487        }
488        :host([block]){
489            display:block;
490        }
491
492        :host([disabled]){
493            pointer-events:none;
494        }
495        
496        :host(:focus-within) com-popover,:host(:hover) com-popover{ 
497            z-index: 2;
498        }
499        com-popover{
500            width:100%;
501            height:100%;
502        }
503        .color-btn{
504            width:100%;
505            height:100%;
506            padding:5px;
507            background-clip: content-box;
508            background-color:var(--themeColor,#15bbf2);
509        }
510        .color-btn:hover{
511            z-index: auto;
512        }
513        com-popover{
514            display:block;
515        }
516        com-popcon{
517            min-width:100%;
518        }
519        .pop-footer{
520            display:flex;
521            justify-content:flex-end;
522            padding:0 .8em .8em;
523        }
524        .pop-footer com-button{
525            font-size: .8em;
526            margin-left: .8em;
527        }
528        .color-btn::before{
529            content:'';
530            position:absolute;
531            left:5px;
532            top:5px;
533            right:5px;
534            bottom:5px;
535            z-index:-1;
536            background:linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
537            background-position:0 0,5px 5px;
538            background-size:10px 10px;
539        }
540        </style>
541        <com-popover id="popover" ${this.dir ? "dir='" + this.dir + "'" : ""}>
542            <com-button class="color-btn" id="color-btn" ${this.disabled ? "disabled" : ""}></com-button>
543            <com-popcon id="popcon">
544                <div class="pop-footer">
545                    <com-button autoclose>取 消</com-button>
546                    <com-button type="primary" id="btn-submit" autoclose>确 认</com-button>
547                </div>
548            </com-popcon>
549        </com-popover>
550        `
551    }
552
553    focus() {
554        this.colorBtn.focus();
555    }
556
557    connectedCallback() {
558        this.popover = this.shadowRoot.getElementById('popover');
559        this.popcon = this.shadowRoot.getElementById('popcon');
560        this.colorBtn = this.shadowRoot.getElementById('color-btn');
561        this.btnSubmit = this.shadowRoot.getElementById('btn-submit');
562        this.colorBtn.addEventListener('click', () => {
563            if (!this.colorPane) {
564                this.colorPane = new ComColorPane();
565                this.colorPane.defaultvalue = this.defaultvalue;
566                this.popcon.prepend(this.colorPane);
567            }
568        })
569        this.btnSubmit.addEventListener('click', () => {
570            this.nativeclick = true;
571            this.value = this.colorPane.value;
572        })
573        this.popcon.addEventListener('close', () => {
574            this.colorPane.value = this.value;
575        })
576        this.value = this.defaultvalue;
577    }
578
579
580
581    get defaultvalue() {
582        return this.getAttribute('defaultvalue') || '#15bbf2';
583    }
584
585    get value() {
586        return this.$value;
587    }
588
589    get color() {
590        return HSVaColor(...parseToHSVA(this.$value).values);
591    }
592
593    get type() {
594        return this.getAttribute('type');
595    }
596
597    get disabled() {
598        return this.getAttribute('disabled') !== null;
599    }
600
601    get dir() {
602        return this.getAttribute('dir');
603    }
604
605    set dir(value) {
606        this.setAttribute('dir', value);
607    }
608
609    set disabled(value) {
610        if (value === null || value === false) {
611            this.removeAttribute('disabled');
612        } else {
613            this.setAttribute('disabled', '');
614        }
615    }
616
617    set defaultvalue(value) {
618        this.setAttribute('defaultvalue', value);
619    }
620
621    set value(value) {
622        this.colorBtn.style.setProperty('--themeColor', value);
623        this.$value = value;
624        if (this.nativeclick) {
625            this.nativeclick = false;
626            this.dispatchEvent(new CustomEvent('change', {
627                detail: {
628                    value: this.value,
629                    color: this.color
630                }
631            }));
632        } else {
633            if (this.colorPane) {
634                this.colorPane.value = this.value;
635            } else {
636                this.defaultvalue = this.value;
637            }
638        }
639    }
640
641    attributeChangedCallback(name, oldValue, newValue) {
642        if (name == 'disabled' && this.colorBtn) {
643            if (newValue != null) {
644                this.colorBtn.setAttribute('disabled', 'disabled');
645            } else {
646                this.colorBtn.removeAttribute('disabled');
647            }
648        }
649        if (name == 'dir' && this.popover) {
650            if (newValue != null) {
651                this.popover.dir = newValue;
652            }
653        }
654    }
655}
656
657if (!customElements.get('com-color-picker')) {
658    customElements.define('com-color-picker', ComColorPicker);
659}
Full Screen

wc-color-picker.js

Source: wc-color-picker.js Github

copy
1import './wc-button.js';
2import './wc-popover.js';
3import message from './wc-message.js';
4import { rgbToHsv,hslToHsv,parseToHSVA } from '../utils/color.js';
5import { HSVaColor } from '../utils/hsvacolor.js';
6
7const Material_colors = ['#f44336','#E91E63','#9C27B0','#673AB7','#3F51B5','#2196F3','#03A9F4','#00BCD4','#009688','#4CAF50','#8BC34A','#CDDC39','#FFEB3B','#FFC107','#FF9800','#FF5722','#795548','#9E9E9E','#607D8B','rgba(0,0,0,.65)','transparent']
8
9class WcColorPane extends HTMLElement {
10
11    constructor() {
12        super();
13        const shadowRoot = this.attachShadow({ mode: 'open' });
14        shadowRoot.innerHTML = `
15        <style>
16            :host{
17                display: block;
18                min-width: 300px;
19            }
20            .color-pane{
21                padding:.8em;
22            }
23            .color-palette{
24                position:relative;
25                height:150px;
26                background:linear-gradient(to top, hsla(0,0%,0%,calc(var(--a))), transparent), linear-gradient(to left, hsla(calc(var(--h)),100%,50%,calc(var(--a))),hsla(0,0%,100%,calc(var(--a)))),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
27                background-position:0 0, 0 0,0 0,5px 5px;
28                background-size:100% 100%, 100% 100%, 10px 10px, 10px 10px;
29                user-select: none;
30                cursor: crosshair;
31                opacity:1;
32                transition:opacity .1s;
33            }
34            .color-palette:active{
35                opacity:.99;
36            }
37            .color-palette::after{
38                pointer-events:none;
39                position:absolute;
40                content:'';
41                box-sizing:border-box;
42                width:10px;
43                height:10px;
44                border-radius:50%;
45                border:2px solid #fff;
46                left:calc(var(--s) * 1%);
47                top:calc((100 - var(--v)) * 1%);
48                transform:translate(-50%,-50%);
49            }
50            .color-chooser{
51                display:flex;
52                padding:10px 0;
53            }
54            .color-show{
55                display:flex;
56                position: relative;
57                width:32px;
58                height:32px;
59                background:var(--c);
60                transition:none;
61                border-radius:50%;
62                overflow:hidden;
63                cursor:pointer;
64            }
65            .color-show .icon-file{
66                width:1em;
67                height:1em;
68                margin: auto;
69                fill: hsl(0, 0%, calc( ((2 - var(--s) / 100) * var(--v) / 200 * var(--a) - 0.6 ) * -999999%  ));
70                opacity: 0;
71                transition: .3s;
72            }
73            .color-show:hover .icon-file{
74                opacity:1;
75            }
76            .color-show input{
77                position:absolute;
78                clip:rect(0,0,0,0);
79            }
80            .color-show::after{
81                content:'';
82                position:absolute;
83                width:32px;
84                height:32px;
85                background:linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
86                background-position:0 0,5px 5px;
87                background-size:10px 10px;
88                z-index:-1;
89            }
90            .color-range{
91                flex:1;
92                margin-left:10px;
93            }
94            input[type="range"]{
95                display: block;
96                pointer-events:all;
97                width:100%;
98                -webkit-appearance: none;
99                outline : 0;
100                height: 10px;
101                border-radius:5px;
102                margin:0;
103            }
104            input[type="range"]::-webkit-slider-runnable-track{
105                display: flex;
106                align-items: center;
107                position: relative;
108            }
109            input[type="range"]::-webkit-slider-thumb{
110                -webkit-appearance: none;
111                position: relative;
112                width:10px;
113                height:10px;
114                transform:scale(1.2);
115                border-radius: 50%;
116                box-shadow: 0 0 10px rgba(0,0,0,0.1);
117                background:#fff;
118                transition:.2s cubic-bezier(.12, .4, .29, 1.46);
119            }
120            input[type="range"]::-moz-range-thumb{
121                box-sizing:border-box;
122                pointer-events:none;
123                position: relative;
124                width:10px;
125                height:10px;
126                transform:scale(1.2);
127                border-radius: 50%;
128                border:0;
129                box-shadow: 0 0 10px rgba(0,0,0,0.1);
130                background:#fff;
131                transition:.2s cubic-bezier(.12, .4, .29, 1.46);
132            }
133            input[type="range"]::-webkit-slider-thumb:active,
134            input[type="range"]:focus::-webkit-slider-thumb{
135                transform:scale(1.5);
136            }
137            input[type="range"]::-moz-range-thumb:active,
138            input[type="range"]:focus::-moz-range-thumb{
139                transform:scale(1.5);
140            }
141            input[type="range"]+input[type="range"]{
142                margin-top:10px;
143            }
144            .color-hue{
145                background:linear-gradient(to right, red, yellow, lime, cyan, blue, magenta, red)
146            }
147            .color-opacity{
148                background:linear-gradient(to right, hsla(calc(var(--h)),100%,50%,0), hsla(calc(var(--h)),100%,50%,1)),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
149                background-position:0 0,0 0,5px 5px;
150                background-size:100% 100%,10px 10px,10px 10px;
151            }
152            .color-label{
153                position:absolute;
154                display:flex;
155                visibility:hidden;
156                opacity:0;
157                left:0;
158                right:0;
159                top:0;
160                bottom:0;
161                transition: .3s;
162            }
163            .color-label input{
164                flex:1;
165                margin-right:.8em;
166                outline:0;
167                min-width:0;
168                width: 0;
169                border-radius:var(--borderRadius,.25em);
170                border:1px solid #ddd;
171                padding:0 5px;
172                line-height:28px;
173                text-align:center;
174                -moz-appearance: textfield;
175                transition:.3s;
176            }
177            input[type="number"]::-webkit-inner-spin-button{
178                display:none;
179            }
180            ::-moz-focus-inner,::-moz-focus-outer{
181                border:0;
182                outline : 0;
183            }
184            .color-label input:focus{
185                border-color:var(--themeColor,#42b983);
186            }
187            .color-footer{
188                display:flex
189            }
190            .btn-switch{
191                position:relative;
192                border-radius:var(--borderRadius,.25em);
193                background:none;
194                border:0;
195                outline:0;
196                line-height:30px;
197                width: 60px;
198                padding: 0;
199                color:var(--themeColor,#42b983);
200                overflow:hidden;
201            }
202            .btn-switch::before{
203                content:'';
204                position:absolute;
205                left:0;
206                top:0;
207                right:0;
208                bottom:0;
209                background:var(--themeBackground,var(--themeColor,#42b983));
210                opacity:.2;
211                transition:.3s;
212            }
213            .btn-switch:hover::before,.btn-switch:focus::before{
214                opacity:.3;
215            }
216            .color-input{
217                position:relative;
218                flex:1;
219                height:30px;
220                overflow:hidden;
221            }
222            .color-footer[data-type="HEXA"] .color-label:nth-child(1),
223            .color-footer[data-type="RGBA"] .color-label:nth-child(2),
224            .color-footer[data-type="HSLA"] .color-label:nth-child(3){
225                opacity:1;
226                visibility:inherit;
227                z-index:2;
228            }
229            .color-sign{
230                padding-top:10px;
231                display:grid;
232                grid-template-columns: repeat(auto-fit, minmax(15px, 1fr));
233                grid-gap: 10px;
234            }
235            .color-sign>button{
236                position:relative;
237                cursor:pointer;
238                width:100%;
239                padding-bottom:0;
240                padding-top:100%;
241                border-radius:4px;
242                border:0;
243                outline:0;
244            }
245            .color-sign>button::before{
246                content:'';
247                position:absolute;
248                left:0;
249                top:0;
250                width:100%;
251                height:100%;
252                z-index:-1;
253                background:linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
254                background-position:0 0,5px 5px;
255                background-size:10px 10px;
256                border-radius: 4px;
257            }
258            .color-sign>button::after{
259                content:'';
260                position:absolute;
261                opacity:.5;
262                z-index:-2;
263                left:0;
264                top:0;
265                width:100%;
266                height:100%;
267                background:inherit;
268                border-radius:4px;
269                transition:.3s;
270            }
271            .color-sign>button:hover::after,.color-sign>button:focus::after{
272                transform:translate(2px,2px)
273            }
274        </style>
275        <div class="color-pane" id="color-pane">
276            <div class="color-palette" id="color-palette"></div>
277            <div class="color-chooser">
278                <a class="color-show" id="copy-btn"><svg class="icon-file" viewBox="0 0 1024 1024"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32z"></path><path d="M704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg><input></a>
279                <div class="color-range">
280                    <input class="color-hue" value="0" min="0" max="360" type="range" id="range-hue">
281                    <input class="color-opacity" value="1" min="0" max="1" step="0.01" type="range" id="range-opacity">
282                </div>
283            </div>
284            <div class="color-footer" data-type="HEXA">
285                <div class="color-input">
286                    <div class="color-label" id="color-hexa">
287                        <input spellcheck="false" />
288                    </div>
289                    <div class="color-label" id="color-rgba">
290                        <input type="number" min="0" max="255" spellcheck="false" />
291                        <input type="number" min="0" max="255" spellcheck="false" />
292                        <input type="number" min="0" max="255" spellcheck="false" />
293                        <input type="number" min="0" max="1" step="0.01" spellcheck="false" />
294                    </div>
295                    <div class="color-label" id="color-hlsa">
296                        <input type="number" min="0" max="360" spellcheck="false" />
297                        <input type="number" min="0" max="100" spellcheck="false" />
298                        <input type="number" min="0" max="100" spellcheck="false" />
299                        <input type="number" min="0" max="1" step="0.01" spellcheck="false" />
300                    </div>
301                </div>
302                <button class="btn-switch" id="btn-switch" type="flat">HEXA</button>
303            </div>
304            <div class="color-sign" id="colors">
305                ${
306                    Material_colors.map(el=>'<button style="background-color:'+el+'" data-color='+el+'></button>').join('')
307                }
308            </div>
309        </div>
310        `
311    }
312
313    choose(ev){
314        const {x,y,width:w,height:h} = this.palette.getBoundingClientRect();
315        const value = [...this.$value];
316        const _x = Math.min(Math.max(0,(ev.clientX-x)/w*100),100);
317        const _y = Math.min(Math.max(0,(ev.clientY-y)/h*100),100);
318        value[1] = _x;
319        value[2] = 100-_y;
320        this.value = `hsva(${value[0]}, ${value[1]}%, ${value[2]}%, ${value[3]})`;
321    }
322
323    connectedCallback() {
324        this.type = ['HEXA','RGBA','HSLA'];
325        this.typeindex = 0;
326        this.palette = this.shadowRoot.getElementById('color-palette');
327        this.colors = this.shadowRoot.getElementById('colors');
328        this.pane = this.shadowRoot.getElementById('color-pane');
329        this.rangeHue = this.shadowRoot.getElementById('range-hue');
330        this.rangeOpacity = this.shadowRoot.getElementById('range-opacity');
331        this.copyBtn = this.shadowRoot.getElementById('copy-btn');
332        this.copyinfo = this.copyBtn.querySelector('input');
333        this.switch = this.shadowRoot.getElementById('btn-switch');
334        this.colorHexa = this.shadowRoot.getElementById('color-hexa').querySelectorAll('input');
335        this.colorRgba = this.shadowRoot.getElementById('color-rgba').querySelectorAll('input');
336        this.colorHlsa = this.shadowRoot.getElementById('color-hlsa').querySelectorAll('input');
337        this.value = this.defaultvalue;
338        this.rangeHue.addEventListener('input',()=>{
339            const value = [...this.$value];
340            value[0] = Number(this.rangeHue.value);
341            this.nativeclick = true;
342            this.value = `hsva(${value[0]}, ${value[1]}%, ${value[2]}%, ${value[3]})`;
343        })
344        this.palette.addEventListener('mousedown',(ev)=>{
345            this.start = true;
346            this.choose(ev);
347        })
348        document.addEventListener('mousemove',this.mousemove);
349
350        document.addEventListener('mouseup',this.mouseup);
351        this.rangeOpacity.addEventListener('input',()=>{
352            const value = [...this.$value];
353            value[3] = Number(this.rangeOpacity.value);
354            this.nativeclick = true;
355            this.value = `hsva(${value[0]}, ${value[1]}%, ${value[2]}%, ${value[3]})`;
356        })
357        this.colors.addEventListener('click',(ev)=>{
358            const item = ev.target.closest('button');
359            if(item){
360                this.nativeclick = true;
361                this.value = item.dataset.color;
362            }
363        })
364        this.switch.addEventListener('click',()=>{
365            this.typeindex ++;
366            this.typeindex %= 3;
367            this.switch.textContent = this.type[this.typeindex];
368            this.nativeclick = true;
369            this.value = this.value;
370            this.switch.parentNode.dataset.type = this.type[this.typeindex];
371        })
372        this.copyBtn.addEventListener('click',()=>{
373            this.copyinfo.select();
374            if (document.execCommand('copy')) {
375                document.execCommand('copy');
376                message.success(this.value);
377            }
378        })
379        this.colorHexa.forEach(el=>{
380            el.addEventListener('change',()=>{
381                this.nativeclick = true;
382                this.value = el.value;
383            })
384        })
385        this.colorRgba.forEach((el,i)=>{
386            el.addEventListener('change',()=>{
387                const value = HSVaColor(...this.$value).toRGBA();
388                value[i] = Number(el.value);
389                this.nativeclick = true;
390                this.value = `rgba(${value[0]}, ${value[1]}, ${value[2]}, ${value[3]})`;
391            })
392        })
393        this.colorHlsa.forEach((el,i)=>{
394            el.addEventListener('change',()=>{
395                const value = HSVaColor(...this.$value).toHSLA();
396                value[i] = Number(el.value);
397                this.nativeclick = true;
398                this.value = `hsla(${value[0]}, ${value[1]}%, ${value[2]}%, ${value[3]})`;
399            })
400        })
401    }
402
403    mousemove = (ev) => {
404        if(this.start){
405            this.choose(ev);
406        }
407    }
408
409    mouseup = () => {
410        if(getComputedStyle(this.palette).opacity!==1 && this.start){
411            this.dispatchEvent(new CustomEvent('change', {
412                detail: {
413                    value: this.value,
414                    color: this.color
415                }
416            }));
417        }
418        this.start = false;
419    }
420
421    disconnectedCallback() {
422        document.removeEventListener('mousemove', this.mousemove);
423        document.removeEventListener('mouseup', this.mouseup);
424    }
425
426    get value() {
427        return HSVaColor(...this.$value)['to'+this.type[this.typeindex]]().toString();
428    }
429
430    get color() {
431        return HSVaColor(...this.$value);
432    }
433
434    get defaultvalue() {
435        return this.getAttribute('defaultvalue')||'#ff0000';
436    }
437
438    set defaultvalue(value) {
439        this.setAttribute("defaultvalue",value);
440    }
441
442    set value(value) {
443        this.$value = parseToHSVA(value).values;
444        //[h,s,v,a]
445        const [h,s,v,a=1] = this.$value;
446        this.pane.style.setProperty('--h',h);
447        this.pane.style.setProperty('--s',s);
448        this.pane.style.setProperty('--v',v);
449        this.pane.style.setProperty('--a',a);
450        this.pane.style.setProperty('--c',this.value);
451        this.copyinfo.value = this.value;
452        this.rangeHue.value = h;
453        this.rangeOpacity.value = a.toFixed(2);
454        const COLOR = HSVaColor(...this.$value);
455        this.colorHexa[0].value = COLOR.toHEXA().toString();
456        const RGBA = COLOR.toRGBA();
457        this.colorRgba[0].value = RGBA[0].toFixed(0);
458        this.colorRgba[1].value = RGBA[1].toFixed(0);
459        this.colorRgba[2].value = RGBA[2].toFixed(0);
460        this.colorRgba[3].value = RGBA[3].toFixed(2);
461        const HSLA = COLOR.toHSLA();
462        this.colorHlsa[0].value = HSLA[0].toFixed(0);
463        this.colorHlsa[1].value = HSLA[1].toFixed(0);
464        this.colorHlsa[2].value = HSLA[2].toFixed(0);
465        this.colorHlsa[3].value = HSLA[3].toFixed(2);
466        if(this.nativeclick){
467            this.nativeclick = false;
468            this.dispatchEvent(new CustomEvent('change', {
469                detail: {
470                    value: this.value,
471                    color: this.color
472                }
473            }));
474        }
475    }
476
477}
478
479if(!customElements.get('wc-color-pane')){
480    customElements.define('wc-color-pane', WcColorPane);
481}
482
483export default class WcColorPicker extends HTMLElement {
484
485    static get observedAttributes() { return ['disabled','dir'] }
486
487    constructor() {
488        super();
489        const shadowRoot = this.attachShadow({ mode: 'open' });
490
491        shadowRoot.innerHTML = `
492        <style>
493        :host{
494            display:inline-block;
495            width:30px;
496            height:30px;
497            font-size:14px;
498        }
499        :host([block]){
500            display:block;
501        }
502
503        :host([disabled]){
504            pointer-events:none;
505        }
506        
507        :host(:focus-within) wc-popover,:host(:hover) wc-popover{ 
508            z-index: 2;
509        }
510        wc-popover{
511            width:100%;
512            height:100%;
513        }
514        .color-btn{
515            width:100%;
516            height:100%;
517            padding:5px;
518            background-clip: content-box;
519            background-color:var(--themeColor,#42b983);
520        }
521        .color-btn:hover{
522            z-index: auto;
523        }
524        wc-popover{
525            display:block;
526        }
527        wc-popcon{
528            min-width:100%;
529        }
530        .pop-footer{
531            display:flex;
532            justify-content:flex-end;
533            padding:0 .8em .8em;
534        }
535        .pop-footer wc-button{
536            font-size: .8em;
537            margin-left: .8em;
538        }
539        .color-btn::before{
540            content:'';
541            position:absolute;
542            left:5px;
543            top:5px;
544            right:5px;
545            bottom:5px;
546            z-index:-1;
547            background:linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
548            background-position:0 0,5px 5px;
549            background-size:10px 10px;
550        }
551        </style>
552        <wc-popover id="popover" ${this.dir? "dir='"+this.dir+"'" : ""}>
553            <wc-button class="color-btn" id="color-btn" ${this.disabled? "disabled" : ""}></wc-button>
554            <wc-popcon id="popcon">
555                <div class="pop-footer">
556                    <wc-button autoclose>取 消</wc-button>
557                    <wc-button type="primary" id="btn-submit" autoclose>确 认</wc-button>
558                </div>
559            </wc-popcon>
560        </wc-popover>
561        `
562    }
563
564    focus() {
565        this.colorBtn.focus();
566    }
567
568    connectedCallback() {
569        this.popover = this.shadowRoot.getElementById('popover');
570        this.popcon = this.shadowRoot.getElementById('popcon');
571        this.colorBtn = this.shadowRoot.getElementById('color-btn');
572        this.btnSubmit = this.shadowRoot.getElementById('btn-submit');
573        this.colorBtn.addEventListener('click',()=>{
574            if(!this.colorPane){
575                this.colorPane = new WcColorPane();
576                this.colorPane.defaultvalue = this.defaultvalue;
577                this.popcon.prepend(this.colorPane);
578            }
579        })
580        this.btnSubmit.addEventListener('click',()=>{
581            this.nativeclick = true;
582            this.value = this.colorPane.value;
583        })
584        this.popcon.addEventListener('close',()=>{
585            this.colorPane.value = this.value;
586        })
587        this.value = this.defaultvalue;
588    }
589
590    
591
592    get defaultvalue() {
593        return this.getAttribute('defaultvalue')||'#42b983';
594    }
595
596    get value() {
597        return this.$value;
598    }
599
600    get color() {
601        return HSVaColor(...parseToHSVA(this.$value).values);
602    }
603
604    get type() {
605        return this.getAttribute('type');
606    }
607
608    get disabled() {
609        return this.getAttribute('disabled')!==null;
610    }
611
612    get dir() {
613        return this.getAttribute('dir');
614    }
615
616    set dir(value){
617        this.setAttribute('dir', value);
618    }
619
620    set disabled(value) {
621        if (value === null || value === false) {
622            this.removeAttribute('disabled');
623        } else {
624            this.setAttribute('disabled', '');
625        }
626    }
627
628    set defaultvalue(value){
629        this.setAttribute('defaultvalue', value);
630    }
631
632    set value(value) {
633        this.colorBtn.style.setProperty('--themeColor',value);
634        this.$value = value;
635        if(this.nativeclick){
636            this.nativeclick = false;
637            this.dispatchEvent(new CustomEvent('change', {
638                detail: {
639                    value: this.value,
640                    color: this.color
641                }
642            }));
643        }else{
644            if(this.colorPane){
645                this.colorPane.value = this.value;
646            }else{
647                this.defaultvalue = this.value;
648            }
649        }
650    }
651
652    attributeChangedCallback(name, oldValue, newValue) {
653        if (name == 'disabled' && this.colorBtn) {
654            if (newValue != null) {
655                this.colorBtn.setAttribute('disabled', 'disabled');
656            } else {
657                this.colorBtn.removeAttribute('disabled');
658            }
659        }
660        if (name == 'dir' && this.popover) {
661            if (newValue != null) {
662                this.popover.dir = newValue;
663            }
664        }
665    }
666}
667
668if (!customElements.get('wc-color-picker')) {
669    customElements.define('wc-color-picker', WcColorPicker);
670}
Full Screen

xy-color-picker.js

Source: xy-color-picker.js Github

copy
1import './xy-button.js';
2import './xy-popover.js';
3import message from './xy-message.js';
4import { rgbToHsv,hslToHsv,parseToHSVA } from '../utils/color.js';
5import { HSVaColor } from '../utils/hsvacolor.js';
6
7const Material_colors = ['#f44336','#E91E63','#9C27B0','#673AB7','#3F51B5','#2196F3','#03A9F4','#00BCD4','#009688','#4CAF50','#8BC34A','#CDDC39','#FFEB3B','#FFC107','#FF9800','#FF5722','#795548','#9E9E9E','#607D8B','rgba(0,0,0,.65)','transparent']
8
9class XyColorPane extends HTMLElement {
10
11    constructor() {
12        super();
13        const shadowRoot = this.attachShadow({ mode: 'open' });
14        shadowRoot.innerHTML = `
15        <style>
16            :host{
17                display: block;
18                min-width: 300px;
19            }
20            .color-pane{
21                padding:.8em;
22            }
23            .color-palette{
24                position:relative;
25                height:150px;
26                background:linear-gradient(to top, hsla(0,0%,0%,calc(var(--a))), transparent), linear-gradient(to left, hsla(calc(var(--h)),100%,50%,calc(var(--a))),hsla(0,0%,100%,calc(var(--a)))),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
27                background-position:0 0, 0 0,0 0,5px 5px;
28                background-size:100% 100%, 100% 100%, 10px 10px, 10px 10px;
29                user-select: none;
30                cursor: crosshair;
31                opacity:1;
32                transition:opacity .1s;
33            }
34            .color-palette:active{
35                opacity:.99;
36            }
37            .color-palette::after{
38                pointer-events:none;
39                position:absolute;
40                content:'';
41                box-sizing:border-box;
42                width:10px;
43                height:10px;
44                border-radius:50%;
45                border:2px solid #fff;
46                left:calc(var(--s) * 1%);
47                top:calc((100 - var(--v)) * 1%);
48                transform:translate(-50%,-50%);
49            }
50            .color-chooser{
51                display:flex;
52                padding:10px 0;
53            }
54            .color-show{
55                display:flex;
56                position: relative;
57                width:32px;
58                height:32px;
59                background:var(--c);
60                transition:none;
61                border-radius:50%;
62                overflow:hidden;
63                cursor:pointer;
64            }
65            .color-show .icon-file{
66                width:1em;
67                height:1em;
68                margin: auto;
69                fill: hsl(0, 0%, calc( ((2 - var(--s) / 100) * var(--v) / 200 * var(--a) - 0.6 ) * -999999%  ));
70                opacity: 0;
71                transition: .3s;
72            }
73            .color-show:hover .icon-file{
74                opacity:1;
75            }
76            .color-show input{
77                position:absolute;
78                clip:rect(0,0,0,0);
79            }
80            .color-show::after{
81                content:'';
82                position:absolute;
83                width:32px;
84                height:32px;
85                background:linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
86                background-position:0 0,5px 5px;
87                background-size:10px 10px;
88                z-index:-1;
89            }
90            .color-range{
91                flex:1;
92                margin-left:10px;
93            }
94            input[type="range"]{
95                display: block;
96                pointer-events:all;
97                width:100%;
98                -webkit-appearance: none;
99                outline : 0;
100                height: 10px;
101                border-radius:5px;
102                margin:0;
103            }
104            input[type="range"]::-webkit-slider-runnable-track{
105                display: flex;
106                align-items: center;
107                position: relative;
108            }
109            input[type="range"]::-webkit-slider-thumb{
110                -webkit-appearance: none;
111                position: relative;
112                width:10px;
113                height:10px;
114                transform:scale(1.2);
115                border-radius: 50%;
116                box-shadow: 0 0 10px rgba(0,0,0,0.1);
117                background:#fff;
118                transition:.2s cubic-bezier(.12, .4, .29, 1.46);
119            }
120            input[type="range"]::-moz-range-thumb{
121                box-sizing:border-box;
122                pointer-events:none;
123                position: relative;
124                width:10px;
125                height:10px;
126                transform:scale(1.2);
127                border-radius: 50%;
128                border:0;
129                box-shadow: 0 0 10px rgba(0,0,0,0.1);
130                background:#fff;
131                transition:.2s cubic-bezier(.12, .4, .29, 1.46);
132            }
133            input[type="range"]::-webkit-slider-thumb:active,
134            input[type="range"]:focus::-webkit-slider-thumb{
135                transform:scale(1.5);
136            }
137            input[type="range"]::-moz-range-thumb:active,
138            input[type="range"]:focus::-moz-range-thumb{
139                transform:scale(1.5);
140            }
141            input[type="range"]+input[type="range"]{
142                margin-top:10px;
143            }
144            .color-hue{
145                background:linear-gradient(to right, red, yellow, lime, cyan, blue, magenta, red)
146            }
147            .color-opacity{
148                background:linear-gradient(to right, hsla(calc(var(--h)),100%,50%,0), hsla(calc(var(--h)),100%,50%,1)),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
149                background-position:0 0,0 0,5px 5px;
150                background-size:100% 100%,10px 10px,10px 10px;
151            }
152            .color-label{
153                position:absolute;
154                display:flex;
155                visibility:hidden;
156                opacity:0;
157                left:0;
158                right:0;
159                top:0;
160                bottom:0;
161                transition: .3s;
162            }
163            .color-label input{
164                flex:1;
165                margin-right:.8em;
166                outline:0;
167                min-width:0;
168                width: 0;
169                border-radius:var(--borderRadius,.25em);
170                border:1px solid #ddd;
171                padding:0 5px;
172                line-height:28px;
173                text-align:center;
174                -moz-appearance: textfield;
175                transition:.3s;
176            }
177            input[type="number"]::-webkit-inner-spin-button{
178                display:none;
179            }
180            ::-moz-focus-inner,::-moz-focus-outer{
181                border:0;
182                outline : 0;
183            }
184            .color-label input:focus{
185                border-color:var(--themeColor,#42b983);
186            }
187            .color-footer{
188                display:flex
189            }
190            .btn-switch{
191                position:relative;
192                border-radius:var(--borderRadius,.25em);
193                background:none;
194                border:0;
195                outline:0;
196                line-height:30px;
197                width: 60px;
198                padding: 0;
199                color:var(--themeColor,#42b983);
200                overflow:hidden;
201            }
202            .btn-switch::before{
203                content:'';
204                position:absolute;
205                left:0;
206                top:0;
207                right:0;
208                bottom:0;
209                background:var(--themeBackground,var(--themeColor,#42b983));
210                opacity:.2;
211                transition:.3s;
212            }
213            .btn-switch:hover::before,.btn-switch:focus::before{
214                opacity:.3;
215            }
216            .color-input{
217                position:relative;
218                flex:1;
219                height:30px;
220                overflow:hidden;
221            }
222            .color-footer[data-type="HEXA"] .color-label:nth-child(1),
223            .color-footer[data-type="RGBA"] .color-label:nth-child(2),
224            .color-footer[data-type="HSLA"] .color-label:nth-child(3){
225                opacity:1;
226                visibility:inherit;
227                z-index:2;
228            }
229            .color-sign{
230                padding-top:10px;
231                display:grid;
232                grid-template-columns: repeat(auto-fit, minmax(15px, 1fr));
233                grid-gap: 10px;
234            }
235            .color-sign>button{
236                position:relative;
237                cursor:pointer;
238                width:100%;
239                padding-bottom:0;
240                padding-top:100%;
241                border-radius:4px;
242                border:0;
243                outline:0;
244            }
245            .color-sign>button::before{
246                content:'';
247                position:absolute;
248                left:0;
249                top:0;
250                width:100%;
251                height:100%;
252                z-index:-1;
253                background:linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
254                background-position:0 0,5px 5px;
255                background-size:10px 10px;
256                border-radius: 4px;
257            }
258            .color-sign>button::after{
259                content:'';
260                position:absolute;
261                opacity:.5;
262                z-index:-2;
263                left:0;
264                top:0;
265                width:100%;
266                height:100%;
267                background:inherit;
268                border-radius:4px;
269                transition:.3s;
270            }
271            .color-sign>button:hover::after,.color-sign>button:focus::after{
272                transform:translate(2px,2px)
273            }
274        </style>
275        <div class="color-pane" id="color-pane">
276            <div class="color-palette" id="color-palette"></div>
277            <div class="color-chooser">
278                <a class="color-show" id="copy-btn"><svg class="icon-file" viewBox="0 0 1024 1024"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32z"></path><path d="M704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg><input></a>
279                <div class="color-range">
280                    <input class="color-hue" value="0" min="0" max="360" type="range" id="range-hue">
281                    <input class="color-opacity" value="1" min="0" max="1" step="0.01" type="range" id="range-opacity">
282                </div>
283            </div>
284            <div class="color-footer" data-type="HEXA">
285                <div class="color-input">
286                    <div class="color-label" id="color-hexa">
287                        <input spellcheck="false" />
288                    </div>
289                    <div class="color-label" id="color-rgba">
290                        <input type="number" min="0" max="255" spellcheck="false" />
291                        <input type="number" min="0" max="255" spellcheck="false" />
292                        <input type="number" min="0" max="255" spellcheck="false" />
293                        <input type="number" min="0" max="1" step="0.01" spellcheck="false" />
294                    </div>
295                    <div class="color-label" id="color-hlsa">
296                        <input type="number" min="0" max="360" spellcheck="false" />
297                        <input type="number" min="0" max="100" spellcheck="false" />
298                        <input type="number" min="0" max="100" spellcheck="false" />
299                        <input type="number" min="0" max="1" step="0.01" spellcheck="false" />
300                    </div>
301                </div>
302                <button class="btn-switch" id="btn-switch" type="flat">HEXA</button>
303            </div>
304            <div class="color-sign" id="colors">
305                ${
306                    Material_colors.map(el=>'<button style="background-color:'+el+'" data-color='+el+'></button>').join('')
307                }
308            </div>
309        </div>
310        `
311    }
312
313    choose(ev){
314        const {x,y,width:w,height:h} = this.palette.getBoundingClientRect();
315        const value = [...this.$value];
316        const _x = Math.min(Math.max(0,(ev.clientX-x)/w*100),100);
317        const _y = Math.min(Math.max(0,(ev.clientY-y)/h*100),100);
318        value[1] = _x;
319        value[2] = 100-_y;
320        this.value = `hsva(${value[0]}, ${value[1]}%, ${value[2]}%, ${value[3]})`;
321    }
322
323    connectedCallback() {
324        this.type = ['HEXA','RGBA','HSLA'];
325        this.typeindex = 0;
326        this.palette = this.shadowRoot.getElementById('color-palette');
327        this.colors = this.shadowRoot.getElementById('colors');
328        this.pane = this.shadowRoot.getElementById('color-pane');
329        this.rangeHue = this.shadowRoot.getElementById('range-hue');
330        this.rangeOpacity = this.shadowRoot.getElementById('range-opacity');
331        this.copyBtn = this.shadowRoot.getElementById('copy-btn');
332        this.copyinfo = this.copyBtn.querySelector('input');
333        this.switch = this.shadowRoot.getElementById('btn-switch');
334        this.colorHexa = this.shadowRoot.getElementById('color-hexa').querySelectorAll('input');
335        this.colorRgba = this.shadowRoot.getElementById('color-rgba').querySelectorAll('input');
336        this.colorHlsa = this.shadowRoot.getElementById('color-hlsa').querySelectorAll('input');
337        this.value = this.defaultvalue;
338        this.rangeHue.addEventListener('input',()=>{
339            const value = [...this.$value];
340            value[0] = Number(this.rangeHue.value);
341            this.nativeclick = true;
342            this.value = `hsva(${value[0]}, ${value[1]}%, ${value[2]}%, ${value[3]})`;
343        })
344        this.palette.addEventListener('mousedown',(ev)=>{
345            this.start = true;
346            this.choose(ev);
347        })
348        document.addEventListener('mousemove',this.mousemove);
349
350        document.addEventListener('mouseup',this.mouseup);
351        this.rangeOpacity.addEventListener('input',()=>{
352            const value = [...this.$value];
353            value[3] = Number(this.rangeOpacity.value);
354            this.nativeclick = true;
355            this.value = `hsva(${value[0]}, ${value[1]}%, ${value[2]}%, ${value[3]})`;
356        })
357        this.colors.addEventListener('click',(ev)=>{
358            const item = ev.target.closest('button');
359            if(item){
360                this.nativeclick = true;
361                this.value = item.dataset.color;
362            }
363        })
364        this.switch.addEventListener('click',()=>{
365            this.typeindex ++;
366            this.typeindex %= 3;
367            this.switch.textContent = this.type[this.typeindex];
368            this.nativeclick = true;
369            this.value = this.value;
370            this.switch.parentNode.dataset.type = this.type[this.typeindex];
371        })
372        this.copyBtn.addEventListener('click',()=>{
373            this.copyinfo.select();
374            if (document.execCommand('copy')) {
375                document.execCommand('copy');
376                message.success(this.value);
377            }
378        })
379        this.colorHexa.forEach(el=>{
380            el.addEventListener('change',()=>{
381                this.nativeclick = true;
382                this.value = el.value;
383            })
384        })
385        this.colorRgba.forEach((el,i)=>{
386            el.addEventListener('change',()=>{
387                const value = HSVaColor(...this.$value).toRGBA();
388                value[i] = Number(el.value);
389                this.nativeclick = true;
390                this.value = `rgba(${value[0]}, ${value[1]}, ${value[2]}, ${value[3]})`;
391            })
392        })
393        this.colorHlsa.forEach((el,i)=>{
394            el.addEventListener('change',()=>{
395                const value = HSVaColor(...this.$value).toHSLA();
396                value[i] = Number(el.value);
397                this.nativeclick = true;
398                this.value = `hsla(${value[0]}, ${value[1]}%, ${value[2]}%, ${value[3]})`;
399            })
400        })
401    }
402
403    mousemove = (ev) => {
404        if(this.start){
405            this.choose(ev);
406        }
407    }
408
409    mouseup = () => {
410        if(getComputedStyle(this.palette).opacity!==1 && this.start){
411            this.dispatchEvent(new CustomEvent('change', {
412                detail: {
413                    value: this.value,
414                    color: this.color
415                }
416            }));
417        }
418        this.start = false;
419    }
420
421    disconnectedCallback() {
422        document.removeEventListener('mousemove', this.mousemove);
423        document.removeEventListener('mouseup', this.mouseup);
424    }
425
426    get value() {
427        return HSVaColor(...this.$value)['to'+this.type[this.typeindex]]().toString();
428    }
429
430    get color() {
431        return HSVaColor(...this.$value);
432    }
433
434    get defaultvalue() {
435        return this.getAttribute('defaultvalue')||'#ff0000';
436    }
437
438    set defaultvalue(value) {
439        this.setAttribute("defaultvalue",value);
440    }
441
442    set value(value) {
443        this.$value = parseToHSVA(value).values;
444        //[h,s,v,a]
445        const [h,s,v,a=1] = this.$value;
446        this.pane.style.setProperty('--h',h);
447        this.pane.style.setProperty('--s',s);
448        this.pane.style.setProperty('--v',v);
449        this.pane.style.setProperty('--a',a);
450        this.pane.style.setProperty('--c',this.value);
451        this.copyinfo.value = this.value;
452        this.rangeHue.value = h;
453        this.rangeOpacity.value = a.toFixed(2);
454        const COLOR = HSVaColor(...this.$value);
455        this.colorHexa[0].value = COLOR.toHEXA().toString();
456        const RGBA = COLOR.toRGBA();
457        this.colorRgba[0].value = RGBA[0].toFixed(0);
458        this.colorRgba[1].value = RGBA[1].toFixed(0);
459        this.colorRgba[2].value = RGBA[2].toFixed(0);
460        this.colorRgba[3].value = RGBA[3].toFixed(2);
461        const HSLA = COLOR.toHSLA();
462        this.colorHlsa[0].value = HSLA[0].toFixed(0);
463        this.colorHlsa[1].value = HSLA[1].toFixed(0);
464        this.colorHlsa[2].value = HSLA[2].toFixed(0);
465        this.colorHlsa[3].value = HSLA[3].toFixed(2);
466        if(this.nativeclick){
467            this.nativeclick = false;
468            this.dispatchEvent(new CustomEvent('change', {
469                detail: {
470                    value: this.value,
471                    color: this.color
472                }
473            }));
474        }
475    }
476
477}
478
479if(!customElements.get('xy-color-pane')){
480    customElements.define('xy-color-pane', XyColorPane);
481}
482
483export default class XyColorPicker extends HTMLElement {
484
485    static get observedAttributes() { return ['disabled','dir'] }
486
487    constructor() {
488        super();
489        const shadowRoot = this.attachShadow({ mode: 'open' });
490
491        shadowRoot.innerHTML = `
492        <style>
493        :host{
494            display:inline-block;
495            width:30px;
496            height:30px;
497            font-size:14px;
498        }
499        :host([block]){
500            display:block;
501        }
502
503        :host([disabled]){
504            pointer-events:none;
505        }
506        
507        :host(:focus-within) xy-popover,:host(:hover) xy-popover{ 
508            z-index: 2;
509        }
510        xy-popover{
511            width:100%;
512            height:100%;
513        }
514        .color-btn{
515            width:100%;
516            height:100%;
517            padding:5px;
518            background-clip: content-box;
519            background-color:var(--themeColor,#42b983);
520        }
521        .color-btn:hover{
522            z-index: auto;
523        }
524        xy-popover{
525            display:block;
526        }
527        xy-popcon{
528            min-width:100%;
529        }
530        .pop-footer{
531            display:flex;
532            justify-content:flex-end;
533            padding:0 .8em .8em;
534        }
535        .pop-footer xy-button{
536            font-size: .8em;
537            margin-left: .8em;
538        }
539        .color-btn::before{
540            content:'';
541            position:absolute;
542            left:5px;
543            top:5px;
544            right:5px;
545            bottom:5px;
546            z-index:-1;
547            background:linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 ),linear-gradient( 45deg, #ddd 25%,transparent 0,transparent 75%,#ddd 0 );
548            background-position:0 0,5px 5px;
549            background-size:10px 10px;
550        }
551        </style>
552        <xy-popover id="popover" ${this.dir? "dir='"+this.dir+"'" : ""}>
553            <xy-button class="color-btn" id="color-btn" ${this.disabled? "disabled" : ""}></xy-button>
554            <xy-popcon id="popcon">
555                <div class="pop-footer">
556                    <xy-button autoclose>取 消</xy-button>
557                    <xy-button type="primary" id="btn-submit" autoclose>确 认</xy-button>
558                </div>
559            </xy-popcon>
560        </xy-popover>
561        `
562    }
563
564    focus() {
565        this.colorBtn.focus();
566    }
567
568    connectedCallback() {
569        this.popover = this.shadowRoot.getElementById('popover');
570        this.popcon = this.shadowRoot.getElementById('popcon');
571        this.colorBtn = this.shadowRoot.getElementById('color-btn');
572        this.btnSubmit = this.shadowRoot.getElementById('btn-submit');
573        this.colorBtn.addEventListener('click',()=>{
574            if(!this.colorPane){
575                this.colorPane = new XyColorPane();
576                this.colorPane.defaultvalue = this.defaultvalue;
577                this.popcon.prepend(this.colorPane);
578            }
579        })
580        this.btnSubmit.addEventListener('click',()=>{
581            this.nativeclick = true;
582            this.value = this.colorPane.value;
583        })
584        this.popcon.addEventListener('close',()=>{
585            this.colorPane.value = this.value;
586        })
587        this.value = this.defaultvalue;
588    }
589
590    
591
592    get defaultvalue() {
593        return this.getAttribute('defaultvalue')||'#42b983';
594    }
595
596    get value() {
597        return this.$value;
598    }
599
600    get color() {
601        return HSVaColor(...parseToHSVA(this.$value).values);
602    }
603
604    get type() {
605        return this.getAttribute('type');
606    }
607
608    get disabled() {
609        return this.getAttribute('disabled')!==null;
610    }
611
612    get dir() {
613        return this.getAttribute('dir');
614    }
615
616    set dir(value){
617        this.setAttribute('dir', value);
618    }
619
620    set disabled(value) {
621        if (value === null || value === false) {
622            this.removeAttribute('disabled');
623        } else {
624            this.setAttribute('disabled', '');
625        }
626    }
627
628    set defaultvalue(value){
629        this.setAttribute('defaultvalue', value);
630    }
631
632    set value(value) {
633        this.colorBtn.style.setProperty('--themeColor',value);
634        this.$value = value;
635        if(this.nativeclick){
636            this.nativeclick = false;
637            this.dispatchEvent(new CustomEvent('change', {
638                detail: {
639                    value: this.value,
640                    color: this.color
641                }
642            }));
643        }else{
644            if(this.colorPane){
645                this.colorPane.value = this.value;
646            }else{
647                this.defaultvalue = this.value;
648            }
649        }
650    }
651
652    attributeChangedCallback(name, oldValue, newValue) {
653        if (name == 'disabled' && this.colorBtn) {
654            if (newValue != null) {
655                this.colorBtn.setAttribute('disabled', 'disabled');
656            } else {
657                this.colorBtn.removeAttribute('disabled');
658            }
659        }
660        if (name == 'dir' && this.popover) {
661            if (newValue != null) {
662                this.popover.dir = newValue;
663            }
664        }
665    }
666}
667
668if (!customElements.get('xy-color-picker')) {
669    customElements.define('xy-color-picker', XyColorPicker);
670}
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Appium Xcuitest Driver on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)