我正在尝试使用十六进制颜色作为提取HSL信息的输入,以便我可以计算梯度光谱上方的位置以放置色点。
在选择颜色选择器或键入颜色时,可以在photoshop中找到一个很好的例子。可以看到另一个示例here:只需键入一种颜色,颜色点就会移到渐变上方的位置。
这是我的代码:
function rgbToHsl(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var d = max - min;
var h;
if (d === 0) h = 0;
else if (max === r) h = (g - b) / d % 6;
else if (max === g) h = (b - r) / d + 2;
else if (max === b) h = (r - g) / d + 4;
var l = (min + max) / 2;
var s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
return [h * 60, s, l];
}
function hslToRgb(h, s, l) {
var c = (1 - Math.abs(2 * l - 1)) * s;
var hp = h / 60.0;
var x = c * (1 - Math.abs((hp % 2) - 1));
var rgb1;
if (isNaN(h)) rgb1 = [0, 0, 0];
else if (hp <= 1) rgb1 = [c, x, 0];
else if (hp <= 2) rgb1 = [x, c, 0];
else if (hp <= 3) rgb1 = [0, c, x];
else if (hp <= 4) rgb1 = [0, x, c];
else if (hp <= 5) rgb1 = [x, 0, c];
else if (hp <= 6) rgb1 = [c, 0, x];
var m = l - c * 0.5;
return [
Math.round(255 * (rgb1[0] + m)),
Math.round(255 * (rgb1[1] + m)),
Math.round(255 * (rgb1[2] + m))
];
}
function hexToRgb(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b){
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ?
[
parseInt(result[1], 16),
parseInt(result[2], 16),
parseInt(result[3], 16)
] : null;
}
function rgbToHex(r, g, b) {
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
function formatAsRGB(rgb) {
return 'rgb(' + rgb[0] + ', ' + rgb[1] + ', ' + rgb[2] + ')';
}
function getDotCoordinates(lightness, saturation, canvasWidth, canvasHeight) {
var x = 0;
var y = 0;
// lighter (going across x-axis)
if (lightness >= .5 && lightness <= 1) {
x = 0;
y = 0;
// darker (going down y-axis)
// on color scale, moving from top to bottom
// lightness between .5 - 1
} else if (lightness >= 0 && lightness <= .5) {
x = (1 - saturation) * canvasWidth;
y = (1 - lightness) * canvasHeight;
}
if (x >= canvasWidth) {
x = canvasWidth - 1;
}
if (y >= canvasHeight) {
y = canvasHeight - 1;
}
return [x, y];
}
var inputColor = '#969141';
var rgbColor = hexToRgb(inputColor);
var hslColor = rgbToHsl(rgbColor[0],rgbColor[1],rgbColor[2]);
var hexColor = rgbToHex(rgbColor[0],rgbColor[1],rgbColor[2]);
var hueColor = hslToRgb(hslColor[0], 1, .5);
var spectrum = $('canvas').get(0);
var ctx = spectrum.getContext('2d');
var colorDot = $('.colorDot');
var colorGradient;
var blackGradient;
var height = 200;
var width = 300;
var positions;
spectrum.width = width;
spectrum.height = height;
ctx.clearRect(0, 0, width, height);
colorGradient = ctx.createLinearGradient(1, 1, width - 1, -1);
colorGradient.addColorStop(0, '#fff');
colorGradient.addColorStop(1, formatAsRGB(hueColor));
ctx.fillStyle = colorGradient;
ctx.fillRect(0, 0, width, height);
blackGradient = ctx.createLinearGradient(0, 0, -1, height - 1);
blackGradient.addColorStop(0, 'transparent');
blackGradient.addColorStop(1, '#000');
ctx.fillStyle = blackGradient;
ctx.fillRect(0, 1, width, height);
// add input color as dot background
colorDot.css('background-color', hexColor);
// get x, y coordinates to position color dot over color spectrum
positions = getDotCoordinates(hslColor[1], hslColor[2], width, height);
// here is the code to position a circle
colorDot.css({
top: positions[0] + 'px',
left: positions[1] + 'px'
});
.container {
position: relative;
}
.colorDot {
width: 20px;
height: 20px;
border-radius: 50%;
border: 2px white solid;
position: absolute;
top: 20px;
left: 20px;
background: transparent;
transform: translate(-50%, -50%);
z-index: 2;
box-shadow: 0 0 5px 2px rgba(0, 0, 0, .05), 1px 1px 3px 1px rgba(0, 0, 0, .15);
}
canvas {
width: 300px;
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div class="container">
<canvas></canvas>
<div class="colorDot"></div>
</div>
答案 0 :(得分:0)
大多数问题是重叠两个渐变不能准确表示颜色空间,而hsl颜色空间看起来却大不相同。我在这里制作了您的选择器的工作版本:https://jsfiddle.net/4sy82q57/
最大的变化是我添加了一个创建hsl背景的功能:
function renderHSL(context, hue, width, height) {
const imgData = context.getImageData(0, 0, width, height);
const pixels = imgData.data;
let x, y, rgb, o;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
o = (y * width + x) * 4;
rgb = hslToRgb(hue, x / width, y / height);
if (x == 100 && y == 100) {
console.log(rgb);
}
pixels[o] = rgb[0];
pixels[o+1] = rgb[1];
pixels[o+2] = rgb[2];
pixels[o+3] = 255;
}
}
context.putImageData(imgData, 0, 0);
}
有了这个,getDotCoordinates函数变得更加简单。