Получить актуальный цвет выбора цвета в javascript - PullRequest
0 голосов
/ 29 января 2020

Я хочу создать палитру цветов. Как мне перевести координаты x / y, где человек нажимает, в фактические цвета rgb / hsv / hex / et c?

Вот код:

// jshint esnext:true
const palette = document.getElementsByClassName('fill-color-palette')[0]
palette.addEventListener('click', event => {
  const x = event.clientX - palette.offsetLeft
  const y = event.clientY - palette.offsetTop
  console.log(x, y)
})
.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, rgb(255, 0, 0), rgb(255, 0, 255), rgb(0, 0, 255), rgb(0, 255, 255), rgb(0, 255, 0), rgb(255, 255, 0), rgb(255, 0, 0));
  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;
}
<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>

https://jsbin.com/recayamaro/edit?html, css, js, консоль, выход

1 Ответ

0 голосов
/ 29 января 2020

Я действительно обнаружил, что довольно легко получить цвет. Вам нужен цвет 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>
...