online hexadecimal convertir color javascript canvas colors

javascript - hexadecimal - rgba color



Calcule la posición de píxeles X, Y en el gradiente basado en el color hexadecimal utilizando Javascript (2)

Tengo un lienzo de degradado HSV de raindow que cuando hace clic en él, se agrega un elemento en esa ubicación con su fondo como el color del píxel en el que se hace clic.

Lo que me gustaría es hacer que funcione a la inversa también. Por ejemplo, si tiene un color hexadecimal, me gustaría encontrar ese píxel en el lienzo y crear un elemento en esa posición.

Mi primer pensamiento fue usar de alguna manera un sistema matriz / cuadrante. Lo siguiente que pensé fue que, dado que estoy usando HSV, podría usar mis puntos de ubicación del gradiente HSV para descubrir la ubicación. El problema es que mis puntos no son equidistantes entre sí, lo que lo hace más difícil. Además de eso, tengo un degradado blanco y un degradado negro que cubre el gradiente de color principal y necesito que se tenga en cuenta.

Entonces mi pregunta es, ¿cómo puedo encontrar la posición del píxel de color o al menos la coincidencia más cercana usando solo un código hexadecimal?

Aquí está mi código hasta ahora: http://codepen.io/shelbywhite/pen/EyqPWY?editors=1000

HTML:

<div class="container"> <canvas class="colorSpectrum"></canvas> <div class="circle"></div> </div>

CSS:

