Как стать автором
Обновить

Реализуем визуальный эффект из фильма «Матрица»

Время на прочтение2 мин
Количество просмотров32K


Доброго времени суток, друзья!

На днях пересмотрел «Матрицу». Слушайте, до чего же классный фильм (это касается только первой части). В очередной раз обратил внимание на «падающие» строчки с иероглифами на ихних экранах (намеренно использовал слово «ихних» забавы ради). Задумался о том, как это можно реализовать… максимально простым способом (ибо лень). Вот что у меня получилось.

Welcome to the Matrix


Разметка выглядит так:
<body style="margin: 0; background: #000; overflow: hidden;">
    <canvas></canvas>
</body>

Инициализируем холст, контекст, ширину и высоту холста. Делаем последние равными ширине и высоте окна браузера:
const C = document.querySelector("canvas"),
  $ = C.getContext("2d"),
  W = C.width = innerWidth,
  H = C.height = innerHeight

Создаем строку с символами, которые будут использоваться для визуализации (не хочу иероглифы, хочу кириллицу!). Преобразуем данную строку в массив. Пробелы дают пустоты в колонках, с ними эффект интереснее:
const str = "А+Б0В-Г1Д=Е2Ё Ж3З И4Й К5Л М6Н О7П Р8С Т9У Ф!Х Ц?Ч Ш.ЩЪ,Ы Ь:ЭЮ;Я",
  matrix = str.split('')

Определяем размер шрифта, количество колонок и создаем пустой массив. Этот массив мы будем использовать для определения координаты y:
let font = 11,
  // количество колонок = ширина холста / размер шрифта
  col = W / font,
  arr = []

Заполняем пустой массив единицами по количеству колонок:
for(let i = 0; i < col; i++) arr[i] = 1

К рисованию все готово. Приступаем:
function draw() {
  // определяем цвет фона
  // такой цвет позволяет добиться эффекта постепенного затухания символов
  $.fillStyle = "rgba(0, 0, 0, .05)"

  // заливаем холст выбранный цветом
  $.fillRect(0, 0, W, H)

  // меняем цвет для шрифта
  $.fillStyle = "#0f0"

  // устанавливаем параметры шрифта
  $.font = font + "px system-ui"

  // рисуем символы
  for (let i = 0; i < arr.length; i++) {
    // выбираем случайный набор символов
    let txt = matrix[Math.floor(Math.random() * matrix.length)]

    // рисуем символы
    // двигаемся вправо и вниз
    // fillText(набор символов, координата x = значение i, умноженное на размер шрифта, координата y = значение arr, умноженное на размер шрифта)
    $.fillText(txt, i * font, arr[i] * font)
    
    // если "y" больше высоты холста или Math.random() выдает больше 0.975 (чем это значение меньше, тем больше будет пустот на экране), то поднимаемся наверх (обнуляем "y")
    // это позволяет обеспечить разницу отрисовки отдельных колонок
    if (arr[i] * font > H && Math.random() > 0.975) arr[i] = 0
    
    // увеличиваем значение y
    arr[i]++
    }
}

Запускаем функцию рисования через каждые 123 миллисекунды (число произвольное):
setInterval(draw, 123)

Наконец, при изменении размеров окна делаем перезагрузку страницы (ибо лень):
window.addEventListener('resize', () => location.reload())

Результат можно посмотреть здесь.

Существует небольшая проблемка: время от времени колонки слипаются, отрисовываются почти вровень по горизонтали. Это влияет на восприятие: глаз цепляется за упорядоченность. Ощущается недостаток хаоса, что ли. Достойного решения пока не найдено.

Благодарю за внимание.
Теги:
Хабы:
Всего голосов 27: ↑18 и ↓9+14
Комментарии40

Публикации

Истории

Работа

Ближайшие события

15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань