JSFiddle - React, Tailwind, and code Playground

Color ramp with simple color blend operation.

by Travis Almand

HTML

<label><input type="color" id="guidance_color" value="#3C8081" /> Guidance Color</label>
<label><input type="color" id="affordance_color" value="#F47929" /> Affordance Color</label>

<br /><br />

<canvas id="canvas" width="500" height="500"></canvas>

<div id="output">
  <div id="guidance">
    <div class="swatch guidance50"></div>
    <div class="swatch guidance100"></div>
    <div class="swatch guidance200"></div>
    <div class="swatch guidance300"></div>
    <div class="swatch guidance400"></div>
    <div class="swatch guidance500"></div>
    <div class="swatch guidance600"></div>
    <div class="swatch guidance700"></div>
    <div class="swatch guidance800"></div>
    <div class="swatch guidance900"></div>
  </div>
  <div id="affordance">
    <div class="swatch affordance50"></div>
    <div class="swatch affordance100"></div>
    <div class="swatch affordance200"></div>
    <div class="swatch affordance300"></div>
    <div class="swatch affordance400"></div>
    <div class="swatch affordance500"></div>
    <div class="swatch affordance600"></div>
    <div class="swatch affordance700"></div>
    <div class="swatch affordance800"></div>
    <div class="swatch affordance900"></div>
  </div>
</div>
<label><input type="color" id="output_color" value="#FFFFFF" /> Background Color</label>

SCSS

label {
  display: block;
  margin: 10px;
}

canvas {
  display: none;
}

#output {
  background-color: var(--outputColor);
  display: flex;
  
  .swatch {
    height: 25px;
    margin: 10px;
    width: 100px;
  }
  
  .guidance50 { background-color: var(--guidance50); transition: 0.25s 0s; };
  .guidance100 { background-color: var(--guidance100); transition: 0.25s 0.1s; };
  .guidance200 { background-color: var(--guidance200); transition: 0.25s 0.2; };
  .guidance300 { background-color: var(--guidance300); transition: 0.25s 0.3s; };
  .guidance400 { background-color: var(--guidance400); transition: 0.25s 0.4s; };
  .guidance500 { background-color: var(--guidance500); transition: 0.25s 0.5s; };
  .guidance600 { background-color: var(--guidance600); transition: 0.25s 0.6s; };
  .guidance700 { background-color: var(--guidance700); transition: 0.25s 0.7s; };
  .guidance800 { background-color: var(--guidance800); transition: 0.25s 0.8s; };
  .guidance900 { background-color: var(--guidance900); transition: 0.25s 0.9s; };
  
  .affordance50 { background-color: var(--affordance50); transition: 0.25s 0s; };
  .affordance100 { background-color: var(--affordance100); transition: 0.25s 0.1s; };
  .affordance200 { background-color: var(--affordance200); transition: 0.25s 0.2s; };
  .affordance300 { background-color: var(--affordance300); transition: 0.25s 0.3s; };
  .affordance400 { background-color: var(--affordance400); transition: 0.25s 0.4s; };
  .affordance500 { background-color: var(--affordance500); transition: 0.25s 0.5s; };
  .affordance600 { background-color: var(--affordance600); transition: 0.25s 0.6s; };
  .affordance700 { background-color: var(--affordance700); transition: 0.25s 0.7s; };
  .affordance800 { background-color: var(--affordance800); transition: 0.25s 0.8s; };
  .affordance900 { background-color: var(--affordance900); transition: 0.25s 0.9s; };
}

JavaScript

console.clear();

const guidanceColor = document.querySelector('#guidance_color');
const affordanceColor = document.querySelector('#affordance_color');
const outputColor = document.querySelector('#output_color');
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
const grayscaleRamp = {
	50: '#F2F2F2',
  100: '#E6E6E6',
  200: '#CCCCCC',
  300: '#B3B3B3',
  400: '#999999',
  500: '#808080',
  600: '#666666',
  700: '#4D4D4D',
  800: '#333333',
  900: '#1A1A1A'
};
let pickedColors = {};

function setColors (ramp, guidance, affordance) {
	function getColor (imageData) {
    return `rgba(${imageData.data[0]}, ${imageData.data[1]}, ${imageData.data[2]}, ${imageData.data[3]})`;
  }
  
	ctx.clearRect(0, 0, canvas.width, canvas.height);

  ctx.globalCompositeOperation = 'color';

  // guidance colors
  Object.entries(ramp).forEach((entry, index) => {
  	ctx.fillStyle = entry[1];
    ctx.fillRect(0, index * 30, 100, 25);
    
    ctx.fillStyle = guidance;
    ctx.fillRect(0, index * 30, 100, 25);
    
    if (index === 0) {
    	let color = getColor(ctx.getImageData(0, 0, 1, 1));
      document.documentElement.style.setProperty('--guidance50', color);
      document.querySelector('.guidance50').setAttribute('title', color);
    } else {
    	let color = getColor(ctx.getImageData(0, index * 30, 1, 1));
      document.documentElement.style.setProperty(`--guidance${index * 100}`, color);
      document.querySelector(`.guidance${index * 100}`).setAttribute('title', color);
    }
  });
  
  // affordance colors
  Object.entries(ramp).forEach((entry, index) => {
  	ctx.fillStyle = entry[1];
    ctx.fillRect(105, index * 30, 100, 25);
    
    ctx.fillStyle = affordance;
    ctx.fillRect(105, index * 30, 100, 25);
    
    if (index === 0) {
    	let color = getColor(ctx.getImageData(105, 0, 1, 1));
      document.documentElement.style.setProperty('--affordance50', color);
      document.querySelector('.affordance50').setAttribute('title',...