Фронтенд реализует функцию палитры цветов

JavaScript
Фронтенд реализует функцию палитры цветов

Позвольте мне найти идею

Хотя у нас есть готовые элементы управления HTML, есть две вещи, которые заставляют нас отказаться от них.

  • Функция не может быть настроена
  • Различные стили браузера не одинаковы

Итак, давайте реализуем его сами ~

Старые правила, нет идеи найти проект, на этот раз проект, который я нашел, называется Iconfont.

Затем найдите другой значок кармы.

Кашель, на саму иконку плевать, мы видим, что здесь есть палитра цветов, давайте нажмем на нее и посмотрим.

Видно, что эта палитра цветов состоит из трех частей.

  • доска для хранения цветов
  • область выбора цвета
  • Поле ввода и кнопка подтверждения

Начнем с того, как реализована область выбора цвета, ведь это ядро ​​палитры цветов.

видно что черезsvgдостигать,svgЧто это такое, здесь не будем вдаваться в подробности.

Цветной блок, помеченный как один, находится черезsvgдваrectопределять.

<rect x="0" y="0" width="100%" height="100%" fill="url(#gradient-white)"></rect>
<rect x="0" y="0" width="100%" height="100%" fill="url(#gradient-black)"></rect>

x,y,width,heightЭти четыре параметра устанавливают для цветового блока ширину и высоту всего родительского элемента.

Такfill="url(#gradient-white)"Что представляет собой этот параметр?

После поиска я получил следующие результаты:

