- PVSM.RU - https://www.pvsm.ru -

Убежище книги

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

читалочка

читалочка

Хочу поделиться веб‑читалкой для домашнего сервера: 3D‑перелистывание страниц на чистом CSS, книги в FB2/EPUB/TXT, закладки и позиция чтения синхронизируются через сервер, поэтому можно начать на телефоне, а продолжить на десктопе. Без сборки, без Node.js, без npm — только браузер и Python. Код на GitHub, лицензия свободная [1].


Зачем это вообще

Всё из‑за закладок. Ну и из‑за приятных тонов картинки, но в основном — из‑за закладок.

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

И всё бы ничего, но смена устройства каждый раз вызывала чувство дискомфорта. Синхронизировать закладки между этими программами невозможно в принципе, а запоминать, на какой главе остановился, у моего внимания не получается. Был ещё один веб‑сервис, которым я пользовался, но у него то ли закрылся хостинг [2], то ли ещё какие‑то проблемы, в общем, он исчез.

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

ТЗ самому себе

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

  • работает на домашнем сервере, доступ с любого устройства по сети, и кеш браузера.

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

  • позиция чтения и закладки — тоже на сервере, чтобы синхронизировались сами;

  • перелистывание страниц как у настоящей книги;

  • форматы: FB2, EPUB, TXT;

  • минимум зависимостей, никакого фронтенд‑конвейера, что бы не городить библиотеки, а развернуть можно было максимально просто.

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

Про WebGL, шейдеры и как меня чуть не свела с ума сетка

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

На практике оказалось, что рендерить текст шейдерами — это боль. Текст в WebGL — это либо атласы глифов, либо SDF, либо текстуры с предрендером, и всё это нужно пересчитывать при каждом изменении шрифта или размера страницы. А потом ещё эту текстуру надо натянуть на изгибающуюся сетку (mesh) страницы, и сетка эта непослушная, то текст плывёт, то края рвутся, то производительность на телефоне проседает, то под текстуры падает, корешка не слушается.

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

WebGL‑рендерер с изгибом страницы остался в планах — но уже как «когда‑нибудь потом, ради красоты», а не как необходимость.


Что получилось

Читалка

  • 3D‑разворот книги с анимацией перелистывания. Можно листать кликом по краям, стрелками, пробелом, свайпом на телефоне, а можно ухватить угол страницы мышью или пальцем и потянуть — как бумажную.

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

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

  • Позиция чтения не плывёт. Каждый абзац получает стабильный якорь (data‑block‑id), и позиция сохраняется по якорю, а не по номеру страницы. Меняешь шрифт — остаёшься на том же месте текста.

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

  • Оглавление с переходом по главам.

  • 5 тем: Бумага, Сепия, Ночной, Лес, Небо. Плюс настройка размера шрифта, интервала и отступов.

  • Библиотека: сетка карточек с обложками и прогрессом, добавление кнопкой или drag&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 парсится на лету на сервере), прочитать, обновить метаданные, удалить книгу. Всё.


Проект сделан по собственному ТЗ, под собственные нужды, и я им пользуюсь каждый день. Если у вас тоже дома есть сервер, зоопарк устройств и боль с закладками — возможно, вам это тоже пригодится, спасибо за внимание.

Автор: Hiddenath

Источник [3]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/diy/456460

Ссылки в тексте:

[1] Код на GitHub, лицензия свободная: https://github.com/Hiddenath/book_reader

[2] хостинг: https://www.reg.ru/?rlink=reflink-717

[3] Источник: https://habr.com/ru/articles/1069526/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1069526