JSFiddle - React, Tailwind, and code Playground

by Raphael Quintao

HTML

<div class="mode1 wheel">1</div>
<div class="mode2 wheel"></div>
<div class="mode3 wheel"></div>
<div class="mode4 wheel"></div>
<svg xmlns="http://www.w3.org/2000/svg" class="gradient-svg"
    width="150"
    viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="49" stroke="blue" stroke-width="2"/>
</svg>
<div class="square">
<div class="l"></div>
<div class="r"></div>
</div>

CSS

html {
  display: flex;
  justify-content: center;
  background-color: #333333;
  --qp-alpha: 1;
}

body {
  display: flex;
  flex-wrap: wrap;
  background-color: #4f4f4f;
  margin: 0;
  gap: 10px;
  padding: 10px;
}

.wheel {
  display: block;
  width: 150px;
  height: 150px;
  border-radius: 50%;
  border: 0px solid black;
  background-clip: content-box;
}

.mode1 {
  background-image: conic-gradient(from 0deg in oklch longer hue, hsl(0, 100%, 50%), hsl(0, 100%, 50%));
  /* background-image: conic-gradient(from 0deg in okhsl, red, red); */
  /* Optional: Add a shadow for better visual separation */
}

.mode2 {
  background-image:
    radial-gradient(circle closest-side, white, transparent),
    conic-gradient(from 0deg in hsl longer hue, red, red);
}
.mode3 {
  background-image:
    radial-gradient(
      circle closest-side,
      hsl(0, 0%, 100%),
      hsl(0 0% 0% / 0.0)
    ),
    conic-gradient(from 0deg in hsl longer hue, red, red);
  background-size: 100% 100%;
  background-repeat: no-repeat no-repeat;
  background-blend-mode: hard-light;
}

.gradient-svg {
  /* fill: red; */
  color: red;
  mask-image: conic-gradient(from 0deg in hsl longer hue, red, red);
  mask-size: 100%;
}

.square {
  width: 150px;
  height: 150px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  background-color: black;
  --q-base: oklch(0.26 0.07944379 25.84675803);
  .l {
    background-color: oklch(from var(--q-base) 0.46 c h / 1);
  }
  .r {
    background-color: oklch(from var(--q-base) calc(l + 0.2) c h / 1);
  }
}

JavaScript

/**
 * Use canvas to generate a color wheel image and set it as the background of the color area.
 */
function gen_color_wheel(size = 150) {
  const get_angle = (x, y, center_x, center_y) => {
    const angle_rad = Math.atan2(y - center_x, x - center_y);
    let angle_deg = (angle_rad * 180) / Math.PI;
    if (angle_deg < 0) angle_deg += 360;
    return angle_deg;
  };
  
  const canvas = document.createElement('canvas');
  canvas.width = size;
  canvas.height = size;
  // document.body.append(canvas);
  // const canvas = new OffscreenCanvas(size + 10, size + 10);
  
  const ctx = canvas.getContext('2d');
  ctx.imageSmoothingEnabled = true;
  const width = canvas.width;
  const height = canvas.height;
  const center_x = width / 2;
  const center_y = height / 2;
  const max_radius = Math.min(width, height) / 2;
  
  for (let x = 0; x < width; x++) {
    for (let y = 0; y < height; y++) {
      const dx = x - center_x;
      const dy = y - center_y;
      const distance = Math.sqrt(dx * dx + dy * dy);
      
      if (distance <= max_radius) {
        const hue = get_angle(x, y, center_x, center_y) + 90;
        const saturation = (distance / max_radius) * 100;
        const lightness = 50;
        const alpha = 1;
        
        ctx.fillStyle = `hsla(${hue}, ${saturation}%, ${lightness}%, ${alpha})`;
        ctx.fillRect(x, y, 1, 1);
      }
    }
  }
  
  return canvas.toDataURL('image/png');
}

const data_url = gen_color_wheel(200);
let el = document.querySelector(".mode4");
el.style.backgroundImage = 'url(' + data_url + ')';
el.style.backgroundPosition = 'center';
el.style.backgroundSize = 'auto';