-3

I'm trying to make a color wheel, and I found this, but I need it to look like this one:

Color Wheel

Below is the code I have. I think the only changes there needs to be is:

  • Flip Horizontally
  • Add Border

These can obviously be done through CSS, but I want to edit the code and change it from there. How can I make the changes stated above?

Relevant Code

for (y = input.min = 0; y < width; y++) {
    for (x = 0; x < width; x++) {
      var rx = x - radius,
        ry = y - radius,
        d = rx * rx + ry * ry,
        rgb = hsvToRgb(
          (atan2(ry, rx) + PI) / PI2, // Hue
          sqrt(d) / radius, // Saturation
          1 // Value
        );

      // Print current color, but hide if outside the area of the circle
      pixels[wheelPixel++] = rgb[0];
      pixels[wheelPixel++] = rgb[1];
      pixels[wheelPixel++] = rgb[2];
      pixels[wheelPixel++] = d > radiusSquared ? 0 : two55;
    }
  }

JSFiddle

(function() {

  // Declare constants and variables to help with minification
  // Some of these are inlined (with comments to the side with the actual equation)
  var doc = document;
  doc.c = doc.createElement;
  b.a = b.appendChild;

  var width = c.width = c.height = 400,
    input = b.a(doc.c("input")),
    imageData = a.createImageData(width, width),
    pixels = imageData.data,
    oneHundred = input.value = input.max = 100,
    circleOffset = 10,
    diameter = width - circleOffset * 2,
    radius = diameter / 2,
    radiusSquared = radius * radius,
    two55 = 255,
    currentY = oneHundred,
    wheelPixel = circleOffset * 4 * width + circleOffset * 4;

  // Math helpers
  var math = Math,
    PI = math.PI,
    PI2 = PI * 2,
    sqrt = math.sqrt,
    atan2 = math.atan2;


  // Load color wheel data into memory.
  for (y = input.min = 0; y < width; y++) {
    for (x = 0; x < width; x++) {
      var rx = x - radius,
        ry = y - radius,
        d = rx * rx + ry * ry,
        rgb = hsvToRgb(
          (atan2(ry, rx) + PI) / PI2, // Hue
          sqrt(d) / radius, // Saturation
          1 // Value
        );

      // Print current color, but hide if outside the area of the circle
      pixels[wheelPixel++] = rgb[0];
      pixels[wheelPixel++] = rgb[1];
      pixels[wheelPixel++] = rgb[2];
      pixels[wheelPixel++] = d > radiusSquared ? 0 : two55;
    }
  }
  a.putImageData(imageData, 0, 0);

  function hsvToRgb(h, s, v) {
    h *= 6;
    var i = ~~h,
      f = h - i,
      p = v * (1 - s),
      q = v * (1 - f * s),
      t = v * (1 - (1 - f) * s),
      mod = i % 6,
      r = [v, q, p, p, t, v][mod] * two55,
      g = [t, v, v, q, p, p][mod] * two55,
      b = [p, p, t, v, v, q][mod] * two55;

    return [r, g, b, "rgb(" + ~~r + "," + ~~g + "," + ~~b + ")"];
  }
})();
<canvas id="c"></canvas>
<script>
  var b = document.body;
  var c = document.getElementsByTagName('canvas')[0];
  var a = c.getContext('2d');
</script>
Horay
  • 1,388
  • 2
  • 19
  • 36

1 Answers1

1

I had success by:

  1. Reversing the definition for rx from x - radius to radius - x to flip horizontally
  2. Adding a CSS border and setting the border-radius to 100% to make it circular
  3. Setting the circleOffset to zero to remove space between the color wheel and its border.

(function() {

  var doc = document,
      b = doc.body,
      c = doc.getElementsByTagName('canvas')[0],
      a = c.getContext('2d')
      doc.c = doc.createElement,
      b.a = b.appendChild,
      
      width = c.width = c.height = 175,
      imageData = a.createImageData(width, width),
      pixels = imageData.data,
      circleOffset = 0,
      diameter = width - circleOffset * 2,
      radius = diameter / 2,
      radiusSquared = radius * radius,
      two55 = 255,
      wheelPixel = circleOffset * 4 * width + circleOffset * 4,
        
      math = Math,
      PI = math.PI,
      PI2 = PI * 2,
      sqrt = math.sqrt,
      atan2 = math.atan2;


  // Load color wheel data into memory.
  for (y = 0; y < width; y++) {
    for (x = 0; x < width; x++) {
      
      var rx = radius - x,
          ry = y - radius,
          d = rx * rx + ry * ry,
          rgb = hsvToRgb(
            (atan2(ry, rx) + PI) / PI2, // Hue
            sqrt(d) / radius, // Saturation
            1 // Value
          );

      // Print current color, but hide if outside the area of the circle
      pixels[wheelPixel++] = rgb[0];
      pixels[wheelPixel++] = rgb[1];
      pixels[wheelPixel++] = rgb[2];
      pixels[wheelPixel++] = d > radiusSquared ? 0 : two55;
      
    }
  }
  a.putImageData(imageData, 0, 0);

  function hsvToRgb(h, s, v) {
    h *= 6;
    var i = ~~h,
      f = h - i,
      p = v * (1 - s),
      q = v * (1 - f * s),
      t = v * (1 - (1 - f) * s),
      mod = i % 6,
      r = [v, q, p, p, t, v][mod] * two55,
      g = [t, v, v, q, p, p][mod] * two55,
      b = [p, p, t, v, v, q][mod] * two55;

    return [r, g, b, "rgb(" + ~~r + "," + ~~g + "," + ~~b + ")"];
  }
  
})();
#c {
  border: 1px solid #000;
  border-radius: 100%;
}
<canvas id="c"></canvas>
showdev
  • 28,454
  • 37
  • 55
  • 73
  • Thank you! Doesn't css support hsl? why did the author have to convert it to rgb? – Horay Jan 18 '16 at 23:09
  • How can I change it to have HSL? (instead of the rgb) – Horay Jan 18 '16 at 23:19
  • I haven't really worked with canvas's, so I don't really know what to do. – Horay Jan 18 '16 at 23:31
  • The values need to be converted to RGB because the `imageData.data` array for `` represents "a one-dimensional array containing the data in the RGBA order". See [ImageData.data](https://developer.mozilla.org/en-US/docs/Web/API/ImageData/data). If you're interested, see [Changing pixel in canvas imageData to HSL](http://stackoverflow.com/questions/12061697/changing-pixel-in-canvas-imagedata-to-hsl60-100-50). – showdev Jan 18 '16 at 23:37