Заливка, обводка, толщина линий

Цвет внутри фигуры, цвет её контура и толщина этого контура — три ручки, которыми ты раскрашиваешь любой скетч в p5.js.

Заливка (fill) — это цвет, которым закрашивается внутренняя площадь фигуры, а обводка (stroke) — цвет и линия её контура. Толщину этого контура задаёт strokeWeight().

В прошлом уроке про RGB, HSB и прозрачность ты научился собирать любой оттенок из чисел. Теперь разберёмся, куда этот цвет попадает: внутрь фигуры или на её край. Это и есть разница между заливкой и обводкой — две разные ручки, которые легко перепутать, пока не пощупаешь руками.

Зачем это вообще нужно

Представь, что ты рисуешь стикер для чата: жёлтый кружок-цыплёнок с чёткой тёмной обводкой, как у наклеек в мессенджерах. Без обводки он сольётся со светлым фоном и будет выглядеть как размытое пятно. А с толстым аккуратным контуром он сразу читается даже в крошечном размере превью. Вот эта «жирная линия по краю» и делает картинку похожей на настоящий стикер, а не на случайную кляксу.

Или другой пример: ты делаешь иконку в стиле плоского дизайна — как кнопки в приложениях. Там часто заливки нет вообще, а есть только тонкий контур. Чтобы так нарисовать, нужно уметь выключать заливку и оставлять одну обводку. И наоборот: иногда контур только мешает, и его убирают, оставляя чистый цветной силуэт.

К концу урока ты сможешь нарисовать вот такого цыплёнка: жёлтое тело с мягкой оранжевой обводкой, отдельно — версию-контур без заливки (как «раскраска») и версию без обводки (как плоский стикер). Три разных образа из одних и тех же кругов — меняются только три ручки стиля.

Звучит как мелочь, но именно от этих трёх ручек зависит «характер» картинки. Толстая чёрная обводка — это мультяшный, комиксный стиль, как в стикерпаках и эмодзи. Тонкая обводка или её отсутствие — спокойный, «взрослый» плоский дизайн, как иконки в твоём телефоне. Контур без заливки — это уже скетч, набросок карандашом. Один и тот же круг превращается то в наклейку, то в иконку, то в раскраску — и всё это ты сейчас научишься переключать буквально парой строк.

Три ручки стиля: заливка, обводка, толщина

Думай про p5.js как про набор фломастеров и заливочный баллончик. Когда ты собираешься нарисовать фигуру, ты сначала выбираешь:

  • Каким цветом закрасить внутри — это fill() (заливка).
  • Каким цветом обвести по краю — это stroke() (обводка).
  • Насколько жирной взять линию края — это strokeWeight() (толщина обводки в пикселях).

Важнейшая мысль, которую стоит запомнить с самого начала: эти функции работают как режим, а не как разовая команда. Ты сказал «теперь рисуем жёлтым» — и все фигуры после этого будут жёлтыми, пока ты не скажешь другое. Это как взять в руку жёлтый фломастер: он будет жёлтым, пока ты не сменишь его на синий. p5.js запоминает текущий цвет заливки и обводки и применяет их к каждой следующей фигуре.

Поэтому порядок строк имеет значение: сначала задаём стиль, потом рисуем фигуру. Если поменять местами — фигура нарисуется старым стилем, а новый применится только к следующей.

Какими числами задавать цвет

И fill(), и stroke() принимают цвет в тех же форматах, что ты разбирал в уроке про RGB, HSB и прозрачность. Освежим, чтобы дальше не спотыкаться:

  • fill(255, 220, 60) — три числа: красный, зелёный, синий (RGB). Это жёлтый.
  • fill(120) — одно число p5.js понимает как оттенок серого: 0 чёрный, 255 белый, всё между ними — серое.
  • fill(255, 220, 60, 100) — четвёртое число это прозрачность (alpha): чем оно меньше, тем сильнее фигура просвечивает то, что под ней.

Те же правила работают и для stroke() — ведь это просто цвет, только для контура. А вот strokeWeight() принимает одно число — толщину линии в пикселях. strokeWeight(1) — тонкий волосок, strokeWeight(20) — жирная полоса в палец шириной.

Пример 1. Тело цыплёнка с обводкой

Начнём с простого: жёлтый круг-туловище с оранжевой обводкой. Это и есть базовый CodeChick — тот самый герой, который растёт вместе с тобой через весь курс.

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(230, 245, 255); // светло-голубое небо

  strokeWeight(6);        // толщина контура — 6 пикселей
  stroke(230, 140, 30);   // обводка оранжевая
  fill(255, 220, 60);     // заливка жёлтая
  circle(200, 200, 160);  // тело цыплёнка по центру
}

