const ColorPicker = (() => { let sliders = document.getElementsByClassName("cp-slider-entry"); let colourPreview = document.getElementById("cp-colour-preview"); let colourValue = document.getElementById("cp-hex"); let currentPickerMode = "rgb"; let currentPickingMode = "mono"; let styleElement = document.createElement("style"); let miniPickerCanvas = document.getElementById("cp-spectrum"); let miniPickerSlider = document.getElementById("cp-minipicker-slider"); let activePickerIcon = document.getElementById("cp-active-icon"); let pickerIcons = [activePickerIcon]; let hexContainers = [document.getElementById("cp-colours-previews").children[0],null,null,null]; let startPickerIconPos = [[0,0],[0,0],[0,0],[0,0]]; let currPickerIconPos = [[0,0], [0,0],[0,0],[0,0]]; let styles = ["",""]; let draggingCursor = false; // Picker mode events Events.on("click", "cp-rgb", changePickerMode, 'rgb'); Events.on("click", "cp-hsv", changePickerMode, 'hsv'); Events.on("click", "cp-hsl", changePickerMode, 'hsl'); // Hex-related events Events.on("change", "cp-hex", hexUpdated); // Slider events Events.on("mousemove", "first-slider", updateSliderValue, 1); Events.on("mousemove", "second-slider", updateSliderValue, 2); Events.on("mousemove", "third-slider", updateSliderValue, 3); Events.on("click", "first-slider", updateSliderValue, 1); Events.on("click", "second-slider", updateSliderValue, 2); Events.on("click", "third-slider", updateSliderValue, 3); // Slider textbox events Events.on("change", "cp-sliderText1", inputChanged, 1); Events.on("change", "cp-sliderText2", inputChanged, 2); Events.on("change", "cp-sliderText3", inputChanged, 3); // Minipicker events Events.on("mousemove", "cp-minipicker-slider", miniSliderInput); Events.on("click", "cp-minipicker-slider", miniSliderInput); Events.on("mousemove", "cp-canvas-container", movePickerIcon); Events.on("click", "cp-mono", changePickingMode, "mono"); Events.on("click", "cp-analog", changePickingMode, "analog"); Events.on("click", "cp-cmpt", changePickingMode, "cmpt"); Events.on("click", "cp-tri", changePickingMode, "tri"); Events.on("click", "cp-scmpt", changePickingMode, "scmpt"); Events.on("click", "cp-tetra", changePickingMode, "tetra"); init(); function init() { // Appending the palette styles document.getElementsByTagName("head")[0].appendChild(styleElement); // Saving first icon position startPickerIconPos[0] = [miniPickerCanvas.getBoundingClientRect().left, miniPickerCanvas.getBoundingClientRect().top]; // Set the correct size of the canvas miniPickerCanvas.height = miniPickerCanvas.getBoundingClientRect().height; miniPickerCanvas.width = miniPickerCanvas.getBoundingClientRect().width; // Update picker position updatePickerByHex(colourValue.value); // Startup updating updateAllSliders(); // Fill minislider updateMiniSlider(colourValue.value); // Fill minipicker updatePickerByHex(colourValue.value); updateMiniPickerSpectrum(); } function hexUpdated() { updatePickerByHex(colourValue.value); updateSlidersByHex(colourValue.value); } // Applies the styles saved in the style array to the style element in the head of the document function updateStyles() { styleElement.innerHTML = styles[0] + styles[1]; } /** Updates the background gradients of the sliders given their value * Updates the hex colour and its preview * Updates the minipicker according to the computed hex colour * */ function updateSliderValue (sliderIndex, updateMini = true) { let toUpdate; let slider; let input; let hexColour; let sliderValues; toUpdate = sliders[sliderIndex - 1]; slider = toUpdate.getElementsByTagName("input")[0]; input = toUpdate.getElementsByTagName("input")[1]; // Update label value input.value = slider.value; // Update preview colour // get slider values sliderValues = getSlidersValues(); // Generate preview colour hexColour = new Color(currentPickerMode, sliderValues[0], sliderValues[1], sliderValues[2]); // Update preview colour div colourPreview.style.backgroundColor = '#' + hexColour.hex; colourValue.value = '#' + hexColour.hex; // Update sliders background // there's no other way than creating a custom css file, appending it to the head and // specify the sliders' backgrounds here styles[0] = ''; for (let i=0; i -8 && top > -8 && left < canvasRect.width-8 && top < canvasRect.height-8){ activePickerIcon.style["left"] = "" + left + "px"; activePickerIcon.style["top"]= "" + top + "px"; currPickerIconPos[0] = [left, top]; } updateMiniPickerColour(); updateOtherIcons(); } } // Updates the main sliders given a hex value computed with the minipicker function updateSlidersByHex(hex, updateMini = true) { let colour = new Color("hex", hex); let mySliders = [sliders[0].getElementsByTagName("input")[0], sliders[1].getElementsByTagName("input")[0], sliders[2].getElementsByTagName("input")[0]]; switch (currentPickerMode) { case 'rgb': colour = colour.rgb; mySliders[0].value = colour.r; mySliders[1].value = colour.g; mySliders[2].value = colour.b; break; case 'hsv': colour = colour.hsv; mySliders[0].value = colour.h; mySliders[1].value = colour.s; mySliders[2].value = colour.v; break; case 'hsl': colour = colour.hsl; mySliders[0].value = colour.h; mySliders[1].value = colour.s; mySliders[2].value = colour.l; break; default: break; } updateAllSliders(false); } // Gets the position of the picker cursor relative to the canvas function getCursorPosMinipicker(e) { var x; var y; if (e.pageX != undefined && e.pageY != undefined) { x = e.pageX; y = e.pageY; } else { x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; } x -= miniPickerCanvas.offsetLeft; y -= miniPickerCanvas.offsetTop; return [Math.round(x), Math.round(y)]; } // Updates the minipicker given a hex computed by the main sliders // Moves the cursor function updatePickerByHex(hex) { let hsv = new Color("hex", hex).hsv; let xPos = miniPickerCanvas.width * hsv.h/360 - 8; let yPos = miniPickerCanvas.height * hsv.s/100 + 8; miniPickerSlider.value = hsv.v; currPickerIconPos[0][0] = xPos; currPickerIconPos[0][1] = miniPickerCanvas.height - yPos; if (currPickerIconPos[0][1] >= 92) currPickerIconPos[0][1] = 91.999; activePickerIcon.style.left = '' + xPos + 'px'; activePickerIcon.style.top = '' + (miniPickerCanvas.height - yPos) + 'px'; activePickerIcon.style.backgroundColor = '#' + getMiniPickerColour(); colourPreview.style.backgroundColor = hex; updateOtherIcons(); updateMiniSlider(hex); } // Fired when the value of the minislider changes: updates the spectrum gradient and the hex colour function miniSliderInput(event) { let currColor = new Color("hex", getMiniPickerColour()); let newHsv = currColor.hsv; let newHex; // Adding slider value to value newHsv = new Color("hsv", newHsv.h, newHsv.s, parseInt(event.target.value)); // Updating hex newHex = newHsv.hex; colourValue.value = newHex; updateMiniPickerSpectrum(); updateMiniPickerColour(); } // Updates the hex colour after having changed the minislider (MERGE) function updateMiniPickerColour() { let hex = getMiniPickerColour(); activePickerIcon.style.backgroundColor = '#' + hex; // Update hex and sliders based on hex colourValue.value = '#' + hex; colourPreview.style.backgroundColor = '#' + hex; updateSlidersByHex(hex); updateMiniSlider(hex); updateOtherIcons(); } // Returns the current colour of the minipicker function getMiniPickerColour() { let pickedColour; pickedColour = miniPickerCanvas.getContext('2d').getImageData(currPickerIconPos[0][0] + 8, currPickerIconPos[0][1] + 8, 1, 1).data; return new Color("rgb", Math.round(pickedColour[0]), Math.round(pickedColour[1]), Math.round(pickedColour[2])).hex; } // Update the background gradient of the slider in the minipicker function updateMiniSlider(hex) { let rgb = Color.hexToRgb(hex); styles[1] = "input[type=range]#cp-minipicker-slider::-webkit-slider-runnable-track { background: rgb(2,0,36);"; styles[1] += "background: linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(0,0,0,1) 0%, " + "rgba(" + rgb.r + "," + rgb.g + "," + rgb.b + ",1) 100%);}"; updateMiniPickerSpectrum(); updateStyles(); } // Updates the gradient of the spectrum canvas in the minipicker function updateMiniPickerSpectrum() { let ctx = miniPickerCanvas.getContext('2d'); let hsv = new Color("hex", colourValue.value).hsv; let white = new Color("hsv", hsv.h, 0, parseInt(miniPickerSlider.value)).rgb; ctx.clearRect(0, 0, miniPickerCanvas.width, miniPickerCanvas.height); // Drawing hues var hGrad = ctx.createLinearGradient(0, 0, miniPickerCanvas.width, 0); for (let i=0; i<7; i++) { let stopHex = new Color("hsv", 60*i, 100, hsv.v); hGrad.addColorStop(i / 6, '#' + stopHex.hex); } ctx.fillStyle = hGrad; ctx.fillRect(0, 0, miniPickerCanvas.width, miniPickerCanvas.height); // Drawing sat / lum var vGrad = ctx.createLinearGradient(0, 0, 0, miniPickerCanvas.height); vGrad.addColorStop(0, 'rgba(' + white.r +',' + white.g + ',' + white.b + ',0)'); vGrad.addColorStop(1, 'rgba(' + white.r +',' + white.g + ',' + white.b + ',1)'); ctx.fillStyle = vGrad; ctx.fillRect(0, 0, miniPickerCanvas.width, miniPickerCanvas.height); } function changePickingMode(newMode, event) { let nIcons = pickerIcons.length; let canvasContainer = document.getElementById("cp-canvas-container"); // Number of hex containers to add let nHexContainers; // Remove selected class from previous mode document.getElementById("cp-colour-picking-modes").getElementsByClassName("cp-selected-mode")[0].classList.remove("cp-selected-mode"); // Updating mode currentPickingMode = newMode; // Adding selected class to new mode event.target.classList.add("cp-selected-mode"); for (let i=1; i 110) { return '#332f35' } else { return '#c2bbc7'; } //take in a color and return its brightness function colorBrightness (color) { var r = parseInt(color.slice(1, 3), 16); var g = parseInt(color.slice(3, 5), 16); var b = parseInt(color.slice(5, 7), 16); return Math.round(((parseInt(r) * 299) + (parseInt(g) * 587) + (parseInt(b) * 114)) / 1000); } } return { init, getSelectedColours, updatePickerByHex, updateSlidersByHex, updateMiniPickerColour } })();