ZoomiJS

InstantCMS 2.X

Нужна ли адаптация библиотеки для InstantCms?

Не знаю что это такое
Всего 4 голоса
#1 15 марта 2026 в 16:09

Всем привет. Есть у меня такая библиотека — ZoomiJS (https://github.com/pechoradev/ZoomiJS)

Использую её во многих своих проектах. Возникла мысль адаптировать её для использования в InstantCms. 

Кратко, что умеет библиотека:

— Находит на странице изображение с заданным в настройках селектором и позволяет увеличивать его в модальном окне

— Умеет формировать галереи по селектору или контейнеру, внутри которых находятся изображения

— Умеет обрабатывать исключения (Например открывать изображения в теле новости, но не открывать обложку новости)

Демо

Когда-то давно писал её для своих целей, но решил, что нужно пускать в свет. 

Касательно этого вопрос — нужно ли сделать адаптацию данной библиотеки для InstantCms (через компонент или виджет)

#2 15 марта 2026 в 16:42

А чем это отличается допустим от fancybox?

#3 15 марта 2026 в 16:49

Проголосовал нет и могу сказать почему на текущий момент открытия фото в модалке идет по ссылке которая прописана в ссылке например но там картинка не будет 3000х3000 а будет 150х90 чтобы вес страницы был меньше если в шаблоне выводить еще дата атрибут на полную то чем ваша библиотека лучше того же fancybox или другого lightbox. Прошу не агрится, я к тому что уважаю вас как разработчика много интересных разработок у Вас но это немного не то просто красивое модальное окно и все.

Добавлено спустя 4 минуты

И опять же не к тому чтобы придраться на гитхабе написано весит min версия 11кБ по факту 22кБ

#4 15 марта 2026 в 17:41

 pupsikmaxisoft, у инструментов разные ниши:

Fancybox: документация на английском, лицензия платная для коммерции (бесплатно только для личных проектов с указанием автора). Fancybox — это комбайн: картинки, видео, фреймы, формы, слайдеры и тд.

ZoomiJS: документация на русском, лицензия MIT (делай что хочешь, даже в коммерции), автор на связи в РФ. Zoomi  делает одну вещь: открывает <img> в модалке с зумом и навигацией

 maxisoft,  Спасибо за честный и развернутый ответ! 🙏 Абсолютно не агрюсь — наоборот, такие комментарии самые ценные, потому что помогают увидеть слабые места =)

Вы абсолютно правы: в реальных проектах мы почти всегда выводим в верстке превью (150×90, 300×200), а в модалке хотим показать полное изображение (3000×3000). И да, для этого нужен data-full или href на оригинал.

Внутри open() есть проверка: img.dataset.full || img.currentSrc || img.src. То есть библиотека уже поддерживает сценарий с превью, но, признаю, это неочевидно из документации — спасибо, что подсветили!

«Чем лучше Fancybox, если всё равно нужны data-атрибуты?» Справедливый вопрос. Честный ответ: если вам нужен только этот сценарий — возможно, ничем. 😊

Про размер файла: 11 КБ vs 22 КБ Тут вы поймали меня на неточности — спасибо! 11 КБ — это размер после gzip-сжатия (так показывают многие онлайн-анализаторы и GitHub)

Это моя ошибка в подаче: нужно указывать оба значения, чтобы не вводить в заблуждение. Исправлю в README и на странице демо.

#5 15 марта 2026 в 18:41

ZoomiJS: документация на русском, лицензия MIT (делай что хочешь, даже в коммерции), автор на связи в РФ. Zoomi  делает одну вещь: открывает <img> в модалке с зумом и навигацией

Pechora.Dev 🐻

Довольно спорный момент так как например код js нет комментариев, и получается что нужно догадаться что за функционал тут и для чего нужно. Опять это не критика и не хейт, просто сама библиотека неплохая если воспримете меня правильно вот некоторые моменты. 

🔴 Критические / баги

1. _unbindEvents вызывается после destroy — self.modal уже null 

  1. // destroy():
  2. self.modal = null;
  3. // ...
  4. self._unbindEvents(); // <-- здесь self.modal уже null!
  5.  
  6. // В _unbindEvents:
  7. if (self._handlers.keydown) self.modal.removeEventListener(...) // TypeError

_unbindEvents() нужно вызывать до обнуления ссылок.

2. navigate() — анимация через translateX = 100 работает некорректно

  1. self.translateX = direction * 100; // пиксели? проценты?
  2. self._updateImageTransform(); // translate(100px, 0px) scale(1)


Это сдвинет изображение на 100 пикселей, а не «за экран». Анимация перехода будет почти незаметна. Нужно либо 100vw, либо анимация через CSS-классы.
 

3. open() — self.modalImg.src устанавливается внутри onLoad нового Image(), но onLoad вызывается сразу при .complete, игнорируя реальную проверку

  1. if (self._preloadImages[src] && self._preloadImages[src].complete) {
  2. onLoad(); // вызов без установки modalImg.src заранее
  3. } else {
  4. var tempImg = new Image();
  5. tempImg.onload = onLoad;
  6. tempImg.src = src; // src задаётся ПОСЛЕ привязки onload &mdash; ок
  7. }


Внутри onLoad есть self.modalImg.src = src — это нормально. Но при .complete нет проверки naturalWidth > 0 (изображение могло загрузиться с ошибкой и тоже .complete === true).

🟡 Средние проблемы

4. Утечка памяти в _preloadImages

Кеш предзагруженных изображений никогда не очищается — ни при navigate, ни при close, ни при смене галереи. При большом количестве изображений это накапливается.

