Книжное убежище

Прокомментировать Просмотры: 3

читалочка

Приветствую обитателей SE7ENа! С удовольствием читаю статьи на этой площадке, однако публикуюсь впервые. Настало время исправить это упущение и немного рассказать о себе. Если охарактеризовать меня в двух словах: отчасти программист, отчасти софтварный инженер. Короче говоря, человек с аналитическим складом ума и способностью быстро улавливать суть происходящего. Перейдем к делу, текста будет немало.

Хочу презентовать собственную веб-читалку, предназначенную для домашнего сервера. Она поддерживает трехмерную анимацию перелистывания страниц на чистом CSS, работает с файлами FB2, EPUB и TXT, а также синхронизирует закладки и текущую позицию чтения через сервер. Благодаря этому можно начать чтение на смартфоне и без проблем продолжить на персональном компьютере. Никаких сложных сборок, Node.js или npm — исключительно браузер и Python. Исходный код опубликован на GitHub под свободной лицензией.


Предпосылки создания

Виной всему закладки. Ну и еще эстетически приятная цветовая гамма интерфейса, но ключевую роль всё же сыграли именно закладки.

В моем распоряжении целый парк разнородной техники: устройства на Android, iPhone, ноутбук под управлением macOS и десктоп на Windows. На каждом аппарате установлена своя читалка: в свое время на андроиде я использовал замечательный CoolReader (он и послужил главным источником вдохновения), на маке — коммерческий BookReader, на айфоне — Eboox, а на Windows — десктопную версию CoolReader, которая, откровенно говоря, выглядит куда скромнее своего мобильного аналога.

Всё бы ничего, но каждая смена гаджета оборачивалась дискомфортом. Синхронизировать закладки между этими разрозненными приложениями невозможно в принципе, а удерживать в памяти номер главы или страницы мне не удается. Существовал и сторонний веб-сервис для чтения, которым я пользовался, но из-за проблем с хостингом он канул в Лету.

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

Техническое задание для себя любимого

Я редко пишу код «в стол», поэтому первым делом сформулировал четкие требования, чтобы двигаться по намеченному вектору и не распыляться на второстепенные фичи. Ключевые пункты:

  • функционирование на домашнем сервере, доступность с любого десктопного или мобильного устройства по локальной сети и использование браузерного кэша;

  • книжная база хранится в виде обычных файлов на диске, а не в реляционной базе данных;

  • текущая позиция и закладки сохраняются на сервере для автоматической синхронизации;

  • визуальный эффект перелистывания страниц, имитирующий бумажный оригинал;

  • поддержка форматов: FB2, EPUB, TXT;

  • минимальное количество зависимостей, отказ от тяжелых фронтенд-пайплайнов ради максимальной простоты развертывания.

В конечном счете все поставленные задачи были успешно реализованы, и результатом я вполне доволен. Возникают лишь небольшие нюансы с правами доступа при деплое на удаленные машины (сервер сохраняет файл state.json и метаданные непосредственно рядом с книгами, поэтому некорректные права на директории приводят к ошибкам). Впрочем, это легко исправляется парой команд chmod/chown после копирования файлов либо запуском с повышенными привилегиями.

О WebGL, шейдерах и нервных клетках, убитых на сетку

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

Однако на практике рендеринг текстового контента через шейдеры оказался сущим кошмаром. Текст в WebGL реализуется либо через атласы глифов, либо методом Signed Distance Fields (SDF), либо с помощью предрендеренных текстур, и всё это добро приходится пересчитывать при малейшем изменении шрифта или масштаба страницы. Попытка натянуть полученную текстуру на деформируемую сетку (mesh) страницы превратилась в отдельную проблему: то текст начинаетплывать, то рвутся края, то катастрофически проседает производительность на мобильных телефонах, игнорируя геометрию книжного корешка.