Это для достижения эффекта градиента, вы можете использоватьurl(#gradient-white)Градиент соответствующего элемента устанавливается равнымrectначальство.

#gradient-whiteЯвляетсяsvgсерединаdefsназываетсяlinearGradientЭлементы.

<defs>Это вещь:

SVG позволяет нам определять графические элементы, которые нам нужно повторно использовать позже. Рекомендуется определить все ссылочные элементы, которые необходимо повторно использовать, в элементе defs. Это повышает удобочитаемость и доступность содержимого SVG. Графические элементы, определенные в элементе defs, не визуализируются напрямую. Вы можете использовать в любом месте вашего окна просмотра<use>element отображает эти элементы. - МДН

<linearGradient>Это вещь:

Элемент linearGradient используется для определения линейного градиента, который используется для заливки или обводки графических элементов. - МДН

существуетIconfontМы также можем найти соответствующий элемент в .

Видно, что есть два разных градиента: один начинается с белого, а другой начинается с черного.

Почему здесь два градиента?

При нормальных обстоятельствах:

После скрытия черного блока градиента:

Сравнив их, нетрудно обнаружить, что черный градиентный блок идет сверху вниз, а белый градиентный блок — слева направо.Наложение двух — это эффект, который мы видим.

посмотри на это дальше<linearGradient>как это определяется.

<defs>
    <!-- 渐变1 -->
    <linearGradient id="gradient-black" x1="0%" y1="100%" x2="0%" y2="0%">
    	<stop offset="0%" stop-color="#000000" stop-opacity="1"></stop>
        <stop offset="100%" stop-color="#CC9A81" stop-opacity="0"></stop>
    </linearGradient>
    <!-- 渐变2 -->
    <linearGradient id="gradient-white" x1="0%" y1="100%" x2="100%" y2="100%">
    	<stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"></stop>
        <stop offset="100%" stop-color="#CC9A81" stop-opacity="0"></stop>
    </linearGradient>
</defs>

<linearGradient>Атрибуты тега x1, x2, y1, y2 определяют, где начинается и заканчивается градиент.

Цветовой диапазон градиента может состоять из двух или более цветов. каждый цвет через<stop>метка для указания. Свойство смещения используется для определения начала и конечного положения градиента. -w3school

элемент<stop>Определение:

Цветовая шкала на градиенте, определяемом стоп-элементом. Стопорный элемент может быть<linearGradient>элемент или<radialGradient>Дочерние элементы элемента. - МДН

Так<stop>надstop-colorтак же какstop-opacityЧто тогда?

На самом деле, как следует из названия, это цвет и прозрачность, где градиент останавливается.

Тогда видно, что:

  • Градиент 1
    • <linearGradient>Определенныйx1="0%" y1="100%" x2="0%" y2="0%"Представляет линейный градиент от нижнего левого угла к верхнему левому
    • Первый<stop>Определенныйoffset="0%" stop-color="#FFFFFF" stop-opacity="1"Цвет, обозначающий начальную позицию,#FFFFFF, прозрачность равна 1
    • второй<stop>Определенныйoffset="100%" stop-color="#CC9A81" stop-opacity="0"Цвет, указывающий конечное положение,#CC9A81Прозрачность 0.
  • Градиент 2
    • <linearGradient>Определенныйx1="0%" y1="100%" x2="100%" y2="100%"Представляет линейный градиент от левого нижнего угла к правому нижнему

Давайте посмотрим, как реализован длинный цветовой блок справа:

<linearGradient id="gradient-hsv" x1="0%" y1="100%" x2="0%" y2="0%">
    <stop offset="0%" stop-color="#FF0000" stop-opacity="1"></stop>
    <stop offset="13%" stop-color="#FF00FF" stop-opacity="1"></stop>
    <stop offset="25%" stop-color="#8000FF" stop-opacity="1"></stop>
    <stop offset="38%" stop-color="#0040FF" stop-opacity="1"></stop>
    <stop offset="50%" stop-color="#00FFFF" stop-opacity="1"></stop>
    <stop offset="63%" stop-color="#00FF40" stop-opacity="1"></stop>
    <stop offset="75%" stop-color="#0BED00" stop-opacity="1"></stop>
    <stop offset="88%" stop-color="#FFFF00" stop-opacity="1"></stop>
    <stop offset="100%" stop-color="#FF0000" stop-opacity="1"></stop>
</linearGradient>

Здесь, используя знания, которые мы узнали выше, мы можем легко понять, что это значит.

Теперь, когда я могу рисовать, как мне получить цвет указанной позиции?

Сообщив об ошибке, я узнал, что он используетHSVЦветовая модель для установки.

Здесь стоит упомянуть, что человек, который знает Али, быстро попросил его исправить ошибку: цветной блок нельзя перетащить, и как только он будет перетянут, будет сообщено об ошибке.

ТакHSVЧто такое цветовая модель?

HSV (Hue, Saturation, Value) — это цветовое пространство, созданное А. Р. Смитом в 1978 году на основе интуитивных характеристик цвета, также известное как модель Hexcone.

Параметры цвета в этой модели: оттенок (H), насыщенность (S), яркость (V). -Энциклопедия Байду

  • Оттенок H измеряется по углу, диапазон значений составляет 0°~360°.
  • Насыщенность S представляет степень близости цвета к спектральному цвету, и значение находится в диапазоне от 0% до 100%.
  • Яркость V представляет собой яркость цвета, диапазон значений составляет 0%~100%.

Из приведенного выше диапазона значений мы можем получить желаемый цвет путем расчета.

Так как же рассчитывается цвет?

давайте оставимIconfontКод, в конце концов, был запутан, и читать его немного утомительно.

Во-первых, нам нужноHSVсерединаHОтсортирован цветовой тон, который представляет собой длинный цветовой блок справа.

Вот простая реализация:

// index.html
<div class="H">
  <svg>
    <defs>
      <linearGradient id="gradient-hsv" x1="0%" y1="100%" x2="0%" y2="0%">
        <stop offset="0%" stop-color="#FF0000" stop-opacity="1"></stop>
        <stop offset="13%" stop-color="#FF00FF" stop-opacity="1"></stop>
        <stop offset="25%" stop-color="#8000FF" stop-opacity="1"></stop>
        <stop offset="38%" stop-color="#0040FF" stop-opacity="1"></stop>
        <stop offset="50%" stop-color="#00FFFF" stop-opacity="1"></stop>
        <stop offset="63%" stop-color="#00FF40" stop-opacity="1"></stop>
        <stop offset="75%" stop-color="#0BED00" stop-opacity="1"></stop>
        <stop offset="88%" stop-color="#FFFF00" stop-opacity="1"></stop>
        <stop offset="100%" stop-color="#FF0000" stop-opacity="1"></stop>
      </linearGradient>
    </defs>
    <rect x="0" y="0" width="100%" height="100%" fill="url(#gradient-hsv)"></rect>
  </svg>
  <div class="slide"></div>
</div>

<div class="color">
  <h2>rgb(102, 81, 192)</h2>
  <div class="show" style="background: rgb(102, 81, 192);">

  </div>
</div>
// style.css
svg{
  width: 100%;
  height: 100%;
}

.H{
  width: 20px;
  height: 200px;
  position: relative;
}

.slide{
  position: absolute;
  left: 4px;
  top: -8px;
  border: 8px solid transparent;
  border-right-color: #888;
  width: 0;
  height: 0;
  pointer-events: none;
}

.show{
  width: 300px;
  height: 100px;
}
// app.js
let H = document.querySelector('.H');
let HRect = H.querySelector('rect');
let HSlide = H.querySelector('.slide')
let HFlag = false;

let Hval = 0;
let Sval = 100;
let Vval = 100;

HRect.addEventListener('mousedown', () => {
  HFlag = true;
})
HRect.addEventListener('mousemove', ev => {
  if(!HFlag) return;

  // ev.offsetY这个值为鼠标相对于源元素的Y坐标,算出滑块在元素中的定位比例
  let offsetY = ev.offsetY / H.offsetHeight;

  HSlide.style.top = ev.offsetY - 8 + 'px'

  // 因为H值的范围是0~360,乘以比例就可以得出一个颜色值了
  Hval = 360 * offsetY;

  setHSV();
})
HRect.addEventListener('mouseup', () => {
  HFlag = false;
})

let colorEl = document.querySelector('.color');
let colorTitle = colorEl.querySelector('h2');
let colorShow = colorEl.querySelector('.show');

function setHSV(){
  // 这里算出对应的RGB值
  let color = `
    rgb(${hsvtorgb(Hval, Sval, Vval).join(',')})
  `

  colorTitle.innerHTML = color;
  colorShow.style.background = color;
}

setHSV();

Также есть функцияhsvtorgb, потому что я скопировал этот код у кого-то другого, поэтому выложу его отдельно.

Источник:блог woo woo woo.cn on.com/brain world/…

function hsvtorgb(h, s, v) {
  s = s / 100;
  v = v / 100;
  var h1 = Math.floor(h / 60) % 6;
  var f = h / 60 - h1;
  var p = v * (1 - s);
  var q = v * (1 - f * s);
  var t = v * (1 - (1 - f) * s);
  var r, g, b;
  switch (h1) {
    case 0:
      r = v;
      g = t;
      b = p;
      break;
    case 1:
      r = q;
      g = v;
      b = p;
      break;
    case 2:
      r = p;
      g = v;
      b = t;
      break;
    case 3:
      r = p;
      g = q;
      b = v;
      break;
    case 4:
      r = t;
      g = p;
      b = v;
      break;
    case 5:
      r = v;
      g = p;
      b = q;
      break;
  }
  return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}

На самом деле я не понимаю алгоритм выше. собачья голова 🐶

Приведенный выше код обеспечивает следующие эффекты:

Тогда мы понимаемHSVПредставитель в КитаеSVцветной блок

Поскольку я не хочу писать слишком долго, я покажу измененную часть кода:

// index.html
<div class="HSV">
  <div class="SV">
    <svg>
      <defs>
        <linearGradient id="gradient-black" x1="0%" y1="100%" x2="0%" y2="0%">
          <stop offset="0%" stop-color="#000000" stop-opacity="1"></stop>
          <!-- endColor -->
          <stop class="endColor" offset="100%" stop-color="#CC9A81" stop-opacity="0"></stop>
        </linearGradient>
        <linearGradient id="gradient-white" x1="0%" y1="100%" x2="100%" y2="100%">
          <stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"></stop>
          <!-- endColor -->
          <stop class="endColor" offset="100%" stop-color="#CC9A81" stop-opacity="0"></stop>
        </linearGradient>
      </defs>
      <rect x="0" y="0" width="100%" height="100%" fill="url(#gradient-white)"></rect>
      <rect x="0" y="0" width="100%" height="100%" fill="url(#gradient-black)"></rect>
    </svg>
    <div class="slide"></div>
  </div>

  <div class="H">
  	// ......
  </div>
</div>
// style.css
.HSV{
  display: flex;
}

.SV{
  width: 200px;
  margin-right: 10px;
}
// app.js
let SV = document.querySelector('.SV');
// 这里我们选择第二个矩形,这样就不会被另一个矩形给遮住点击事件
let SVRect = SV.querySelector('rect:last-child');
let SVSlide = SV.querySelector('.slide');
let SVFlag = false;

SVRect.addEventListener('mousedown', () => {
  SVFlag = true;
})
SVRect.addEventListener('mousemove', ev => {
  if(!SVFlag) return;

  // 一波换算得出滑块的比例然后乘以100就是对应的SV的值了
  Sval = ev.offsetX / SV.offsetWidth * 100;
  // 透明度因为方向的问题所以就反转一下
  Vval = (1 - ev.offsetY / SV.offsetHeight) * 100;

  SVSlide.style.left = ev.offsetX + 3 + 'px';
  SVSlide.style.top = ev.offsetY + 3 + 'px';

  setHSV();
})
SVRect.addEventListener('mouseup', () => {
  SVFlag = false;
})

let endColors = document.querySelectorAll('.endColor');

function setHSV(){
  // 这里算出对应的RGB值
  // 这个是最终结果的颜色
  let color = `
    rgb(${hsvtorgb(Hval, Sval, Vval).join(',')})
  `;
  // 这个是给SV设置的结束颜色
  let StopColor = `
    rgb(${hsvtorgb(Hval, 100, 100).join(',')})
  `;

  // 为在页面中的rect设置结束颜色
  [...endColors].map(el => el.setAttribute('stop-color', StopColor));

  colorTitle.innerHTML = color;
  colorShow.style.background = color;
}

Из приведенного выше кода я могу получить следующие эффекты:

На самом деле приведенный выше код не завершен, на изображении ниже видно, что он белый с обоих концов.

я долго искалsvgвопрос, почемуIconfontРезультаты разные...

Потом я обнаружил, что оригиналIconfontПридайте всему цветовому блоку сплошной фоновый цвет

Давайте добавим его, чтобы посмотреть на эффект.

// app.js
function setHSV(){
  // ...

  SV.style.background = StopColor;
  
  // ...
}

На этом основная функция палитры цветов выполнена.

закончился

Хотя есть еще две функции, но поскольку я не хочу писать слишком длинные статьи, давайте закончим здесь.

Хоть эта статья и подошла к концу, вы можете продолжить улучшать его функции, такие как:

  • Выполните функции двух других разделов: доска для хранения цветов, поле ввода.
  • Преобразование RGB в шестнадцатеричное
  • Напишите это как всплывающее окно
  • Компонентизируйте его с помощью Vue

Наконец, спасибо за чтение.