如何基于X和Y坐标从色轮获取颜色值?

时间:2018-10-10 22:04:23

标签: javascript nativescript

所以我有这个色轮,它将用于拾色器。
我正在通过NativeScript针对移动应用程序进行此操作。而且我想知道如何仅使用X / Y坐标获得RGB 十六进制(,因为我可以使用任何一个)?

{x:0,y:0}的正中央,因此负数将在左侧和上方,而正数在右侧和向下。 我坚持试图弄清楚如何获得颜色。我没有要显示的代码,因为我不知道从哪里开始。

色轮是预制的图像,而不是在使用该应用程序时由我自动用画布生成的图像。

color wheel

3 个答案:

答案 0 :(得分:2)

以下所有角度度量均基于通常的数学意义:0°沿水平方向向右倾斜,因此角度沿逆时针方向增加,因此90°向上,向左180°,向下270°。

使用MS PowerPoint中的色轮(因为它可用),通过将圆分成3个120°宽的部分(分别以红色,绿色和蓝色的0°,120°和240°为中心)来计算值。

在线段边界上,颜色是相邻颜色的100%,因此60°是100%红色和100%绿色。相邻的颜色逐渐淡入分段的中心,因此在90°(从红色/绿色边界向绿色中心的一半距离)处,颜色为100%绿色和50%红色。

这给出了相邻颜色的混合,相反颜色的混合是基于距中心的距离。

此映射方案不适用于RGB,因为它是3维空间,但是如果将坐标用于 hue 饱和度,则它会给出3个HSV维中的2个 value 的相邻滑块。为简单起见,以下仅使用 value 设置为1的光盘。

完整的解释在Hand-coding a color wheel with canvas

/* Convert radians to degrees.
 *
 * @param {number} rad - radians to convert, expects
 *                       rad in range +/- PI per Math.atan2
 * @returns {number} degrees equivalent of rad
 */
function rad2deg(rad) {
  return (360 + 180 * rad / Math.PI) % 360;
}

/* Convert h,s,v values to r,g,b
 * See: https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV
 *
 * @param {number} hue - in range [0, 360]
 * @param {number} saturation - in range 0 to 1
 * @param {number} value - in range 0 to 1
 * @returns {Array|number} [r, g,b] in range 0 to 255
 */
function hsv2rgb(hue, saturation, value) {
  hue /= 60;
  let chroma = value * saturation;
  let x = chroma * (1 - Math.abs((hue % 2) - 1));
  let rgb = hue <= 1? [chroma, x, 0]:
            hue <= 2? [x, chroma, 0]:
            hue <= 3? [0, chroma, x]:
            hue <= 4? [0, x, chroma]:
            hue <= 5? [x, 0, chroma]:
                      [chroma, 0, x];

  return rgb.map(v => (v + value - chroma) * 255);
}

/* Convert cartesian coordinates to RGB
 * Converts: x, y to polar (radial_distance, angle), then
 *           polar to HSV, then
 *           HSV to RGB
 *
 * @param {number} x - x coordinate in range -1 to 1
 * @param {number} y - y coordinate in range -1 to 1
 * @returns {Array|number} [red, green, blue] values in range 0 to 255
 */
function rectToRGB(x, y) {
  // Hue is from angle, saturation from distance from centre, value set to 1
  var r = Math.sqrt(x*x + y*y);
  // Limit extent to disc
  var sat = r > 1? 0 : r;
  var hsv = [rad2deg(Math.atan2(y, x)), sat, 1];
  var rgb = hsv2rgb(...hsv).map(Math.round);
  return rgb;
}

function posToColour(evt) {
  var node = this;
  var originOffset = node.width / 2;
  var offsetLeft = offsetTop = 0;
  
  do {
    offsetLeft += node.offsetLeft;
    offsetTop  += node.offsetTop;
    node = node.offsetParent;
  } while (node.offsetParent)
    
  // Adjust coordinates then scale to range -1 to 1
  var x = ((evt.x - offsetLeft - originOffset) / originOffset).toFixed(2);
  var y = ((originOffset - evt.y + offsetTop) / originOffset).toFixed(2);

  var rgb = rectToRGB(x, y);
  
  var patch = document.getElementById('colorPatch');
  patch.style.backgroundColor = `rgb(${rgb.join()})`;
  document.getElementById('data').innerHTML = 
    `x, y : ${(x<0?'':' ')+x}, ${(y<0?'':' ')+y}<br>r,g,b: ${rgb.map(x=>('  '+x).slice(-3)).join(', ')}`;
}

document.addEventListener('DOMContentLoaded', function() {
  document.getElementById('colourDisc').addEventListener('mousemove', posToColour, false);
}, false);
img {width:200px;height:200px;}
div {width: 90px; height: 90px}
<table>
 <tr>
   <td><img src="https://i.stack.imgur.com/lPPOO.png" id="colourDisc"></td>
   <td><div id="colorPatch"></div>
       <div><pre id="data"></pre></div></td>
</table>

如果您根据链接的文章将色轮生成为画布,那么很可能只需在光标下找到颜色即可。

hsv2rgb 相对于原始版本略有缩小,但是我认为它更短更清楚,但有过度使用:?的危险。运算符。

答案 1 :(得分:0)

您似乎要排除一些细节,我假设您已经有一个坐标转换方法或其他东西,我知道您有一个画布,因此您具有画布api和图像数据。

function getRGB(x, y, canvas) {
  let context = canvas.getContext('2d');
  let [red, green, blue, alpha] = context.getImageData(x, y, 1, 1).data;
  return {red, green, blue, alpha};
} 

答案 2 :(得分:-1)

从此轮获取颜色的简单方法是将其获取为Hsl,然后将其转换为RGB(或十六进制)。色相和饱和度值很容易从圆上确定tan(hue)= y / x;色相=色相%360 //饱和度=√(x²+y²)* 100 /半径。但是亮度值无法从图片中确定,因此我会选择50%。