.container { background: grey; height: 350px; width: 400px; } .circle { background: transparent; box-shadow: 0 0 8px rgba(0,0,0,0.2); border-radius: 50%; border: 2px solid #fff; height: 20px; margin: -12px; width: 20px; position: absolute; } .colorSpectrum { display: block; height: 100%; transform: translateZ(0); width: 100%; }

Javascript:

$(function() { var closest = function(num, arr) { var curr = arr[0]; var diff = Math.abs(num - curr); for (var val = 0; val < arr.length; val++) { var newdiff = Math.abs(num - arr[val]); if (newdiff < diff) { diff = newdiff; curr = arr[val]; } } return curr; }; var container = $(''.container''); var containerWidth = container.width(); var containerHeight = container.height(); var verticalGradientsHeight = Math.round(containerHeight * .34); console.log(''verticalGradientsHeight'', verticalGradientsHeight); var round = function(value, decimals) { return Number(Math.round(value+''e''+decimals)+''e-''+decimals); }; // Draws the color spectrum onto the canvas var drawColorSpectrum = function() { // Cache canvas element var canvasElement = $(''.colorSpectrum''); // Cache javascript element var canvas = canvasElement[0]; // Get canvas context var ctx = canvas.getContext(''2d''); // Cache page height var canvasWidth = containerWidth; // Cache page height var canvasHeight = containerHeight - 72; // Bottom gradient start position var blackStartYPos = canvasHeight - verticalGradientsHeight; // Bottom gradient end position var blackEndYPos = canvasHeight; // Create white gradient element var white = ctx.createLinearGradient(0, 0, 0, verticalGradientsHeight); // Create black gradient element var black = ctx.createLinearGradient(0, blackStartYPos, 0, blackEndYPos); // Create new instance of image var img = new Image(); // Cache container _colorSpectrumContainer = canvasElement.parent(); // Set global var spectrumCanvas = canvasElement; // Set width of canvas canvas.width = canvasWidth; // Set height of canvas canvas.height = canvasHeight; // Image load listener img.onload = function() { // Draw intial image ctx.drawImage(this, 0, 0, canvasWidth, canvasHeight); // Draw white to transparent gradient white.addColorStop(0, "hsla(0,0%,100%,1)"); white.addColorStop(0.05, "hsla(0,0%,100%,1)"); white.addColorStop(0.20, "hsla(0,0%,100%,0.89)"); white.addColorStop(0.38, "hsla(0,0%,100%,0.69)"); white.addColorStop(0.63, "hsla(0,0%,100%,0.35)"); white.addColorStop(0.78, "hsla(0,0%,100%,0.18)"); white.addColorStop(0.91, "hsla(0,0%,100%,0.06)"); white.addColorStop(1, "hsla(0,0%,100%,0)"); ctx.fillStyle = white; ctx.fillRect(0, 0, canvasWidth, verticalGradientsHeight); // Draw black to transparent gradient black.addColorStop(0, "hsla(0,0%,0%,0)"); black.addColorStop(0.20, "hsla(0,0%,0%,0.01)"); black.addColorStop(0.28, "hsla(0,0%,0%,0.04)"); black.addColorStop(0.35, "hsla(0,0%,0%,0.09)"); black.addColorStop(0.51, "hsla(0,0%,0%,0.26)"); black.addColorStop(0.83, "hsla(0,0%,0%,0.69)"); black.addColorStop(1, "hsla(0,0%,0%,1)"); ctx.fillStyle = black; ctx.fillRect(0, blackStartYPos, canvasWidth, verticalGradientsHeight); } // Set image source img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAABCAYAAACbv+HiAAAA0ElEQVR4AYWSh2oDMAwFz6u7//+d2YmXalGBIBM47nnPIIEtmd8FGBTgDbPxDmbn49pX+cZX+Nz4mkZ2SECEAXTCAprlalntBC5whdUJnOfKEy5DjZYtB+o0D3XUMk0tkaZZEn2VuyiJQQQywS/P4c25ucTrfF3ndsoVdjmy3NMiuptR1eHfNcBFM2orW1ZXru00JZiBDrIII5AG5AlloX5TcG6/ywuuv0zAbyL4TWRZmIvU5TNBTjCPIIu5N3YgO7Wxtbot3q4+2LgTyFnZ/QHzBZD1KDpyqQAAAABJRU5ErkJggg=="; }; // var hexToRgb = function(hex) { hex = hex.replace(''#'',''''); r = parseInt(hex.substring(0, 2), 16); g = parseInt(hex.substring(2, 4), 16); b = parseInt(hex.substring(4, 6), 16); return [r, g, b]; }; // var rgbToHsb = function(r, g, b) { var rr, gg, bb, r = r / 255, g = g / 255, b = b / 255, h, s, v = Math.max(r, g, b), diff = v - Math.min(r, g, b), diffc = function(c){ return (v - c) / 6 / diff + 1 / 2; }; if (diff == 0) { h = s = 0; } else { s = diff / v; rr = diffc(r); gg = diffc(g); bb = diffc(b); if (r === v) { h = bb - gg; }else if (g === v) { h = (1 / 3) + rr - bb; }else if (b === v) { h = (2 / 3) + gg - rr; } if (h < 0) { h += 1; }else if (h > 1) { h -= 1; } } return { h: Math.round(h * 360), s: Math.round(s * 100), b: Math.round(v * 100) }; }; // Find hue in stop range var findHueInStopRange = function(hue) { // Array of hue stops with HSV, RGB, and HEX info var stops = [{ h: 0, l: 0, s: 100, b: 100 }, { h: 60, l: 21, s: 100, b: 100 }, { h: 120, l: 40, s: 85, b: 85 }, { h: 180, l: 56, s: 85, b: 85 }, { h: 237, l: 72, s: 86, b: 96 }, { h: 300, l: 89, s: 86, b: 96 }, { h: 359, l: 100, s: 100, b: 100 }]; // Total number of stops var stopsLength = stops.length; // Loop through stops for (var i = 0; i < stopsLength; i += 1) { // Temp set var currentStop = stops[i]; // Temp set // var nextStop = stops[i + 1]; var nextStop = (i + 1 > stopsLength - 1) ? currentStop : stops[i + 1]; // Location is a percentage var huePos; // Temp set var xPos = false; console.log(''hue'', currentStop.h, ''>>'', hue, ''<<'', nextStop.h); // Find which range of hue stops the current color is // Hue is between current and next hue stop if (hue >= currentStop.h && hue <= nextStop.h) { // hue is current stop if (hue === currentStop.h) { // Set as location huePos = currentStop.l; // hue is next stop } else if (hue === nextStop.h) { // Set as location huePos = nextStop.l; // Hue is somewhere between stops } else { // Get percentage location between hue stops var relativeHuePos = (hue - currentStop.h) / (nextStop.h - currentStop.h); // Normalized to fit custom gradient stop locations huePos = relativeHuePos * (nextStop.l - currentStop.l) + currentStop.l; } // A location was found if (huePos) { // Convert from percentage to pixel position xPos = Math.round(containerWidth * (huePos / 100)); return xPos; } else { continue; } } } }; // Find saturation in stop range var findSaturationInStopRange = function (saturation) { // Array of hue stops with HSV, RGB, and HEX info var stops = [{ l: 0, s: 0 }, { l: 0.05, s: 6 }, { l: 0.20, s: 18 }, { l: 0.38, s: 35 }, { l: 0.63, s: 69 }, { l: 0.78, s: 89, }, { l: 0.91, s: 100, }, { l: 1, s: 100, }]; // Total number of stops var stopsLength = stops.length; // Loop through stops for (var i = 0; i < stopsLength; i += 1) { // Temp set var currentStop = stops[i]; // Temp set var nextStop = (i + 1 > stopsLength - 1) ? currentStop : stops[i + 1]; // Location is a percentage var satPos; // Temp set var yPos = false; // Convert location to percentage var currentStopLocation = currentStop.l * 100; // Convert location to percentage var nextStopLocation = nextStop.l * 100; // Find which range of hue stops the current color is // Hue is between current and next hue stop if (saturation >= currentStop.s && saturation <= nextStop.s) { // hue is current stop if (saturation === currentStop.s) { // Set as location satPos = currentStopLocation; // hue is next stop } else if (saturation === nextStop.s) { // Set as location satPos = nextStopLocation; // Hue is somewhere between stops } else { // Get percentage location between gradient stops var ratioBetweenSaturation = (saturation - currentStop.s) / (nextStop.s - currentStop.s); // Normalized to fit custom gradient stop locations satPos = ratioBetweenSaturation * (nextStopLocation - currentStopLocation) + currentStopLocation; } console.log(''ratioBetweenSaturation'', ratioBetweenSaturation); console.log(''satPos'', satPos); console.log(''saturation'', saturation, ''>='', currentStop.s, saturation, ''<='', nextStop.s); // A location was found if (satPos !== false) { // Convert from percentage to pixel position yPos = Math.round(verticalGradientsHeight * (satPos / 100)); return yPos; } else { continue; } } } }; // Find brightness in stop range var findBrightnessInStopRange = function (brightness) { // Array of hue stops with HSV, RGB, and HEX info var stops = [{ l: 0, b: 100 }, { l: 0.20, b: 88 }, { l: 0.28, b: 69 }, { l: 0.35, b: 26 }, { l: 0.51, b: 9 }, { l: 0.83, b: 4, }, { l: 1, b: 0, }]; // Total number of stops var stopsLength = stops.length; // Loop through stops for (var i = 0; i < stopsLength; i += 1) { // Temp set var currentStop = stops[i]; // Temp set var nextStop = (i + 1 > stopsLength - 1) ? currentStop : stops[i + 1]; // Location is a percentage var brightPos; // Temp set var yPos = false; // Convert location to percentage var currentStopLocation = currentStop.l * 100; // Convert location to percentage var nextStopLocation = nextStop.l * 100; console.log(''brightness'', brightness, ''>='', currentStop.b, brightness, ''<='', nextStop.b); // Find which range of hue stops the current color is // Hue is between current and next hue stop if (brightness <= currentStop.b && brightness >= nextStop.b) { // hue is current stop if (brightness === currentStop.b) { // Set as location brightPos = currentStopLocation; // hue is next stop } else if (brightness === nextStop.b) { // Set as location brightPos = nextStopLocation; // Hue is somewhere between stops } else { // Get percentage location between gradient stops var ratioBetweenBrightness = (brightness - currentStop.b) / (nextStop.b - currentStop.b); // Normalized to fit custom gradient stop locations brightPos = ratioBetweenBrightness * (nextStopLocation - currentStopLocation) + currentStopLocation; } console.log(''ratioBetweenBrightness'', ratioBetweenBrightness); console.log(''brightPos'', brightPos); console.log(''brightness'', brightness, ''>='', currentStop.b, brightness, ''<='', nextStop.b); // A location was found if (brightPos !== false) { // Convert from percentage to pixel position yPos = Math.round(verticalGradientsHeight * (brightPos / 100)); return yPos; } else { continue; } } } }; // Get coordinates from hue, brightness, saturation var getColorCoordinates = function (hex) { // Convert hex to rgb var rgb = hexToRgb(hex); console.log(''rgb'', rgb); // Convert rgb to hsb var hsb = rgbToHsb(rgb[0], rgb[1], rgb[2]); console.log(''hsb'', hsb); // Set x position to position of hue var xPos = findHueInStopRange(hsb.h); var yPos = 0; // if 100, get (containerHeight - verticalGradientHeight) + whatever position is set with bottom gradient // // Saturation and brightness are both maxed if (hsb.s === 100 && hsb.b === 100) { // Set y position at center of container yPos = containerHeight * 0.5; } else { console.log(''using nothing'', hsb.s, hsb.b); // if (hsb.s < 100) { // Saturation y position (upper quadrant) yPos = findSaturationInStopRange(hsb.s); console.log(''using saturation'', yPos); } else if (hsb.b < 100) { // Brightness y position (lower quadrant) yPos = findBrightnessInStopRange(hsb.b); console.log(''using brightness'', yPos); } } return { x: xPos, y: yPos }; } // Get hue location var position = false; // Temp set var hex = ''42ad40''; // Draw gradient drawColorSpectrum(); // Find x position position = getColorCoordinates(hex); //91ff26 console.log(''location'', position); // Draw line $(''.circle'').css({ top: position.y + ''px'', left: position.x + ''px'', background: ''#'' + hex }); });

** ACTUALIZACIÓN **

En realidad estoy tratando de hacer esto en HSV no HSL. No tengo más preferencia que usar Photoshop para generar un degradado suave.

Además, he agregado un nuevo ejemplo con lo que he creado. Una de las respuestas más votadas abajo indica cómo lograr lo que trato de hacer, pero hasta ahora no he podido hacerlo con éxito.

El código actualizado estará en este enlace, también he actualizado el código anterior: http://codepen.io/shelbywhite/pen/EyqPWY?editors=1000


Para obtener la ubicación, necesita los valores de HSL

// global var RGB = [0,0,0]; // holds the RGB values 0-255 var LSH = [0,0,0]; // holds the LSH values (note H is normalised to 0-255) var rgbToLSH = function(){ var r = RGB[0]/255; var g = RGB[1]/255; var b = RGB[2]/255; var min = Math.min(r,g,b); var max = Math.max(r,g,b); var lum = (min+max)/2; if(lum > 0.5){ var sat = (max-min)/(max+min); }else{ var sat = (max-min)/(2-max-min); } if(r >= b && r >= g){ var hue = (g-b)/(max-min); }else if(b >= b && b >= g){ var hue = 4.0 + (r-g)/(max-min); }else{ var hue = 2.0 + (b-r)/(max-min); } hue *= 60; if(hue < 0) hue += 360; hue = (hue/360); lum = Math.min(1,Math.max(0,lum)); sat = Math.min(1,Math.max(0,sat)); hue = Math.min(1,Math.max(0,hue)); LSH[0] = lum*255; LSH[1] = sat*255; LSH[2] = hue*255; }

Hue dará la posición en el eje xy Saturación te dará y de arriba a la mitad y la luminosidad te dará la posición del eje y desde la mitad hasta la parte inferior (siguiendo tu ejemplo);


Podría iterar sobre todo ImageData y comparar ambos colores.

var findPixelByHex = function(imageData, hex) { var d = imageData.data var w = imageData.width var h = imageData.height for (var y = 0; y < h; ++y) { for (var x = 0; x < w; ++x) { var i = (y * w + x) * 4 if (hex === rgbToHex(d[i], d[i + 1], d[i + 2])) { setColorAtPixel(x, y, hex) } } } }

Tenga en cuenta que esto es bastante lento y no es la mejor idea.