Результат: на светло-голубом фоне в центре холста — крупный жёлтый круг диаметром 160 пикселей, обведённый по краю заметной оранжевой линией толщиной 6 пикселей. Похоже на пухлое тело цыплёнка-стикера.

Разберём построчно, что здесь происходит:

  1. strokeWeight(6) — задаём, что контур будет толщиной 6 пикселей. Без этой строки p5.js взял бы линию толщиной 1 пиксель — почти незаметную.
  2. stroke(230, 140, 30) — выбираем оранжевый цвет обводки (числа в формате RGB из прошлого урока).
  3. fill(255, 220, 60) — выбираем жёлтую заливку для внутренней площади.
  4. circle(200, 200, 160) — и только теперь рисуем круг. Он сразу получает оба заданных стиля: жёлтую серединку и оранжевый край.

Обрати внимание: три строки настройки стоят до строки с фигурой. Попробуй мысленно (или в редакторе) переставить circle(...) на самый верх — круг нарисуется чёрным с тонкой обводкой, потому что в момент отрисовки p5.js ещё не знал про твои цвета.

Пример 2. Глаз и клюв — два разных стиля в одном кадре

Теперь добавим цыплёнку глаз и клюв. Здесь важно увидеть, как стиль переключается между фигурами: каждая новая пара fill()/stroke() перекрывает предыдущую.

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(230, 245, 255);

  // тело
  strokeWeight(6);
  stroke(230, 140, 30);
  fill(255, 220, 60);
  circle(200, 200, 160);

  // глаз — чёрный, тонкая обводка
  strokeWeight(1);
  stroke(0);
  fill(30);
  circle(170, 170, 26);

  // клюв — оранжевый треугольник без обводки
  noStroke();
  fill(245, 130, 20);
  triangle(225, 175, 270, 190, 225, 205);
}

Результат: тот же жёлтый цыплёнок, но теперь у него есть тёмный глаз слева вверху (маленький круг с тонким контуром) и оранжевый клюв-треугольник справа от центра, у которого совсем нет обводки — только чистая заливка.

Что здесь стоит заметить:

  • Перед глазом мы заново задали strokeWeight(1) и stroke(0). Если бы не задали — глаз унаследовал бы толстую оранжевую обводку от тела, и это выглядело бы странно.
  • stroke(0) и fill(30) — одно число в скобках p5.js понимает как оттенок серого: 0 — чёрный, 255 — белый. Это короткая запись, ты уже видел её для оттенков серого.
  • Перед клювом мы вызвали noStroke() — выключили обводку совсем. Поэтому треугольник получился без контура, гладким оранжевым пятном.

Ключевая идея: p5.js не «забывает» стиль сам по себе. Глаз и клюв нарисовались по-разному только потому, что мы явно сменили настройки перед каждым из них.

Пример 3. noFill() и noStroke() — режим «раскраска» и режим «стикер»

Иногда нужна фигура без серединки — один контур, как в раскраске или в чертеже. За это отвечает noFill(): он говорит «закрашивать внутри не надо». А noStroke() — наоборот, убирает контур, оставляя сплошной цвет.

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(230, 245, 255);

  // слева — цыплёнок-контур (как раскраска)
  noFill();              // внутри пусто
  stroke(230, 140, 30);  // только оранжевый край
  strokeWeight(5);
  circle(120, 200, 130);

  // справа — цыплёнок-стикер (плоский, без контура)
  noStroke();            // края нет
  fill(255, 220, 60);    // сплошная жёлтая заливка
  circle(280, 200, 130);
}

Результат: на голубом фоне два круга одинакового размера. Левый — прозрачный внутри, виден только оранжевый контур толщиной 5 пикселей (сквозь него просвечивает фон). Правый — сплошной жёлтый круг вообще без контура, как наклейка.

Эти две функции — переключатели. Стоит понять, что они выключают режим до тех пор, пока ты снова не позовёшь fill(...) или stroke(...):

  • noFill() выключает заливку. Чтобы вернуть её обратно, достаточно снова вызвать fill(какой-нибудь цвет).
  • noStroke() выключает обводку. Вернуть — через stroke(...).

