Я действительно обнаружил, что довольно легко получить цвет. Вам нужен цвет HSV, где оттенок равен 0 (красный), а насыщенность и значение рассчитываются путем деления x / y на ширину / высоту. Если у вас есть цвет HSV, вы можете преобразовать его в RGB, чтобы отобразить его в браузере с помощью пользовательской функции.
Вот код. Вы можете выбрать другие значения оттенка / альфа, нажимая кнопки
const current = document.getElementById('current')
const palette = document.getElementsByClassName('fill-color-palette')[0]
const colorPin = palette.getElementsByClassName('pin')[0]
const hueSlider = document.getElementsByClassName('fill-color-hue')[0]
const huePin = hueSlider.getElementsByClassName('pin')[0]
const alphaSlider = document.getElementsByClassName('fill-color-alpha')[0]
const alphaPin = alphaSlider.getElementsByClassName('pin')[0]
palette.addEventListener('click', event => {
const x = event.clientX - palette.offsetLeft
const y = event.clientY - palette.offsetTop
const width = palette.clientWidth
const height = palette.clientHeight
const saturation = parseFloat(x / width)
const value = parseFloat((height - y) / height)
const hue = hueSlider.dataset.value || 0
const alpha = alphaSlider.dataset.value || 1
// update the pin
colorPin.style.left = x + 'px'
colorPin.style.top = y + 'px'
// set the color
const color = HSVtoRGB(hue, saturation, value)
current.textContent = `${color.r},${color.g},${color.b},${alpha}`
current.style.backgroundColor = `rgb(${current.textContent})`
})
hueSlider.addEventListener('click', event => {
const y = event.clientY - hueSlider.offsetTop
const height = hueSlider.clientHeight
const hue = parseFloat(y / height)
// update the pin
huePin.style.top = y + 'px'
// update the palette
const color = HSVtoRGB(hue, 1, 1)
palette.style.backgroundColor = `rgb(${color.r},${color.g},${color.b})`
// set the hue
hueSlider.dataset.value = hue
})
alphaSlider.addEventListener('click', event => {
const y = event.clientY - alphaSlider.offsetTop
const height = alphaSlider.clientHeight
const alpha = parseFloat((height - y) / height)
// update the pin
alphaPin.style.top = y + 'px'
// set the alpha
alphaSlider.dataset.value = alpha
})
function HSVtoRGB (hue, saturation, value) {
let r, g, b
const i = Math.floor(hue * 6)
const f = hue * 6 - i
const p = value * (1 - saturation)
const q = value * (1 - f * saturation)
const t = value * (1 - (1 - f) * saturation)
switch (i % 6) {
case 0:
r = value
g = t
b = p
break
case 1:
r = q
g = value
b = p
break
case 2:
r = p
g = value
b = t
break
case 3:
r = p
g = q
b = value
break
case 4:
r = t
g = p
b = value
break
case 5:
r = value
g = p
b = q
breakreak
}
return {
r: Math.round(r * 255),
g: Math.round(g * 255),
b: Math.round(b * 255)
}
}
.grid {
display: grid;
padding: 5px;
grid-template-columns: 1fr 15px 15px;
column-gap: 10px;
}
.fill-color-palette {
position: relative;
height: 160px;
border-radius: 3px;
background-image: linear-gradient(rgb(0, 0, 0, 0), #000), linear-gradient(to right, #FFF, rgb(255, 255, 255, 0));
}
.fill-color-hue {
position: relative;
width: 15px;
height: 160px;
background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
border-radius: 3px;
}
.fill-color-alpha {
position: relative;
width: 15px;
height: 160px;
background: linear-gradient(to bottom, rgb(0, 0, 0) 0%, transparent 100%) 0% 0% no-repeat local, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACpJREFUeNpi3LFjBwM2oK2tjVWciYFEMKqBGMCCK7yvXr06Gkr00wAQYACiEgXLqZw3aAAAAABJRU5ErkJggg==) 0 0 / 15px repeat local;
border-radius: 3px;
}
.pin {
position: absolute;
width: 15px;
height: 15px;
border: none;
border-radius: 11px;
background-color: #FFF;
box-shadow: rgb(51, 51, 51) 0px 0px 0px 1px inset, rgb(51, 51, 51) 0px 0px 0px 1px;
cursor: pointer;
}
.pin.active {
width: 11px;
height: 11px;
border: 2px solid #FFF;
background-color: transparent;
}
#current {
width: 120px;
height: 20px;
margin: 5px;
border-radius: 3px;
border: 1px solid #000;
}
<div class="grid">
<div class="fill-color-palette" style="background-color: rgb(255, 0, 0);">
<div class="pin active"></div>
</div>
<div class="fill-color-hue">
<div class="pin active"></div>
</div>
<div class="fill-color-alpha">
<div class="pin active"></div>
</div>
</div>
<div id="current"></div>