![image](https://habrastorage.org/webt/r4/y5/c3/r4y5c3ll3ab62bu_giksqihzjx4.jpeg)
Муаровый узор — это оптическая иллюзия, возникающая при наложении двух периодических сетчатых рисунков. Повторяющиеся элементы двух рисунков то накладываются друг на друга, то образуют промежутки.
В обычной жизни мы часто сталкиваемся с ним, например, когда смотрим на тюлевые занавески. Что неудивительно — само французское название Moire исходно обозначало похожий тип шелковой ткани.
![image](https://habrastorage.org/webt/yi/1q/9d/yi1q9drnqyien6jqpq4l-x-s5sq.jpeg)
Этот эффект можно часто наблюдать в самых разных сферах — от фотографии до радиологии и мореходства.
Чтобы добиться возникновения этого эффекта, а заодно попрактиковаться в 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 параметры создают форму круга, а не овала.
В итоге у вас получается что-то такое.
![image](https://habrastorage.org/webt/z1/3a/ga/z13agansua-rb64spcr1h-v2zdq.png)
Пока не впечатляет, да?
Теперь нам нужно сделать так, чтобы этих элипсов стало больше, каждый следующий чуть больше предыдущего. Для этого нам нужно создать цикл, убрать в него наш эллипс и сделать третий и четвертый параметры переменными.
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 мы подставляем в функцию рисования эллипса в качестве третьего и четвертого параметра, отвечающих за диаметр по ширине и высоте.
Теперь, когда мы запустим код, то получим следующее.
![image](https://habrastorage.org/webt/q_/um/3m/q_um3mbhly7bkqy0gexgd48ud48.png)
Это еще не муар, но уже похоже. Что же сделал код? Он просто последовательно рисовал 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 для второго круга. Поскольку она будет по чуть-чуть меняться каждый раз, наш круг будет двигаться вправо по горизонтали, пока его центр не достигнет края экрана.
![image](https://habrastorage.org/webt/3v/ww/so/3vwwsobznt-udcvzksly9kipe5s.png)
Не забудьте поменять первый параметр второго эллипса с 360 на переменную x.
Готово. В итоге вы получите повторяющийся беконечно муаровый эффект у себя на экране компьютера, который легко интегрировать в свои веб-проекты.
Ссылка на итоговый результат
- Идея проекта взята из книги Superfun P5.js Projects — Nazia Fakhruddin, честно купленной на Amazon.
- Часть материала взята из статьи того же автора на Medium medium.com/@naziafakhruddin/the-mysterious-moir%C3%A9-pattern-49d797897355