Заметь: в правом круге мы не вызывали fill() заново после noStroke() — заливка осталась жёлтой ещё с... стоп, нет. Здесь мы её задали явно строкой fill(255, 220, 60). И это хорошая привычка: не полагайся на то, что осталось «от прошлой фигуры», задавай стиль явно — так код понятнее, и ошибок меньше.

Пример 4. Цыплёнок в своём мире: толщина решает всё

Соберём маленькую сцену и поиграем именно с толщиной обводки. Цыплёнок стоит на травке, рядом — зёрнышко. Разная strokeWeight у разных деталей задаёт им разный «вес» в кадре.

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(230, 245, 255); // небо

  // травка — толстая зелёная линия-полоса внизу
  stroke(90, 180, 70);
  strokeWeight(40);
  line(0, 360, 400, 360);

  // тело цыплёнка — заметная обводка
  strokeWeight(6);
  stroke(230, 140, 30);
  fill(255, 220, 60);
  circle(200, 250, 150);

  // зёрнышко — тонкий аккуратный контур
  strokeWeight(2);
  stroke(120, 80, 40);
  fill(210, 170, 90);
  ellipse(300, 330, 22, 14);
}

Результат: внизу холста — толстая зелёная полоса травы (на самом деле это просто очень жирная линия толщиной 40 пикселей). Над ней по центру стоит жёлтый цыплёнок с оранжевой обводкой 6 пикселей, а справа от него лежит маленькое песочно-бежевое зёрнышко-овал с тоненьким коричневым контуром в 2 пикселя.

Главный фокус примера: strokeWeight мы меняем три раза — 40 для травы, 6 для тела, 2 для зёрнышка. Каждое новое значение перекрывает предыдущее и держится до следующей смены. Если убрать строку strokeWeight(2) перед зёрнышком, оно унаследует толщину 6 от тела цыплёнка и будет выглядеть неожиданно жирным для такой мелкой детали. Попробуй убрать её мысленно — и сразу почувствуешь, зачем мы задаём стиль явно перед каждой фигурой.

Ещё заметь хитрость: траву мы нарисовали обычной линией, просто очень толстой. strokeWeight управляет не только контуром фигур, но и толщиной самих линий line(...). Так одной ручкой можно рисовать и тонкие усики, и широкие полосы.

Шпаргалка: какая ручка что делает

Чтобы всё уложилось в голове, держи короткую таблицу-памятку:

ФункцияЧто делаетПример
fill(r, g, b)Цвет внутри фигурыfill(255, 220, 60)
stroke(r, g, b)Цвет контура / линииstroke(230, 140, 30)
strokeWeight(n)Толщина контура в пикселяхstrokeWeight(6)
noFill()Убрать заливку (внутри прозрачно)noFill()
noStroke()Убрать контур (чистый силуэт)noStroke()

Запомни таблицу не как список для зубрёжки, а как пять переключателей на пульте: два задают цвет (внутри и снаружи), один — толщину, и два выключают то, что не нужно. Любую картинку курса ты соберёшь именно этими пятью.

Частые ошибки и подводные камни

Эти грабли наступают почти всем новичкам. Узнаешь их заранее — сэкономишь себе час недоумения «почему фигура не того цвета».

1. Задал стиль ПОСЛЕ фигуры

Самая частая ошибка. p5.js применяет текущий стиль в момент отрисовки фигуры. Если написать так:

circle(200, 200, 160);  // рисуем СНАЧАЛА
fill(255, 220, 60);     // цвет задаём ПОТОМ — поздно!

Результат: круг останется чёрным (цвет по умолчанию), потому что в момент circle(...) заливка ещё не была жёлтой. Запомни правило: сначала стиль, потом фигура.

2. Перепутал fill и stroke

Легко перепутать, какая ручка за что отвечает. Если хочешь жёлтую серединку, а написал stroke(255, 220, 60) — жёлтым станет тоненький контур, а внутри будет чёрная заливка по умолчанию. Кажется, что «цвет не применился», хотя на самом деле он применился не туда. Проверь: fill — внутри, stroke — край.

3. Забыл, что стиль «прилипает» к следующим фигурам

Поставил толстую оранжевую обводку для тела цыплёнка, нарисовал ниже зёрнышко — а у зёрнышка вдруг тоже жирный оранжевый край. Это не баг: p5.js хранит последний заданный стиль и применяет его дальше, пока ты не сменишь. Решение — задавать стиль явно перед каждой группой фигур (или использовать push()/pop(), но про них будет отдельный разговор).

4. strokeWeight стоит, а обводки не видно

