Color Picker
document.body.innerHTML = '';
 
var ColorPicker = class {
    constructor(size=150, parent) {
        var wrap = document.createElement('div');
        (parent || document.body).appendChild(wrap);
        var shadow = wrap.shadowRoot || wrap.attachShadow({mode: 'open'});
        var style = document.createElement('style');
        style.innerHTML = `
            :host {
                --transparent: linear-gradient(45deg, #eee 25%, transparent 0, transparent 75%, #eee 0) 0 0/14px 14px, linear-gradient(45deg, #eee 25%, transparent 0, transparent 75%, #eee 0) 7px 7px/14px 14px;
            }
            :host hr {
                border: none;
                margin: 0;
                padding: 0;
            }
            :host .range_wrap {
                background: var(--transparent);
                display: inline-block;
                position: relative;
            }
            :host .range_wrap input[type="range"] {
                -webkit-appearance: none;
                background: linear-gradient(90deg, rgba(0,0,0,0), rgba(0,0,0,1));
                border: none;
                cursor: pointer;
                display: block;
                height: 1em;
                margin: 0;
                padding: 0;
                width: calc(var(--range_size) * 1px);
            }
            :host .range_wrap input[type="range"]::-webkit-slider-thumb {
                -webkit-appearance: none;
                -moz-appearance: none;
                width: 0;
                height: 0;
            }
            :host .range_wrap label {
                background: rgb(255, 255, 255);
                border-radius: 50%;
                box-shadow: rgb(170 170 170) 1px 1px 3px;
                display: block;
                height: 1em;
                left: calc(var(--value) / 255 * (var(--range_size) * 1px - 1em));
                pointer-events: none;
                position: absolute;
                top: 0px;
                width: 1em;
            }
            :host .range_wrap:focus-within label {
                outline: 2px solid #4d90fe;
            }
 
        `;
 
        this.picker = document.createElement('canvas');
        this.strip = document.createElement('canvas');
        var range = document.createElement('div');
        var hr = document.createElement('hr');
        range.classList.add('range_wrap');
        this.opacity = document.createElement('input');
        this.opacity.type = 'range';
        this.opacity.max = 255;
        this.opacity.value = 255;
        var label = document.createElement('label');
        label.style.setProperty('--value', 255);
        this.opacity.__label__ = label;
        [this.opacity, label].forEach(v => range.appendChild(v));
        [style, this.picker, this.strip, hr, range].forEach(v => shadow.appendChild(v));
        this.p_ctx = this.picker.getContext('2d');
        this.s_ctx = this.strip.getContext('2d');
        this.picker.height = parseInt(size * 5 / 6);
        this.picker.width = parseInt(size);
        this.strip.height = parseInt(size * 5 / 6);
        this.strip.width = parseInt(size / 4);
        range.style.setProperty('--range_size', parseInt(size / 4) + parseInt(size));
        this.current_color = 'rgba(255, 0, 0, 1)';
        this.update(this.current_color);
        this.createStrip();
        this.picker.onclick = e => {
            var data = this.p_ctx.getImageData(e.offsetX, e.offsetY, 1, 1).data;
            this.current_color = `rgba(${data.slice(0, 3).join(', ')}, ${parseInt(this.opacity.value / 255 * 100) / 100})`;
            console.log( this.current_color );
        };
        this.strip.onclick = e => {
          var data = this.s_ctx.getImageData(e.offsetX, e.offsetY, 1, 1).data.slice(0, 3);
          this.update(`rgba(${data.join(', ')}, 1)`);
        };
        this.opacity.oninput = e => e.target.__label__.style.setProperty('--value', e.target.value);
    }
    createStrip() {
        this.s_ctx.rect(0, 0, this.strip.width, this.strip.height);
        var grd = this.s_ctx.createLinearGradient(0, 0, 0, this.strip.height);
        var colors = ['rgba(255, 0, 0, 1)', 'rgba(255, 255, 0, 1)', 'rgba(0, 255, 0, 1)', 'rgba(0, 255, 255, 1)', 'rgba(0, 0, 255, 1)', 'rgba(255, 0, 255, 1)', 'rgba(255, 0, 0, 1)']
        colors.forEach((v, i) => grd.addColorStop(i / colors.length, v));
        this.s_ctx.fillStyle = grd;
        this.s_ctx.fill();
    }
    update(color) {
        this.p_ctx.fillStyle = color;
        this.p_ctx.fillRect(0, 0, this.picker.width, this.picker.height);
 
        var grdWhite = this.s_ctx.createLinearGradient(0, 0, this.picker.width, 0);
        grdWhite.addColorStop(0, 'rgba(255, 255, 255, 1)');
        grdWhite.addColorStop(1, 'rgba(255, 255, 255, 0)');
        this.p_ctx.fillStyle = grdWhite;
        this.p_ctx.fillRect(0, 0, this.picker.width, this.picker.height);
 
        var grdBlack = this.s_ctx.createLinearGradient(0, 0, 0, this.picker.height);
        grdBlack.addColorStop(0, 'rgba(0, 0, 0, 0)');
        grdBlack.addColorStop(1, 'rgba(0, 0, 0, 1)');
        this.p_ctx.fillStyle = grdBlack;
        this.p_ctx.fillRect(0, 0, this.picker.width, this.picker.height);
    }
};
 
new ColorPicker();
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License