Все следующие угловые измерения основаны на обычном математическом смысле: 0 ° направлено горизонтально вправо, углы увеличиваются против часовой стрелки, поэтому 90 ° вверх, 180 ° влево и 270 ° вниз.
Используя цветовое колесо в MS PowerPoint (поскольку оно доступно), значения рассчитываются путем деления круга на 3 сегмента шириной 120 ° с центром в 0 °, 120 ° и 240 ° для красного, зеленого и синего соответственно.
На границах сегментов цвет составляет 100% смежных цветов, поэтому 60 ° - это 100% красный и 100% зеленый.Примыкающий цвет исчезает к центру сегмента, поэтому при 90 ° (на полпути от красной / зеленой границы к зеленому центру) цвет становится на 100% зеленым и на 50% красным.
Это даетсочетание смежных цветов, смешение противоположных цветов основано на расстоянии от центра.
Эта схема отображения не работает для RGB, так как это трехмерное пространство, однако оно дает 2 из 3 измеренийдля HSV, если координаты используются для оттенка и насыщенности и смежного ползунка для значения .Для простоты ниже просто используется диск со значением , установленным на 1.
Полное объяснение приведено на Ручное кодирование цветового круга с канвой .
/* 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}
Если вы создаете цветовое колесо как холст для связанной статьи,тогда, скорее всего, вы можете просто получить цвет под курсором.
hsv2rgb несколько уменьшен по сравнению с оригиналом, но я думаю, что он намного понятнее, поскольку он короче, поскольку существует риск чрезмерного использования:?оператор.