Спустя пару недель экспериментов было принято волевое решение: отказаться от WebGL в пользу CSS 3D transforms. И что вы думаете? Для имитации классического перелистывания возможностей CSS 3D оказалось более чем достаточно: свойства transform: rotateY(), perspective и transform-origin, привязанные к корешку, создают отличный эффект движения, пока браузер самостоятельно занимается оптимизированным рендерингом, сглаживанием и композитингом текста. Текст остается нативным DOM-элементом — его можно легко выделять мышкой, искать по нему информацию, и он выглядит кристально четким при любом значении DPI. Без ложки дёгтя, правда, не обошлось. Чтобы картинка выглядела реалистично, пришлось повозиться с освещением, тенями и градиентами. Кроме того, возникли трудности с анимацией в Safari: тени и сам текст изменялись, но само перелистывание страниц отсутствовало.

Полноценный WebGL-рендерер с физическим изгибом страниц пока отложен в долгий ящик — исключительно ради эстетики, а не практической необходимости.


Итоговый функционал

Что представляет собой готовая читалка:

  • Трехмерный книжный разворот с плавной анимацией перелистывания. Листать можно кликами по краям экрана, клавиатурными стрелками, пробелом, свайпами на смартфоне или просто зацепив угол страницы курсором мыши либо пальцем, перетаскивая ее точно так же, как бумажный лист.

  • Одностраничный режим для вертикально ориентированных экранов: мобильные устройства автоматически переключаются на отображение одиночной страницы вместо разворота.

  • Динамическая разбивка на страницы: текст форматируется прямо в окне браузера с учетом текущего разрешения дисплея, выбранного шрифта и отступов. При повороте планшета или телефона происходит мгновенный пересчет.

  • Надежная фиксация позиции. Каждый абзац получает уникальный стабильный якорь (data-block-id), поэтому прогресс привязывается именно к текстовому блоку, а не к абстрактному номеру страницы. Изменение размера шрифта не сбивает текущее местоположение.

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

  • Интерактивное оглавление для быстрого перемещения по главам.

  • Пять цветовых тем на выбор: Бумажная, Сепия, Ночная, Лесная и Небесная. Плюс гибкая кастомизация кегля, межстрочных интервалов и полей.

  • Менеджер библиотеки в виде сетки карточек с обложками и индикаторами прогресса, поддерживающий добавление через кнопку или Drag-and-Drop, а также удаление с дополнительным подтверждением.

анимация
анимация

Архитектурные решения: максимальная простота как конкурентное преимущество

Проект сознательно спроектирован без использования тяжелых фронтенд-фреймворков и систем сборки:

  • Фронтенд написан на чистом ES2022 JavaScript с задействованием пользовательских CSS-переменных (Custom Properties) для реализации тем и CSS 3D-трансформаций для анимации. Из внешних библиотек подключены только epub.js и JSZip, которые лежат скачанными локально в директории lib (если честно, я их даже особо не тестировал, поскольку предпочитаю формат FB2 с его нативной XML-разметкой).

  • Бэкенд представляет собой единственный файл server.py, построенный на базе стандартного модуля http.server без единой сторонней зависимости. Скрипт поднимает два потока: раздачу статического контента на порту 8080 и обработку API на порту 8001.

  • Хранилище данных организовано предельно просто: книги хранятся в исходном виде в папке books под оригинальными именами, рядом с ними располагаются файлы метаданных вида `<имя>.meta.json`, содержащие информацию о прогрессе и закладках, а глобальные параметры пишутся в state.json. Никаких СУБД. Создание бэкапа сводится к банальной команде cp -r books/.

Программный интерфейс (API) минималистичен: получение списка литературы, отдача обработанного текста (парсинг FB2 выполняется на лету средствами сервера), сохранение прочитанного прогресса, обновление метаинформации и удаление файлов. И на этом всё.


Данный проект создавался в строгом соответствии с личным техническим заданием под конкретные потребности, и я ежедневно использую его по назначению. Если у вас дома тоже пылится домашний сервер, имеется зоопарк разношерстных девайсов и регулярно болит голова из-за рассинхронизации закладок — возможно, это решение окажется полезным и для вас. Благодарю за уделенное время!

 

Источник

Поделиться:

Похожие статьи

Поиск по играм, новостям и статьям…

Введите не менее двух символов

Введите не менее двух символов