Позвольте мне найти идею
Хотя у нас есть готовые элементы управления 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, потому что я скопировал этот код у кого-то другого, поэтому выложу его отдельно.
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
Наконец, спасибо за чтение.