5. _transformRAF не отменяется при destroy

  1. // В destroy() нет:
  2. if (self._transformRAF) cancelAnimationFrame(self._transformRAF);

RAF-колбэк выполнится после уничтожения объекта и попытается обратиться к self.modalImg — null.

6. updateOptions с options.selector содержит баг

  1. if (options.selector && options.selector !== self.options.selector) self._parseSelectors();

 
 К моменту проверки self.options уже обновлён через extend, поэтому options.selector !== self.options.selector всегда false. Нужно сохранять старый селектор до extend.
 

7. _bindMouseEvents — swipe через мышь имеет конфликт с drag

  1. self._handlers.mouseDown = function(e) {
  2. if (self.scale > 1) {
  3. self._startDrag(...);
  4. } else if (self.galleryImages.length > 1) {
  5. self._startSwipe(...);
  6. }
  7. };

 Если scale > 1 — swipe недоступен. Но пользователь может захотеть листать галерею при зуме, свайпнув достаточно далеко. Логика взаимоисключающая без явной причины.

🟢 Мелкие / стиль
 

8. _updateNavButtons — кнопки всегда disabled = false при length > 1 

  1. if (self._prevBtn) self._prevBtn.disabled = self.galleryImages.length <= 1;


 При length > 1 кнопки будут disabled = false — это правильно, но выглядит как неинтуитивная логика. Лучше явно: self._prevBtn.disabled = false.

9. Строки интерфейса захардкожены на русском

  1. self.modal.setAttribute('aria-label', 'Просмотр изображения');
  2. self._closeBtn.setAttribute('aria-label', 'Закрыть модальное окно');
  3. // ...
  4. self.modalCaption.textContent = 'Ошибка загрузки изображения';

 
 Это должно быть в DEFAULTS для поддержки i18n.
 

10. debounce — нет немедленного вызова (leading edge)

Для resize задержка 150ms — нормально. Но функция не экспортируется и не переиспользуется. Можно оставить, просто пометить как утилиту.

11. Отсутствует passive: true на touchstart/touchmove на document

На самом modalImg стоит { passive: false } — ок, нужен preventDefault. Но на document для mousemove/mouseup passive не указан, хотя там preventDefault не вызывается.

 Самое важное к исправлению: порядок вызовов в destroy(), анимация в navigate(), баг в updateOptions, и очистка _preloadImages.

#6 15 марта 2026 в 18:47

 maxisoft, вы такой огромный анализ через нейросеть сделали?

#7 15 марта 2026 в 18:49

 maxisoft, вы такой огромный анализ через нейросеть сделали?

Pechora.Dev 🐻

Хотел бы сказать сам :))))) но будем честными да через агентов :)

#8 15 марта 2026 в 18:52

 maxisoft, я так и понял, потому что половина из написанного — вообще не так. Да, кое-какие проблемы агент верно нашел, но спорить с ним я не буду, потому что половина написанного — я и слов то таких не знаю 😄

И да. Статический анализ без запуска кода и тестов иногда даёт «ложные срабатывания» (как с disabled или translateX).

#9 15 марта 2026 в 19:13
 maxisoft, я так и понял, потому что половина из написанного — вообще не так.
Pechora.Dev 🐻

я не говорю что там 100500% правильного до 80% там очевидые проблемы. например утечка памяти будет 100% анимация вопрос спорный согласен так как не очевидно что у вас в direction это номер в навигации и получается что вы сдвигаете например 1 * 100 потом на 2 * 100 спорить не буду. звездоку на гитхабе поставил

#10 15 марта 2026 в 19:15

звездоку на гитхабе поставил

maxisoft

Спасибо! Тщательно все перечитал, да — замечания верные, буду оптимизировать. Эх, подкинули работы 😁

#11 15 марта 2026 в 19:23

я не буду кривить душой да я использую ИИ для разработки, оптимизации, выявления ошибок. Так жизнь теперь заставляет. Но у меня например проверку делает 3 ИИ которые спорят обсуждают между собой то есть не чисто ИИ а по факту 3 независимых эксперта и потом на основании всего что они там наобсуждали делается анализ и пишется отчет. Знаю по опыту уже в 97% они правы оказываются чтобы не галюки не ловили есть скилы под все это дело (хотя тоже не панацея)

#12 15 марта 2026 в 19:27

 maxisoft, да, забирают у нас с вами работу, сейчас в каждого второго тыкни на улице — вайбкодер 😁

#13 15 марта 2026 в 19:30
 maxisoft, да, забирают у нас с вами работу, сейчас в каждого второго тыкни на улице — вайбкодер 😁
Pechora.Dev 🐻

время меняется и тут ничего не сделать точно также как трактора в прошлом отняли работу у землекопов.

#14 15 марта 2026 в 19:47

 maxisoft, а вы какой ии используете?

#15 15 марта 2026 в 20:53
 maxisoft, а вы какой ии используете?
Pechora.Dev 🐻

для каждой задачи своя. для картинок Гемини с Нанобана2 для кодинга там полный улет GLM 5 Kimi 2,5 Minimax Owen — жду дипсик 4 в основном китайцы работают супер без впн и прочих приблуд и оплата нормально через алипей или вичат у меня. А самая умная уже смотрит за всеми и принимает решение claude code — причем разные ИИ для плана и для реализации. а ну и еще ряд локальных ИИ от qwen до mistral и deepseek для внутренних задач и агентов типа openclaw локально еще стоит n8n для автоматизации процессов

Вы не можете отвечать в этой теме.
Войдите или зарегистрируйтесь, чтобы писать на форуме.
🍪Мы используем файлы cookie для работы сайта. Читать подробнее.