4.1 KiB
Джойстик: редизайн під референс + два реальні баги (2026-08-13)
Референс: прозора середина, градієнтний бордер, помаранчева точка пальця
з підсвіткою навколо. JoystickC.init() (SDK-обгортка nipplejs) приймає
будь-які опції nipplejs напряму, включно з color: {back, front} —
кожен рядок йде прямо в background відповідного div, підтримує
градієнти й навіть var()/calc() (живі CSS-змінні всередині inline
style реально оновлюються).
Фінальна реалізація (beforeResourcesLoadedCb.ts + main.css):
back(кільце) —conic-gradient(from var(--joy-angle), ...), базовий колір однотонний темний, підсвітка (тон точки пальця) лише у широкій дузі навпроти пальця, зcalc()-інтерполяцією RGB-каналів (не альфи!) за--joy-force.front(точка) — суцільний плоский колір, без градієнта/тіні.- Форма кільця (прозора середина) —
mask-image: radial-gradient(...)з абсолютними px, не відсотками — щоб змінаsize(радіус зони) не розтягувала товщину бордера пропорційно. - Розмір точки пальця (
.front) — фіксований px-оверрайд, повністю відв'язаний відsize(nipplejs хардкодить точку якsize/2, тож збільшення радіуса зони інакше тягнуло за собою і точку). JoystickC.onJoysticMove— окрема підписка (SDK підтримує кілька делегатів на подію,PlayerCпідписаний окремо на той самий івент для руху) ставить--joy-angle/--joy-forceнаinstance.ui.elщокадру.
⚠️ Знайдений і виправлений баг: підсвітка на 90° проти стрілки від
реального положення пальця. Math.atan2(y, x) на скрін-координатах (y
вниз) і CSS conic-gradient(from Xdeg, ...) обидва рахують по
годинниковій, але з різною точкою нуля: atan2 — схід (3 година),
conic-gradient — північ (12 година). Фікс — плюс 90° один раз, не свап
знаку і не переписування напрямку градієнта.
⚠️ Знайдений і виправлений баг: підсвітка не зупинялась на межі
зони, а продовжувала змінюватись, коли палець вели далі за край.
Трасування в самому nipplejs (Collection.ts): force рахується з
СИРОЇ, необмеженої дистанції дотику (dist / size), тоді як
frontPosition (сама видима точка й кут вище) — з ОБМЕЖЕНОЇ. За краєм
кільця force продовжує необмежено зростати, хоча точка вже візуально
запінена на місці — усі calc() розраховані на force в межах 0..1.
Це ж переповнення й давало жовтуватий відтінок (RGB-канали переїжджали
за цільовий колір). Фікс — один Math.min(Math.max(force, 0), 1) перед
записом у CSS-змінну, а не clamp у кожному calc() окремо.
Розмір: size (радіус зони) підняли на +50%, потім усі елементи
(зона+точка+товщина кільця) зменшені на -30% від того — фінальні числа:
size: 105, точка 35px/-17.5px margin, кільце 43.4/44.8/46.9/48.3px.