Муаровый узор — это оптическая иллюзия, возникающая при наложении двух периодических сетчатых рисунков. Повторяющиеся элементы двух рисунков то накладываются друг на друга, то образуют промежутки.
В обычной жизни мы часто сталкиваемся с ним, например, когда смотрим на тюлевые занавески. Что неудивительно — само французское название Moire исходно обозначало похожий тип шелковой ткани.
Этот эффект можно часто наблюдать в самых разных сферах — от фотографии до радиологии и мореходства.
Чтобы добиться возникновения этого эффекта, а заодно попрактиковаться в p5.js, я решил написать простой код, который его воссоздает.
p5.js — это библиотека для Javascript, созданная в 2014 году. Ее основная цель — стать окном в мир программирования для дизайнеров, художников, учителей и прочих представителей творческих профессий. Он поддерживает и анимацию, и схемы, легко переводится в веб-формат.
Чтобы начать работу надо создать новый проект онлайн-редакторе. По умолчанию новый проект имеет следующий вид:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
}
function setup() — задает функцию, которая выполняется только раз
function draw() — повторяется в бесконечном цикле
Мы начинаем с настройки нашего “холста”. Для функции createCanvas() задаем параметры 720 и 500 (ширина и высота соответственно).
Чтобы на фоне у нас появился эллипс, внутрь функции draw() (которая, как мы помним, отвечает за повторение) вставляем следующие параметры:
{
noFill()
stroke ('purple')
strokeWeight(3)
ellipse(360,250,100,100) }
Что же здесь происходит?
noFill() — не дает заливать внутренность эллипса каким-либо цветом.
stroke ('purple') — создает линию с фиолетовым цветом.
strokeWeight(3) — задает толщину этой линии.
ellipse(360,250,100,100) — говорит, что линия должна закручиваться в эллипс с заданными параметрами (положение по X, положение по Y, диаметр по X, диаметр по Y). Первый и второй параметр равны половине параметров в функции createCanvas(400, 400) — чтобы быть ровно по центру. Одинаковые 3 и 4 параметры создают форму круга, а не овала.
В итоге у вас получается что-то такое.
Пока не впечатляет, да?
Теперь нам нужно сделать так, чтобы этих элипсов стало больше, каждый следующий чуть больше предыдущего. Для этого нам нужно создать цикл, убрать в него наш эллипс и сделать третий и четвертый параметры переменными.
background(220);
for(let i=0;i<1000; i+=10) {
noFill()
stroke ('purple')
strokeWeight(3)
ellipse(360,250,i,i)
Если вы хоть раз в своей жизни имели дело с циклами — вам будет понятно, что происходит. Мы задаем начальное значение i = 0, так что в начале мы рисуем эллипс в нулевым радиусом. Потом мы задаем лимит до какого значения i мы будем повторять цикл (до 1000), после чего определяем шаг изменения i+=10 — каждый раз к предыдущему результату i будет добавляться 10.
Параметр i мы подставляем в функцию рисования эллипса в качестве третьего и четвертого параметра, отвечающих за диаметр по ширине и высоте.
Теперь, когда мы запустим код, то получим следующее.
Это еще не муар, но уже похоже. Что же сделал код? Он просто последовательно рисовал 100 кругов (пока диаметр последнего не стал 1000), которые различаются между собой в диаметре на 10, каждый раз сохраняя результат.
Не забудьте вписать noFill() иначе у вас сохранится и отобразится только результат последней итерации.
Теперь, чтобы получить второй эллипс, впишем его в тот же цикл, но немного с другими параметрами:
function draw() {
background(220);
for(let i=0;i<1000; i+=10) {
noFill()
stroke ('purple')
strokeWeight(3)
ellipse(360,250,i,i)
stroke("red")
strokeWeight(3)
ellipse(360, 250,i-500,i-500)
}
В итоге вы получите последовательность кругов, самый большой из которых будет в диаметре равен 1000 минус 500. Высота нашего холста — как раз 500, так что внутренний перфекционист будет удовлетворен. Ну и он будет красного цвета.
Настало время для финального действия — заставить эти круги двигаться мимо друг друга.
Для этого ВНЕ цикла добавляем переменную x со значением 0 в самом начале всего кода и цикл if ПОСЛЕ функции draw()
let x = 0
function setup() {
createCanvas(720, 500);
}
function draw() {
background(220);
for(let i=0;i<1000; i+=10) {
noFill()
stroke ('purple')
strokeWeight(3)
ellipse(360,250,i,i)
stroke("red")
strokeWeight(3)
ellipse(x,250,i-500,i-500)
}
if (x>width) {
x= 0
} else {x= x+3}
}
Здесь есть условие. Если x меньше ширины холста, то мы сбрасываем x в дефолтное нулевое значение. Пока этого не произошло мы прибавляем по 3 к нашему значению x. Как может быть понятно, через X мы хотим задать координату по оси X для второго круга. Поскольку она будет по чуть-чуть меняться каждый раз, наш круг будет двигаться вправо по горизонтали, пока его центр не достигнет края экрана.
Не забудьте поменять первый параметр второго эллипса с 360 на переменную x.
Готово. В итоге вы получите повторяющийся беконечно муаровый эффект у себя на экране компьютера, который легко интегрировать в свои веб-проекты.
Ссылка на итоговый результат
- Идея проекта взята из книги Superfun P5.js Projects — Nazia Fakhruddin, честно купленной на Amazon.
- Часть материала взята из статьи того же автора на Medium medium.com/@naziafakhruddin/the-mysterious-moir%C3%A9-pattern-49d797897355