Ты задал strokeWeight(10), но контур не появился. Скорее всего, выше по коду стоит noStroke() — толщина-то есть, но рисовать контур запрещено. strokeWeight() задаёт толщину, но не включает обводку сам по себе: нужен ещё активный stroke(...).

5. Ждёшь, что noFill сделает фигуру белой

noFill() не красит фигуру в белый — он делает её прозрачной внутри. Сквозь неё виден фон или то, что нарисовано раньше. Если тебе нужен именно белый цвет внутри — это fill(255), а не noFill(). Разница видна сразу, как только под фигурой окажется что-то цветное.

Мини-проект: три образа CodeChick

Теперь твоя очередь. Возьми пример 1 (жёлтое тело с оранжевой обводкой) за основу и собери на одном холсте три версии цыплёнка в ряд:

  1. Обычный — жёлтая заливка + оранжевая обводка толщиной 6 (как в примере 1).
  2. Раскраска — только контур: noFill() и оранжевая обводка потолще, например strokeWeight(8).
  3. Стикер — плоский, без контура: noStroke() и сплошная жёлтая заливка.

Подсказки, чтобы получилось:

  • Размести три тела по горизонтали, меняя только X: например, центры в 100, 200, 300 при холсте 400×400, диаметр кругов поменьше — около 90.
  • Перед каждым кругом явно задавай его стиль — не надейся, что он «остался» от соседа.
  • Когда заработает, поиграй с числами: сделай обводку толще (strokeWeight(12)), смени оранжевый на свой любимый оттенок, добавь каждому глаз. Поменяй число и посмотри, что будет — именно так и нащупывается интуиция.

Если все три цыплёнка получились разными, а ты при этом ни разу не менял саму фигуру circle(...) — поздравляю, ты понял главное: вид фигуры задают именно эти три ручки стиля, а не фигура сама по себе.

Итоги

Сегодня ты освоил три ручки, которыми управляешь видом любой фигуры в p5.js:

  • fill(цвет) — заливка, цвет внутри фигуры.
  • stroke(цвет) — обводка, цвет контура.
  • strokeWeight(пиксели) — толщина контура.
  • noFill() — убрать заливку (фигура становится прозрачной внутри).
  • noStroke() — убрать обводку (остаётся чистый силуэт).

И главное правило: стиль — это режим. Задаёшь его до фигуры, и он держится, пока ты не сменишь. Поэтому контур цыплёнка теперь у тебя под контролем: можно сделать его жирным и «стикерным» или тонким и аккуратным.

В следующем уроке мы разберём background() поглубже и научимся складывать фигуры слоями — рисовать одно поверх другого так, чтобы цыплёнок оказался в своём мире: на фоне неба, на травке, рядом с зёрнышком. Цвет и стиль у тебя уже есть — пора собирать из них сцену.

Проверьте себя
1. Какая функция задаёт цвет, которым закрашивается внутренняя площадь фигуры?
Astroke()
Bfill()
CstrokeWeight()
DnoFill()
2. Ты написал strokeWeight(8) и fill(255, 220, 60), а затем circle(...). Что увидишь?
AКруг без заливки, только толстый контур
BЖёлтый круг с контуром толщиной 8 пикселей
CНичего: strokeWeight нельзя ставить перед fill
DЖёлтый круг вообще без контура
3. Что делает noFill()?
AКрасит фигуру в белый цвет
BДелает фигуру прозрачной внутри — виден фон
CУбирает контур фигуры
DУдаляет фигуру с холста
4. Почему важно задавать fill() и stroke() ДО строки с фигурой, а не после?
AИначе программа выдаст ошибку
Bp5.js применяет текущий стиль в момент отрисовки фигуры
CПосле фигуры функции стиля не работают совсем
DЭто просто рекомендация, порядок ничего не меняет
5. Ты вызвал noStroke(), а потом strokeWeight(10) и нарисовал круг. Контура нет. Почему?
AstrokeWeight задаёт толщину, но noStroke запретил рисовать обводку
BstrokeWeight(10) — слишком большое число, p5.js его игнорирует
CНужно было вызвать strokeWeight ДО noStroke
DКруги вообще не поддерживают обводку
6. Ты задал толстую оранжевую обводку для тела цыплёнка, а у нарисованного следом зёрнышка тоже толстый оранжевый край, хотя ты этого не хотел. В чём дело?
AЭто баг p5.js
BСтиль «прилипает»: p5.js хранит последний заданный stroke и применяет дальше
CЗёрнышко всегда наследует цвет ближайшей фигуры
DНужно было нарисовать зёрнышко раньше тела