colorpicker with alpha (rgba)

by polaszk

HTML

<div class="colorOption">
  <label class="label">Color 1:</label>
  <div class="colorSquare openPaletteBtn-js" data-name="color1" data-value="rgba(143, 66, 138, .5)" style="background: rgba(143, 66, 138, 0.5)"></div>
</div>
<div class="colorOption">
  <label class="label">Color 2:</label>
  <div class="colorSquare openPaletteBtn-js" data-name="color2" data-value="#ccc" style="background: #ccc"></div>
</div>

<div class="colorPalette colorPalette-js" data-name="">
  <canvas class="canvas-js"></canvas>
  <div class="alphaPicker alphaPicker-js">
    <span class="selectedAlpha selectedAlpha-js"></span>
  </div>
  <div class="colorPalette__buttons">
    <button class="colorPalette__button colorPalette__secondaryButton cancelColorBtn-js" type="button">Cancel</button>
    <button class="colorPalette__button colorPalette__primaryButton saveColorBtn-js" type="button">OK</button>
  </div>
</div>

CSS

.colorOption {
  margin: 10px 0;
}

.colorSquare {
  box-shadow: 2px 8px 10px 0 rgba(0, 0, 0, .25);
  cursor: pointer;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  display: inline-block;
  margin: 5px 5px -5px;
}

.colorPalette {
  border: solid 1px #000;
  background: #fff;
  display: flex;
  position: absolute;
  flex-direction: column;
  align-items: center;
  z-index: 100;
  width: 342px;
  height: 487px;
  margin: 20px;
  display: none;
}

.alphaPicker {
  position: relative;
  width: 300px;
  height: 30px;
  margin: 0 20px 20px;
  background: linear-gradient(to right, rgb(143, 16, 16), rgba(143, 16, 16, 0)) left top / contain, url('') white;
}

.selectedAlpha {
  border: 3px solid #fff;
  box-sizing: border-box;
  position: absolute;
  z-index: 1;
  height: 30px;
  width: 30px;
  transform: translate(-50%, 0px);
  box-shadow: rgb(103, 191, 255) 0 0 3px 1px;
  pointer-events: none;
}

.colorPalette__values {
  margin: 0 0 20px 0;
}

.colorPalette__button {
  cursor: pointer;
  padding: 12px 42px;
  border: 1px solid #283593;
  border-radius: 3rem;
  outline: none;
  transition: 150ms ease;
  width: 140px;
}

.colorPalette__primaryButton {
  background-color: #283593;
  color: #fff;
}

.colorPalette__primaryButton:hover {
  background-color: #495de3;
  border-color: #495de3;
}

.colorPalette__secondaryButton {
  background-color: #fff;
  color: #283593;
  margin: 0 14px 0 21px;
}

.colorPalette__secondaryButton:hover {
  border-color: #626465;
  background-color: #626465;
  color: #fff;
}

JavaScript

var colorPicker = {
  init: function() {
    colorPicker.events();
    colorPicker.drawElements();
  },
  drawElements: function(color) {
    var canvas = document.querySelector('.canvas-js');
    var ctx = canvas.getContext('2d');
    var lw = ctx.lineWidth;
    var canvasPadding = 20;
    var drawXStart = canvasPadding;
    var drawYStart = canvasPadding;
    var huePickerHeight = 30;
    var canvasPickerSize = 300;
    var canvasHeight = huePickerHeight + canvasPickerSize + canvasPadding * 2;
    var canvasWidth = canvasPickerSize + canvasPadding * 2;
    var h = colorPicker.rgbHexToHsv(color).h;
    var s = colorPicker.rgbHexToHsv(color).s;
    var v = colorPicker.rgbHexToHsv(color).v;
    var hueX = Math.round(h / 360 * canvasPickerSize + drawXStart);
    var hueY = huePickerHeight / 2 + drawYStart;
    var hueRadius = huePickerHeight / 2 - 2;
    var sbX = s * canvasPickerSize / 100 + drawXStart;
    var sbY = huePickerHeight + (100 - v) * canvasPickerSize / 100 + drawYStart;

    ctx.canvas.height = canvasHeight;
    ctx.canvas.width = canvasWidth;

    colorPicker.drawHueGradient(ctx, canvasPickerSize, huePickerHeight, drawXStart, drawYStart);
    colorPicker.drawSaturationBrightnessGradient(ctx, drawXStart, drawYStart, canvasHeight, huePickerHeight, canvasPickerSize, canvasWidth, h);

    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.strokeStyle = '#bbb';
    ctx.fillStyle = 'none';
    ctx.arc(hueX, hueY, hueRadius, 0, 2 * Math.PI, false);
    ctx.stroke();

    ctx.beginPath();
    ctx.strokeStyle = '#bbb';
    ctx.fillStyle = 'rgba(0,0,0,0)';
    ctx.arc(sbX, sbY, 5, 0, 2 * Math.PI, false);
    ctx.stroke();
    ctx.fill();
    ctx.lineWidth = lw;
  },
  drawHueGradient: function(ctx, canvasPickerSize, huePickerHeight, drawXStart, drawYStart) {
    var grd = ctx.createLinearGradient(0, 0, canvasPickerSize, 0);
    grd.addColorStop(0, '#f00');
    grd.addColorStop(1 / 6, '#ff0');
    grd.addColorStop(2 / 6, '#0f0');
    grd.addColorStop(3 / 6,...