Цвет: RGB, HSB и прозрачность
В этом уроке наш цыплёнок CodeChick наконец перестанет быть серым: ты научишься смешивать цвет из красного, зелёного и синего, плавно перебирать оттенки через HSB и делать фигуры полупрозрачными.
Цвет в p5.js — это всего лишь набор чисел: говоришь библиотеке, сколько в краске красного, зелёного и синего, и она смешивает оттенок прямо на холсте.
Зачем тебе это нужно
До этого момента наш CodeChick жил в чёрно-белом мире. В прошлом уроке про первые формы ты собрал его из круга-тела, круга-головы и треугольника-клюва — но всё это было серым, как набросок карандашом. Согласись, настоящий цыплёнок так не выглядит. Он жёлтый и пушистый, с ярким оранжевым клювом, как будто его только что нарисовали неоновым маркером.
Цвет — это то, что превращает скучную геометрию в картинку, на которую хочется смотреть. Подумай про свои любимые игры или обложки треков в плеере: половина их вайба держится именно на цвете. Кислотный фиолетовый фон, мягкое свечение, полупрозрачные блики — всё это можно описать парой чисел и поставить в код.
К концу урока ты сможешь:
- покрасить любую фигуру в нужный цвет через модель RGB;
- плавно перебирать оттенки радуги через модель HSB (это пригодится для анимаций позже);
- делать фигуры полупрозрачными через канал alpha и накладывать их друг на друга, как стёкла светофильтров;
- и, конечно, покрасить нашего CodeChick: тело — в жёлтый, клюв — в оранжевый.
Вот к чему мы придём в самом конце — держи этот кадр в голове как цель:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(135, 206, 235); // нежно-голубое небо
noStroke();
fill(255, 221, 51); // жёлтое тело
ellipse(200, 230, 160, 160);
fill(255, 235, 120); // голова чуть светлее
ellipse(200, 140, 110, 110);
fill(255, 140, 0); // оранжевый клюв
triangle(200, 140, 250, 155, 200, 175);
fill(40); // чёрный глаз
ellipse(225, 130, 14, 14);
}Результат: на голубом фоне сидит жёлтый круглый цыплёнок с головой посветлее, ярко-оранжевым клювом-треугольником и маленьким чёрным глазом. Наконец-то он выглядит как живой CodeChick, а не как карандашный набросок. Дальше мы разберём каждое число в этом коде по косточкам.
Главная идея: цвет — это рецепт из трёх банок краски
Представь, что у тебя есть три банки светящейся краски: красная, зелёная и синяя. Ты смешиваешь их в разных пропорциях и получаешь любой цвет. Чем больше плеснёшь красной — тем краснее. Добавишь немного зелёной к красной — получится оранжевый. Нальёшь поровну всех трёх — выйдет белый.
Именно так и устроен экран твоего телефона: каждая точка-пиксель — это крошечная тройка красной, зелёной и синей лампочек. Меняя их яркость, экран рисует тебе и мемы, и игры, и этот текст. p5.js даёт тебе те же три банки в виде чисел.
RGB — модель цвета, в которой оттенок задаётся долями красного (Red), зелёного (Green) и синего (Blue).
В p5.js каждая «банка» — это число от 0 (краска не льётся совсем) до 255 (краска на максимум). Почему именно 255, а не 100? Это техническая традиция компьютеров: в один байт помещается ровно 256 разных значений, от 0 до 255. Можешь воспринимать это просто как «шкала яркости от нуля до 255».
Чтобы задать цвет фигуры, используют функцию fill() — она задаёт заливку, то есть цвет, которым закрашивается внутренняя площадь фигуры.
Заливка (fill) — цвет, которым закрашивается внутренняя площадь фигуры.
А контур фигуры — это обводка, за неё отвечает stroke().
Обводка (stroke) — цвет и линия контура фигуры или самой линии.
Как читать три числа в fill()
Когда ты пишешь fill(255, 221, 51), ты говоришь: «красной — почти на максимум, зелёной — много, синей — совсем чуть-чуть». Много красного и зелёного без синего как раз и дают жёлтый. Вот маленькая шпаргалка, которую полезно запомнить:
| Код | R | G | B | Что получится |
fill(255, 0, 0) | 255 | 0 | 0 | Чистый красный |
fill(0, 255, 0) | 0 | 255 | 0 | Ярко-зелёный |
fill(0, 0, 255) | 0 | 0 | 255 | Синий |
fill(255, 255, 0) | 255 | 255 | 0 | Жёлтый (красный + зелёный) |
fill(255, 140, 0) | 255 | 140 | 0 | Оранжевый (клюв!) |
fill(0, 0, 0) | 0 | 0 | 0 | Чёрный (краски нет) |
fill(255, 255, 255) | 255 | 255 | 255 | Белый (всё на максимум) |
Заметь забавную штуку: на экране «нет краски» (все нули) — это чёрный, а «вся краска» (все 255) — белый. Это противоположно тому, как смешиваются краски в красках на бумаге, где побольше краски — темнее. Дело в том, что экран сам светится, и мы смешиваем не пигменты, а свет. Чем больше света от всех трёх лампочек — тем ближе к белому.
Короткая запись: оттенки серого
Если дать fill() только одно число, p5.js поставит его сразу во все три банки. fill(0) — это то же самое, что fill(0, 0, 0), то есть чёрный. fill(128) — ровно посередине, серый. fill(255) — белый. Это удобный способ быстро задать любой оттенок серого, не повторяя число трижды. Помнишь чёрный глаз цыплёнка из первого примера? Там стояло как раз fill(40) — почти чёрный.
Разбираем на примерах
Пример 1. Красим тело цыплёнка в жёлтый
Начнём с самого главного — сделаем CodeChick жёлтым. Разберём код построчно.
function setup() {
createCanvas(400, 400);
}
function draw() {
background(245); // светло-серый фон
noStroke(); // убираем контур у фигур
fill(255, 221, 51); // жёлтая краска: R=255, G=221, B=51
ellipse(200, 200, 160, 160); // круглое тело в центре
}Результат: на почти белом фоне в центре холста — большой ровный жёлтый круг без контура. Это тело будущего цыплёнка.
Что здесь происходит, по шагам:
createCanvas(400, 400)создаёт квадратный холст 400 на 400 пикселей — наш лист скетчбука.background(245)заливает фон светло-серым (одно число — значит оттенок серого).noStroke()говорит: рисуй фигуры без контура. Без этой строки у круга была бы тонкая чёрная обводка по умолчанию.fill(255, 221, 51)— выбираем жёлтую краску. Эта строчка действует на всё, что нарисуем после неё.ellipse(200, 200, 160, 160)рисует эллипс с центром в точке (200, 200) шириной и высотой по 160 — получается круг.
Важнейший момент про порядок: fill() работает как кисть, которую ты обмакнул в банку. Пока не обмакнёшь в другую банку, все фигуры красятся текущим цветом. Поэтому цвет всегда ставят перед фигурой, которую хотят им покрасить.
Пример 2. Добавляем оранжевый клюв
Тело есть — добавим голову и оранжевый клюв. Тут важно показать, как сменить краску между фигурами.
function draw() {
background(245);
noStroke();
fill(255, 221, 51); // жёлтый — для тела и головы
ellipse(200, 230, 160, 160); // тело
ellipse(200, 140, 110, 110); // голова
fill(255, 140, 0); // меняем кисть на оранжевую
triangle(200, 140, 250, 150, 200, 170); // клюв
}Результат: на сером фоне жёлтый цыплёнок из двух кругов (тело и голова сверху), а сбоку от головы торчит маленький оранжевый треугольник-клюв.
Главная мысль примера: одну краску можно использовать для нескольких фигур подряд. Мы поставили жёлтый один раз и нарисовали и тело, и голову. А потом сменили кисть на оранжевый — и всё, что идёт дальше, красится оранжевым. Если бы ты поставил fill(255, 140, 0) в самом начале, оранжевыми вышли бы и тело, и голова. Попробуй мысленно переставить строки и представь результат — это лучший способ прочувствовать, как работает порядок.
Поэкспериментируй: поменяй fill(255, 140, 0) на fill(255, 80, 0) — клюв станет более красно-морковным. А fill(255, 180, 40) сделает его медово-золотистым. Меняй среднее число (зелёный канал) и смотри, как оранжевый перетекает от красного к жёлтому.
Пример 3. HSB — радуга в одно число
Допустим, ты хочешь сделать цыплёнка-радугу или плавно перекрасить фон через все цвета спектра. В RGB это мучение: чтобы пройти красный → оранжевый → жёлтый → зелёный → голубой, придётся одновременно крутить три числа в разные стороны. Неудобно. Для таких задач есть вторая модель цвета — HSB.
HSB — модель цвета через тон (Hue), насыщенность (Saturation) и яркость (Brightness); удобна для плавного перебора оттенков.
Представь круглую палитру художника — цветовое колесо. Hue (тон) — это угол на этом колесе: крути его, и цвет едет по радуге. Saturation (насыщенность) — насколько цвет сочный: 0 — это серый, 100 — кричаще-яркий. Brightness (яркость) — насколько он светлый: 0 — чёрный, 100 — во всю мощь.
Чтобы переключить p5.js в режим HSB, в начале вызывают colorMode(HSB). Удобно сразу задать диапазоны: тон по кругу 0–360 градусов, а насыщенность и яркость — 0–100, как проценты.
function setup() {
createCanvas(400, 200);
colorMode(HSB, 360, 100, 100); // тон 0-360, насыщенность и яркость 0-100
noStroke();
}
function draw() {
background(0, 0, 100); // белый фон (яркость 100, насыщенности нет)
// рисуем 12 кружков-перьев, каждое со своим тоном
for (let i = 0; i < 12; i++) {
let tone = i * 30; // 0, 30, 60 ... 330 градусов
fill(tone, 90, 90); // сочный и яркий
ellipse(30 + i * 30, 100, 26, 26);
}
}Результат: на белом фоне выстроились в ряд 12 кружков — настоящая радуга: от красного слева через оранжевый, жёлтый, зелёный, голубой, синий к фиолетовому справа. Каждый следующий кружок — это тон, сдвинутый на 30 градусов по цветовому колесу.
Видишь, в чём магия? Чтобы пройти всю радугу, мы крутим одно число — tone. Насыщенность и яркость держим постоянными. В RGB такое нарисовать было бы куда муторнее. Запомни правило: RGB удобен, когда ты знаешь конкретный цвет; HSB — когда хочешь плавно перебирать оттенки. В уроках про анимацию мы будем медленно увеличивать tone от кадра к кадру и получим переливающийся фон — но это позже.
Пример 4. Прозрачность — стёкла светофильтров
Последний кирпичик — прозрачность. Представь цветные стёкла или плёнки-светофильтры: накладываешь жёлтое стекло на синее — и сквозь них просвечивает зеленоватый цвет. В p5.js за это отвечает четвёртый параметр цвета — alpha.
Прозрачность (alpha) — четвёртый параметр цвета, задающий, насколько фигура просвечивает то, что под ней.
Вернёмся в режим RGB. Теперь у fill() может быть четыре числа: fill(R, G, B, alpha). Alpha тоже идёт от 0 до 255, где 0 — фигура полностью прозрачная (невидимая), а 255 — полностью непрозрачная (как обычно). Значение посередине, например 100, делает фигуру похожей на цветное стекло.
function setup() {
createCanvas(400, 300);
noStroke();
}
function draw() {
background(255); // белый фон
fill(255, 0, 0, 120); // красный, полупрозрачный
ellipse(160, 150, 180, 180);
fill(0, 0, 255, 120); // синий, полупрозрачный
ellipse(240, 150, 180, 180);
}Результат: два больших круга — красный слева и синий справа — частично накладываются друг на друга. В зоне пересечения сквозь оба стекла просвечивает фиолетовый цвет, как будто два светофильтра наложили один на другой. Будь alpha равной 255, верхний круг просто перекрыл бы нижний без всякого смешивания.
Где это пригодится нашему CodeChick? Например, можно нарисовать у него мягкие розовые щёчки полупрозрачным кругом поверх жёлтой головы — и щёки не закрасят голову наглухо, а лишь подрумянят её. А ещё прозрачный alpha — секрет красивых «хвостов» за движущимися объектами в анимации, но об этом тоже в следующих модулях.
Частые ошибки и подводные камни
На цвете новички спотыкаются предсказуемо. Вот пять граблей — обходи их.
1. fill() стоит после фигуры
Самая частая ошибка. Ты пишешь сначала ellipse(...), а fill() ставишь строкой ниже — и удивляешься, почему круг не пожелтел. Запомни: краску берут до того, как рисуют. Цвет действует только на фигуры, которые идут после него в коде.
2. Числа больше 255 или меньше 0
В RGB каждый канал живёт в диапазоне 0–255. Если написать fill(300, 0, 0), p5.js не сломается, но и ярче «максимально красного» не станет — лишнее просто обрежется до 255. А отрицательные числа превратятся в 0. Так что не жди, что fill(500, 0, 0) будет «суперкрасным», это всё тот же fill(255, 0, 0).
3. Забыл colorMode и удивляешься, почему HSB врёт
Если ты не вызвал colorMode(HSB, ...), то p5.js по умолчанию читает три числа как RGB. Тогда fill(60, 90, 90) ты задумывал как яркий жёлтый по тону, а получишь тускло-серо-зелёный, потому что библиотека приняла это за R=60, G=90, B=90. Правило: хочешь HSB — переключи режим в setup() заранее.
4. Перепутал заливку и обводку
Иногда хочешь покрасить площадь фигуры, а меняешь цвет контура — или наоборот. fill() — это про внутреннюю заливку, stroke() — про линию контура. Если контур тебе вообще не нужен, вызови noStroke(); если не нужна заливка (только контур) — noFill().
5. Ждёшь, что alpha сработает на одиночной фигуре
Прозрачность видна только тогда, когда под полупрозрачной фигурой что-то есть — фон или другая фигура. Если ты поставишь полупрозрачный круг на пустоту того же цвета, разницы не заметишь. Alpha проявляет себя на наложении: круг на круге, фигура на цветном фоне.
Мини-практика: раскрась своего CodeChick
Теперь твоя очередь. Возьми код финального цыплёнка из начала урока и доведи его до собственного стиля. Сделай по шагам:
- Смени небо. Поменяй
background(135, 206, 235)на закатное небо. Подсказка: для тёплого заката добавь побольше красного и поменьше синего, напримерbackground(255, 150, 100). - Подбери свой жёлтый. Поиграй с
fill(255, 221, 51): сделай цыплёнка более лимонным (подними зелёный) или более золотым (опусти зелёный, добавь немного красноты в клюв). - Добавь щёчки. После головы нарисуй два маленьких полупрозрачных розовых круга:
fill(255, 150, 150, 100)и дваellipse(...)по бокам клюва. Благодаря alpha они лягут румянцем, а не пятном. - Сделай радужный вариант. Отдельным скетчем переключись в
colorMode(HSB, 360, 100, 100)и покрась тело цыплёнка случайным тоном — поставь, например,fill(200, 80, 95)и посмотри, в какой цвет он оденется. Меняй первое число и лови момент, когда он станет мятным, потом сиреневым.
Цель — почувствовать руками, как числа превращаются в настроение картинки. Не бойся ставить «неправильные» значения: в худшем случае цыплёнок выйдет кислотным, и это нормально для экспериментов.
Итоги
Соберём всё в одну картину:
- RGB — цвет как смесь трёх банок краски: красной, зелёной и синей, каждая от 0 до 255.
fill(255, 221, 51)— жёлтый,fill(255, 140, 0)— оранжевый клюв. - Одно число в
fill()— это оттенок серого:fill(0)чёрный,fill(255)белый. - HSB — цвет через тон, насыщенность и яркость; крутишь один тон (Hue) — и едешь по всей радуге. Включается через
colorMode(HSB, ...). - alpha — четвёртое число цвета, прозрачность от 0 до 255; полупрозрачные фигуры накладываются, как цветные стёкла.
fill()красит заливку,stroke()— контур; цвет всегда ставят до фигуры.- Главные грабли:
fill()после фигуры, забытыйcolorMode, путаница заливки и обводки.
Наш CodeChick больше не серый набросок — он жёлтый, с оранжевым клювом и собственным небом за спиной. В следующем уроке этого модуля мы займёмся обводкой и стилем линий поплотнее, а затем научим цыплёнка двигаться: добавим draw()-анимацию, и те самые цвета и прозрачность, что ты освоил сегодня, оживут в движении.