Publicat per

DropApp – PR2

Publicat per

DropApp – PR2

1. Ideació i Evolució del Projecte Concepte: DropApp evoluciona d’un temporitzador passiu (PR1) a un assistent oftalmològic contextual. La sequedat ocular depèn…
1. Ideació i Evolució del Projecte Concepte: DropApp evoluciona d’un temporitzador passiu (PR1) a un assistent oftalmològic contextual. La…

1. Ideació i Evolució del Projecte

Concepte:

DropApp evoluciona d’un temporitzador passiu (PR1) a un assistent oftalmològic contextual. La sequedat ocular depèn directament de la humitat ambiental. Per tant, l’App no només avisa quan posar-se les gotes, sinó que informa l’usuari de l’estat del seu entorn immediat.

Selecció d’APIs (Estratègia de Dades):

Per oferir una experiència completa, he optat per combinar dues APIs complementàries:

  • BigDataCloud (Reverse Geocoding): Permet traduir les coordenades GPS fredes (ex: 41.38, 2.17) a un nom de ciutat comprensible per a l’usuari (ex: “Barcelona”).
  • Open-Meteo (Temps): Aporta la dada mèdica rellevant (% Humitat Relativa) sense necessitat de registre ni claus d’API.

Esbós preliminar de l’app

2. Desenvolupament Tècnic amb Capacitor

2.1. Arquitectura Híbrida

L’aplicació segueix el patró Bridge:

  • Capa Lògica (main.js): Actua com a orquestrador. Gestiona la geolocalització nativa i encadena les peticions a les dues APIs.

  • Capa Visual (sketch.js): Rep les dades processades (Nom de ciutat i Humitat) a través d’un objecte global compartit window.eyeWeather i les pinta al canvas

2.2. Integració de les APIs (Flux en Cascada)

S’ha implementat una lògica asíncrona robusta (async/await) al fitxer main.js per connectar el dispositiu amb les dues APIs externes:

  1. GPS Natiu (Geolocation): El plugin @capacitor/geolocation obté la latitud i longitud precises quan l’usuari té activat el mode “Ubicació GPS (Automàtic)”. S’utilitza enableHighAccuracy: true i un timeout de 10 segons per evitar bloquejos.

  2. Identificació (API 1 – BigDataCloud): Amb les coordenades rebudes, es consulta l’endpoint reverse-geocode-client de BigDataCloud amb el paràmetre localityLanguage=ca, prioritzant el nom de ciutat/localitat en català sempre que sigui possible.

  3. Dades Climàtiques (API 2 – Open-Meteo): A partir de la mateixa latitud/longitud es consulta Open-Meteo per obtenir la temperatura actual i la humitat relativa (temperature_2mrelative_humidity_2m), sense necessitat de registres ni claus d’API.

  4. Persistència i flux manual: Si l’usuari desactiva el GPS i selecciona una ciutat manualment, les coordenades escollides es desen a localStorage i es reutilitzen a les crides següents, mantenint el flux de dades encara que el GPS estigui aturat.

  5. Fallback per IP: Si no disposem de coordenades (primera obertura, error de GPS) l’app consulta de nou BigDataCloud, però en aquest cas mitjançant geolocalització per IP, per obtenir unes coordenades aproximades i un nom de ciutat genèric com a reserva.

  6. Sincronització i estats UX: Mentre esperem resposta de les APIs, l’objecte global window.eyeWeather mostra un estat de “????️ Cercant GPS” per indicar activitat. Si alguna de les crides falla, l’App entra en “Mode Offline (Sense dades)”, però evita trencar el flux visual del temporitzador i manté un estat de seguretat per a l’usuari.

2.3. Funcionalitats Natives

A part de la geolocalització, s’han integrat tres funcionalitats hardware per a l’experiència d’alerta:

    • Llanterna (@capawesome/capacitor-torch): Des de sketch.js es controla una màquina d’estats (0 = off, 1 = llum fixa, 2 = estroboscòpic) i, en funció del temps restant, es fan crides a window.setFlashMode() exposada per main.js. Aquest pont és el que activa o desactiva realment el maquinari de la llanterna al dispositiu.

    • Haptics (@capacitor/haptics): main.js encapsula el patró de vibració en bucle (setInterval) quan sona l’alarma final, i sketch.js hi accedeix mitjançant window.dropappVibrate() per donar feedback tàctil immediat en prémer els botons.

    • Local Notifications: Per garantir l’avís fins i tot si el dispositiu entra en repòs profund (Doze Mode), main.js programa l’alarma en el moment d’iniciar el comptador utilitzant la propietat allowWhileIdle i canals prioritaris. Això delega la responsabilitat al sistema operatiu, assegurant la puntualitat exacta independentment de l’estat de l’app.

Integració final mostrant ubicació i dades ambientals.

Temporitzador acabat, moment on està activat el flash, la vibració i on apareix la notificació

2.4. Mode de proves (interval 0)

Durant el desenvolupament ha estat necessari verificar el comportament del temporitzador i de les alertes sense haver d’esperar una hora real entre dosis. Per això, al fitxer sketch.js he implementat un mode prova:

  • L’usuari pot configurar les “Hores entre dosis” a 0 mitjançant la finestra de configuració.

  • Si el valor llegit des de localStorage és 0, l’aplicació interpreta que es tracta d’un mode debug i força l’interval intern a 1 minut (60 * 1000 ms) en lloc d’1 hora (60 * 60 * 1000 ms).

  • Això permet testejar totes les fases de l’alarma (pre-avís, estroboscopi, vibració i notificació) de forma ràpida, mantenint la configuració normal per a l’ús mèdic real.

D’aquesta manera puc comprovar el flux complet de l’app (UI p5.js + hardware + notificacions) sense haver d’esperar períodes llargs.

2.5. Resiliència i Gestió del Segon Pla

Per garantir que l’usuari rebi l’avís de la gota encara que el sistema operatiu “congeli” el JavaScript de l’App per estalviar bateria (comú en Android), he implementat una Estratègia Híbrida de Resurrecció:

  • Alarmes Exactes Nativament: He configurat els permisos SCHEDULE_EXACT_ALARM i USE_EXACT_ALARM a l’AndroidManifest. Això permet que el sistema natiu de notificacions desperti el dispositiu en el moment precís, independentment de l’estat de l’App.

  • Sincronització al Resume: Al fitxer main.js, he programat un listener del cicle de vida (resume). Quan l’usuari obre l’App des de la notificació, el codi compara immediatament el Timestamp actual amb l’hora objectiu emmagatzemada a localStorage.

  • Feedback Immediat: Si el temps s’ha esgotat durant el segon pla, l’App reactiva instantàniament les funcions de hardware (flash estroboscòpic i vibració) i l’estat d’alarma visual a p5.js, garantint una transició fluida i sense errors entre el segon pla i el primer pla.

3. Decisions Preses i Solució de Problemes

Un aspecte clau del disseny va ser la interpretació visual de les dades (Data Viz). No volia que l’usuari hagués d’interpretar xifres fredes. Per això, vaig implementar una lògica reactiva: si l’API d’Open-Meteo detecta una humitat inferior al 35% (llindar de risc per ull sec), l’app canvia automàticament el text d’estat a “Ambient SEC (Risc sequetat ocular)” i tenyeix la gota central de color ambre/groc. Això ofereix un diagnòstic visual instantani sense necessitat de lectura atenta.

Un altre repte va ser la gestió de noms de ciutat llargs al canvas. Ciutats com ” Colinas del Campo de Martín Moro” es tallaven visualment, així que al sketch.js vaig optar per utilitzar caixes de text delimitades que permeten el salt de línia automàtic (text wrapping), mantenint el text sempre centrat i llegible.

La latència de les APIs també va aparèixer com a problema: com que es fan dues crides externes (BigDataCloud + Open-Meteo), el temps de resposta podia allargar-se. Per evitar la sensació que l’app s’havia penjat, vaig afegir un estat intermedi “Cercant GPS…” a l’objecte global window.eyeWeather, de manera que l’usuari rep feedback immediat mentre arriba la informació.

Pel que fa als permisos de GPS, a Android 13 l’app fallava si no tenia ACCESS_FINE_LOCATION declarat al AndroidManifest.xml. A més d’afegir el permís, vaig introduir un timeout de 10 segons a la crida de geolocalització per evitar bloquejos en entorns amb mala cobertura de satèl·lits.

També es va detectar un crash relacionat amb les notificacions per falta del recurs gràfic de la icona. La solució va passar per generar el recurs ic_stat_dropapp dins de res/drawable i referenciar-lo a la configuració de LocalNotifications.schedule(), assegurant que Android disposa sempre d’una icona vàlida per mostrar l’avís.

Finalment, per garantir que l’alerta fos efectiva en entorns sorollosos o quan el dispositiu no és a la vista, es va decidir combinar tres canals: l’efecte visual de la llanterna i el fons “d’alarma”, la vibració repetida amb @capacitor/haptics i la notificació de sistema. Aquesta decisió reforça l’ús del maquinari natiu i millora l’accessibilitat general de l’app.

Objecte global:

window.eyeWeather: Sincronitza dades API entre main.js (productor) i sketch.js (consumidor), amb estats UX (“Cercant GPS…”, “Mode Offline”).

Finestra flotant de la configuració i cerca de GPS

4. Pròxims Passos: Publicació i Beta

Per convertir aquest MVP en una versió final preparada per a la Google Play Store, els passos següents són:

  • Optimització de Processos en Background: Tot i que l’estratègia actual de resurrecció és efectiva, el següent pas tècnic seria implementar @capacitor/background-runner. Això permetria que l’App seguís consultant l’API meteorològica de forma invisible per a l’usuari, actualitzant el diagnòstic climàtic fins i tot si l’App no s’obre en tot el dia.

  • Signatura de l’Aplicació (Keystore): Cal generar un Android App Bundle (.aab) signat criptogràficament des d’Android Studio. Aquest és un requisit indispensable de seguretat per identificar-me com a desenvolupador oficial davant de Google.

  • Privacitat i GDPR: Atès que l’App fa ús de geolocalització precisa i APIs de tercers (BigDataCloud/Open-Meteo), és necessari redactar i enllaçar una Política de Privacitat formal. En ella s’ha d’especificar que les coordenades GPS s’utilitzen de manera efímera i no s’emmagatzemen en servidors externs.

  • Proves en més dispositius: Tot i que el funcionament en Android 15 (Xiaomi) és correcte, caldria testejar l’App en versions anteriors d’Android (11 i 12) per assegurar que la gestió de permisos natius es comporta de manera consistent.

5. Referències i Recursos Utilitzats

Serveis de Dades (APIs)

  • Open-Meteo Weather API: Servei de dades meteorològiques (Humitat Relativa) sota llicència Creative Commons (CC BY 4.0). [https://open-meteo.com/]

  • BigDataCloud Reverse Geocoding: API client-side per a la transformació de coordenades a toponímia. Versió gratuïta per a desenvolupadors. [https://www.bigdatacloud.com/]

Tecnologies i Llibreries

  • Nucli: Capacitor (v6) per a la compilació nativa Android.

  • Visualització: p5.js (Processing Foundation) per al renderitzat del canvas i animacions.

  • Plugins de Sistema:

    • @capacitor/geolocation: Accés al GPS natiu.

    • @capacitor/local-notifications: Gestió d’avisos en segon pla.

    • @capacitor/haptics: Motor de vibració del dispositiu.

    • @capawesome/capacitor-torch: Control del maquinari de la llanterna (Flash).

Repositori del Projecte

  • Codi Font: Repositori públic disponible a GitHub: [https://github.com/Javime85/DropApp-PR2]

Debat0el DropApp – PR2

No hi ha comentaris.

Publicat per

Ideació de DropApp

Publicat per

Ideació de DropApp

Pomodoro base amb Vite, p5.js i Capacitor Abans de dissenyar DropApp, vaig seguir un tutorial de Pomodoro Timer per entendre el flux complet entre Vite, p5.js i Capacitor.…
Pomodoro base amb Vite, p5.js i Capacitor Abans de dissenyar DropApp, vaig seguir un tutorial de Pomodoro Timer per entendre el…

Pomodoro base amb Vite, p5.js i Capacitor

Abans de dissenyar DropApp, vaig seguir un tutorial de Pomodoro Timer per entendre el flux complet entre Vitep5.js i Capacitor. Vaig crear un projecte amb plantilla vanilla de Vite, afegir p5.js i p5.sound com a scripts clàssics al directori public, i utilitzar el mode instància per evitar conflictes de variables globals.

Captura del navegador amb el primer canvas

A continuació vaig implementar un Pomodoro complet a src/sketch.js: dues fases (25 min treball + 5 min pausa), cercle de progrés, temps gran al centre i botó play/pausa. La targeta vertical centrada millora la llegibilitat i prepara la base visual per DropApp.

Captura del navegador amb el Pomodoro final

Finalment vaig integrar Capacitor, afegir la plataforma Android, generar el build amb npm run build i copiar-lo amb npx cap copy android. Al Android Studio es va executar en emulador i dispositiu físic, comprovant que el Pomodoro funciona igual que al navegador.

Captura d’Android Studio amb l’emulador mostrant el Pomodoro

Captura del telèfon físic amb el Pomodoro en execució

Ideació de DropApp

Partint del tutorial Pomodoro, vaig adaptar el context cap a una necessitat personal: recordar la pauta de gotes oftalmològiques diàries. DropApp mostra el temps fins a la pròxima dosi amb un cercle animat i botó de confirmació, més una configuració mínima (hores entre dosis + mode fosc).

Esbós de com volia que fos inicialment la pàgina principal

Esbós de com volia que fos inicialment la pàgina de configuració

Desenvolupament i adaptació del tutorial

Un cop el Pomodoro funcionava empaquetat amb Capacitor a Android Studio, vaig adaptar el codi:

  • Texts de “treball” → missatges sobre gotes

  • Cercle → temps fins a pròxima dosi

  • Temporitzador → hores en lloc de minuts

Captura del navegador amb DropApp funcionant 

Captura DropApp a Xiaomi Redmi Note 14 Pro

Vaig afegir un panell de configuració (botó ⚙️) per definir hores entre dosis i activar mode fosc, guardant valors a localStorage.

Panell de configuració obert al navegador

Panell configuració al dispositiu

El logotip dissenyat com “p” + ull + gota es va processar amb Android Studio Image Asset per icones adaptatives.

Logotip original DropApp “p + ull + gota”

Icona de DropApp al launcher del Xiaomi Redmi Note 14 Pro

Integració de funcionalitats natives

Per complir el requisit d’integrar funcionalitats natives s’ha utilitzat el plugin Haptics de Capacitor per generar feedback de vibració quan l’usuari prem el botó “M’he posat les gotes” i quan el temporitzador arriba a zero, moment en què es vol reforçar que toca una nova aplicació del col·liri. A més, s’ha provat el plugin de Local Notifications per mostrar una notificació amb so quan s’esgota el temps, amb l’objectiu que l’usuari rebi l’avís encara que no estigui mirant la pantalla.

​Fragment de codi destacant la crida a Haptics i LocalNotifications 

Per a les funcionalitats natives he emprat el plugin Haptics per generar vibració quan l’usuari marca que s’ha posat les gotes i quan el temporitzador arriba a zero, i he provat Local Notifications per programar avisos amb so encara que l’app estigui en segon pla.

Llanterna + vibració activades quan el temporitzador arriba a zero (Xiaomi Redmi Note 14 Pro)

Durant les proves s’ha detectat que, en el dispositiu Xiaomi utilitzat, la vibració i el so de notificació estan fortament condicionats per la configuració de MIUI i les opcions de seguretat. Tot i que el codi fa les crides correctes als plugins, en alguns casos la vibració és imperceptible o les notificacions queden limitades, fet que es documenta com a limitació del dispositiu i no de la lògica de l’app.

Problemes trobats i solucions

Problema Solució
INSTALL_FAILED_USER_RESTRICTED Activar “Instal·lació USB” a opcions desenvolupador MIUI
p5.sound “Loading…” Eliminar so web → Haptics + navigator.vibrate()
Pantalla negra Android WebView + configuració dispositiu (funciona navegador)
Timer segon pla Pendent: timestamp localStorage + notificació nativa

Mirant cap a la PR2

De cara a la PR2 es planteja mantenir DropApp com a eina de recordatori de gotes, peròenriquir-la amb una API externa gratuïta i sense autenticació. Es considera especialment interessant una API de clima o humitat, com ara Open-Meteo, per mostrar a l’usuari dades ambientals relacionades amb la sequedat ocular (temperatura, humitat relativa, vent) i contextualitzar la importància de seguir la pauta de gotes.​

Mockup de com es podria veure

Això permetrà que, a la PR2, DropApp no només recordi quan aplicar la gota, sinó que també ofereixi informació externa rellevant per comprendre millor per què alguns dies els símptomes de sequedat ocular poden ser més intensos.

Referències i eines

  • HTML5. Llenguatge de marcat per estructurar la interfície base de l’aplicació híbrida.
  • CSS3. Utilitzat per disseny visual, disposició responsive i mode fosc/clar de DropApp.
  • JavaScript (ES6+). Llenguatge principal per lògica del temporitzador, gestió d’estats, controls UI i comunicació amb plugins natius.
  • p5.js. Llibreria per canvas interactiu, animació gota procedimental (bézier + map()) i cercle progrés (arc()).
    **p5.js Reference. (2025). arc() & bezierVertex(). https://p5js.org/reference**
  • Capacitor 6. Framework per empaquetar app web en aplicació mòbil Android, pont entre JavaScript i APIs natius.
    • @capacitor/haptics. Plugin natiu per vibració (ImpactStyle.Heavy) al confirmar gotes i final temporitzador.
    • Capacitor Documentation. (2025). Haptics Plugin API. https://capacitorjs.com/docs/apis/haptics**
      @capacitor/local-notifications. Plugin per notificacions locals amb so quan s’esgota interval de dosis.
    • Ionic Team. (2025). Local Notifications Plugin. https://capacitorjs.com/docs/apis/local-notifications**
      @capawesome/capacitor-torch. Plugin per llanterna (fix + parpelleig) al final temporitzador.
  • localStorage. Emmagatzematge persistent per configuració (hores dosis + mode fosc).
  • Android Studio. Entorn desenvolupament per compilar APK, executar emulador/dispositiu, analitzar Logcat i generar icones adaptatives amb Image Asset Studio.
  • Vite. Build tool per desenvolupament ràpid (HMR) i optimització producció (npm run build).
  • Node.js & npm. Gestió dependències i execució comandes Capacitor (npx cap sync android).
  • Xiaomi Redmi Note 14 Pro (Android 15). Dispositiu proves principals amb HyperOS/MIUI limitacions documentades.
  • Perplexity AI. Assistència IA per ideació mockups PR2 (Open-Meteo API + gràfics humitat).

Debat0el Ideació de DropApp

No hi ha comentaris.

Publicat per

Rellotge Orbital Pomodoro

Publicat per

Rellotge Orbital Pomodoro

1. Introducció En aquest repte he desenvolupat una extensió per al navegador Firefox anomenada Rellotge Orbital Pomodoro. L’objectiu principal és combinar un rellotge…
1. Introducció En aquest repte he desenvolupat una extensió per al navegador Firefox anomenada Rellotge Orbital Pomodoro. L’objectiu principal és…

1. Introducció

En aquest repte he desenvolupat una extensió per al navegador Firefox anomenada Rellotge Orbital Pomodoro. L’objectiu principal és combinar un rellotge orbital abstracte amb un temporitzador Pomodoro clàssic, de manera que l’usuari pugui controlar els seus cicles de treball i descans directament des de la barra del navegador.

L’extensió mostra un rellotge amb tres òrbites (hores, minuts i segons), un arc exterior que indica el progrés del Pomodoro i tres fases principals: treball, descans curt i descans llarg. A més, les dades de la sessió es guarden perquè, encara que es tanqui la popup, en reobrir-la es pugui continuar exactament on s’havia deixat.

2. Ideació i esbossos

La idea de partida va ser reutilitzar el “Rellotge Creatiu” del repte anterior i portar-lo a un context més funcional: una extensió que ajudi a aplicar la tècnica Pomodoro. Volia mantenir el caràcter visual i experimental del rellotge orbital, però afegint-hi botons, fases i sons que el convertissin en una eina real de productivitat.

Figura 1. Esbós inicial de la interfície del rellotge orbital Pomodoro.

En aquest esbós es pot veure la idea general: tres òrbites de colors amb punts en moviment, un arc exterior per indicar el progrés i una imatge central per diferenciar la fase. A la part inferior hi apareixen les icones de play, pausa i reinici, que més endavant es van substituir per botons amb text per millorar la claredat.

3. Disseny de la interfície

La interfície està pensada per encaixar en un popup de 300 × 150 píxels. La part superior està ocupada pel canvas de p5.js, on es dibuixen el rellotge orbital i l’arc de progrés. Just a sota hi ha el text amb la fase actual (Treball, Descans curt, Descans llarg) i a la part inferior hi ha tres botons: IniciarPausa i Reinicia.

Els colors de les òrbites i de l’arc canvien segons la fase per donar un feedback visual ràpid. Quan canvia la fase també es mostra una imatge diferent al centre del rellotge (icona de treball, descans curt o descans llarg) i es reprodueix un so curt.

Figura 2. Vista del popup en fase de treball, amb el rellotge orbital, la imatge de fase i els botons “Iniciar”, “Pausa” i “Reinicia”.

4. Funcionament intern i lògica

El temporitzador segueix l’estructura clàssica de la tècnica Pomodoro: 25 minuts de treball, 5 de descans curt i 15 de descans llarg cada quatre cicles. La funció setPomPhase(newPhase) s’encarrega de configurar cada fase (durada, colors, so i imatge central) i de posar en marxa el comptador.

En cada fotograma de p5.js, la funció updatePomodoro() calcula el temps transcorregut i obté un percentatge de progrés entre 0 i 1. Aquest valor s’utilitza per dibuixar l’arc exterior del rellotge i, quan arriba a 1, es crida nextPomPhase() per passar automàticament a la fase següent. Paral·lelament, els punts orbitals continuen mostrant l’hora real del sistema, de manera que el rellotge combina informació funcional i estètica.

Un dels punts més delicats va ser la gestió de la pausa i la represa. Per resoldre-ho, vaig introduir la variable pomPausedElapsed, que acumula el temps ja consumit de la fase. Quan es reprèn el temporitzador, aquest valor es té en compte per no tornar a començar des de zero.

5. Persistència d’estat amb storeItem() i getItem()

Com que les popups d’extensions Manifest V3 es destrueixen quan es tanquen, era necessari guardar l’estat del Pomodoro per no perdre el progrés. Per això he utilitzat storeItem() i getItem() de p5.js, que internament fan servir localStorage.

  • savePomodoroState() desa un objecte amb la fase actual, la durada de la fase, el temps acumulat, el nombre de cicles i si el temporitzador està en marxa o no. També guarda un lastUpdate per saber quan es va fer l’últim guardat.

  • loadPomodoroState() es crida al setup() i recupera aquest objecte. Si el temporitzador estava actiu, calcula quant de temps real ha passat des de llavors i ajusta el comptador perquè continuï on tocaria.

Gràcies a aquest mecanisme, si tanco la popup en mig d’una sessió i la torno a obrir al cap d’uns minuts, el temps està actualitzat i la fase continua sense haver-se de reiniciar manualment.

6. Problemes trobats i solucions

Al llarg del desenvolupament han aparegut diversos problemes interessants:

  • Compatibilitat d’àudio amb Manifest V3:
    Inicialment vaig provar d’utilitzar la biblioteca p5.sound, però dins d’una extensió Firefox amb Manifest V3 no es carregava correctament. La solució va ser substituir-la per l’API nativa d’HTML5 (new Audio()), que funciona bé en el context del popup.

  • Pausa i represa del temporitzador:
    A les primeres versions, en pausar i tornar a iniciar, el temporitzador es desquadrava o es reiniciava. Ho vaig solucionar desant el temps acumulat en pomPausedElapsed i recalculant el temps transcorregut a cada represa.

  • Sincronització del temps en reobrir la popup:
    Com que millis() es reinicia cada vegada que es carrega el canvas, calia saber quant temps real havia passat des de l’últim guardat. Per això guardo també lastUpdate i, en carregar l’estat, calculo la diferència amb el millis() actual.

  • Espai limitat al popup:
    Treballar amb 300 × 150 píxels obliga a simplificar molt el disseny. He ajustat la mida de les òrbites i dels botons per evitar solapaments i mantenir una jerarquia visual clara.

7. Reflexió i aprenentatges

Aquest repte m’ha ajudat a entendre millor com funcionen les extensions de navegador i quines són les diferències entre una pàgina web normal i un popup d’extensió. També he après a treballar amb l’API de localStorage a través de p5.js, i a pensar en termes d’estat persistent, no només de variables en memòria.

A nivell de disseny, m’ha servit per veure com un projecte més “artístic” (el rellotge creatiu) es pot convertir en una eina funcional afegint-hi controls, fases i persistència. El procés d’anar ajustant colors, sons i animacions fins que el feedback fos coherent ha estat molt útil per entendre la importància de la UX, fins i tot en interfícies tan petites com una popup.

De cara al futur, m’agradaria afegir funcionalitats com ara estadístiques de sessions completades, notificacions del navegador quan s’acaba una fase, i la possibilitat de personalitzar les durades dels intervals. Tot i això, considero que la versió actual compleix els objectius del repte i proporciona una bona base per seguir evolucionant el projecte.

Debat0el Rellotge Orbital Pomodoro

No hi ha comentaris.

Publicat per

Healthy Smile App

Publicat per

Healthy Smile App

Descripció general Aquesta PAC consisteix a desenvolupar una aplicació interactiva d’escriptori (Electron + p5.js) pensada per ajudar la mainada a agafar hàbits…
Descripció general Aquesta PAC consisteix a desenvolupar una aplicació interactiva d’escriptori (Electron + p5.js) pensada per ajudar la mainada…

Descripció general

Aquesta PAC consisteix a desenvolupar una aplicació interactiva d’escriptori (Electron + p5.js) pensada per ajudar la mainada a agafar hàbits saludables, concretament mantenir la boca oberta, gràcies a una detecció facial automàtica en temps real ambientada amb temàtica de Halloween.

Procés de treball

He començat revisant llibreries de detecció facial per p5.js i, després de comparar opcions (MediaPipe, ml5.js, face-api.js), he seleccionat MediaPipe per precisió i facilitat.
He fet diversos esbossos a mà i amb Figma sobre l’estructura de l’app i les partícules. El disseny visual s’ha adaptat a la temàtica de Halloween, escollint il·lustracions i sons lliures de drets i afegint animacions de ratpenats.

Esbós inicial de pantalla principal:
Dibuix que il·lustra l’estructura general, els botons i el missatge inicial.

Durant el desenvolupament he tingut dos grans reptes:

  • Integrar la detecció facial en temps real a Electron sense perdre rendiment.

  • Ajustar les partícules perquè reaccionin de manera fluida quan s’obre la boca i fer que l’efecte fos atractiu per a infants.

Finalment, he empaquetat tot el projecte i documentat instruccions detallades al README, així com els crèdits dels recursos usats.

Prototip i validació d’interacció

Per validar que el funcionament i la interfície fossin adequats he fet un esbós secundari representant l’app en execució amb l’usuari davant la webcam.


Esbós de la pantalla de l’app amb la webcam activa, mostrant la detecció facial.

Tecnologies i decisions

  • Electron: per crear l’entorn d’escriptori multiplataforma.

  • p5.js: per gestionar la gràfica, animacions i càmera.

  • MediaPipe: per a la detecció premade de punts de la cara i obertura de la boca.

  • CSS separat: per personalitzar fàcilment l’estètica.

He triat aquestes eines perquè faciliten la integració de webcam i animació, i tenen molta documentació, així com una comunitat activa.

Flux de funcionament

  • L’usuari obre l’aplicació i prem “Començar”.

  • Es demana accés a la webcam i es mostra el flux de vídeo.

  • La llibreria MediaPipe detecta la boca: quan s’obre, apareixen partícules animades i s’activa un so.

  • Quan es tanca la boca, els efectes s’aturen i es mostra un missatge d’“obre la boca per continuar”.

  • En qualsevol moment es pot tancar l’app amb el botó o la tecla ESC.

Vídeo real de l’aplicació detectant la boca i mostrant els efectes dinàmics. 

Recursos visuals i atribució

  • Il·lustracions de ratpenats: Bats silhouettes isolated – Freepik — Llicència: Ús gratuït amb atribució.

  • Efecte de so de ratpenat: bat-chirping-sounds — Pixabay — Llicència: Ús gratuït sota llicència de contingut de Pixabay.

Enllaços

Debat0el Healthy Smile App

No hi ha comentaris.

Publicat per

Rellotge orbital

Publicat per

Rellotge orbital

1. Concepte i Objectiu El projecte “Rellotge Orbital” neix de la voluntat de reinterpretar la representació del temps, allunyant-se de les convencions…
1. Concepte i Objectiu El projecte “Rellotge Orbital” neix de la voluntat de reinterpretar la representació del temps, allunyant-se…

1. Concepte i Objectiu

El projecte “Rellotge Orbital” neix de la voluntat de reinterpretar la representació del temps, allunyant-se de les convencions analògiques i digitals. L’objectiu principal ha estat transformar una dada purament funcional —l’hora— en una experiència visual, artística i contemplativa. La inspiració fonamental prové dels moviments celestes, concebent el pas del temps com un sistema d’òrbites planetàries on cada element té el seu propi cicle i ritme, però conviu en un mateix univers harmònic. Es busca que l’espectador no només “llegeixi” l’hora, sinó que “senti” el flux constant i cíclic del temps.

2. Procés Creatiu i Referències

La fase d’ideació va començar explorant referents d’art generatiu i visualitzacions de dades abstractes. Projectes com “About Time” de Louie Rigano van ser una inspiració clau per entendre com es pot representar el temps sense números, utilitzant únicament la posició, la forma i el color.

El procés d’esbós ha estat iteratiu i ha passat per diverses etapes, documentades a les imatges adjuntes:

  • Esbossos inicials a mà (esbos_1.jpgesbos_2.jpg): Les primeres idees van ser explorades sobre paper amb llapis. Aquests esbossos buscaven definir l’estructura bàsica de les òrbites concèntriques i la disposició jeràrquica dels tres elements principals que representarien les hores, els minuts i els segons. L’objectiu era trobar un equilibri visual i una composició neta.

esbos_1.jpg
esbos_2.jpg
  • Esbossos digitals i proves de color (Esbos_3.jpgEsbos_4.jpg): Un cop definida l’estructura, el procés va passar a un format digital. En aquesta fase es va experimentar amb la paleta de colors sobre un fons neutre per assignar una personalitat a cada unitat de temps i validar l’harmonia cromàtica, tal com es mostra a Esbos_3.jpg (amb el punt ja corregit a groc) i Esbos_4.jpg, que representa la fusió entre el concepte original i l’execució digital.

Esbos_3.jpg
Esbos_4.jpg

3. Implementació i Desenvolupament Tècnic

El projecte s’ha desenvolupat íntegrament amb la llibreria p5.js, aprofitant el seu potencial per a la creació gràfica i la interactivitat.

  • Lògica temporal: El nucli del rellotge utilitza les funcions hour()minute() i second() de p5.js per mapejar el temps actual a la posició angular de cada un dels tres punts sobre les seves respectives òrbites.

  • Paleta de colors: Es va definir una paleta de colors càlids per diferenciar clarament cada unitat temporal i dotar-la de caràcter:

    • Segons: Un groc lluminós (RGB: 255, 230, 100) per transmetre rapidesa.

    • Minuts: Un taronja vibrant (RGB: 255, 160, 60) que actua com a pont cromàtic.

    • Hores: Un vermell intens (RGB: 255, 80, 80) per a l’element amb més pes temporal.

  • Tipografia: La font Roboto s’ha utilitzat de manera minimalista, només per mostrar el títol i l’autoria a la part inferior dreta. Aquesta decisió manté el llenç principal lliure de text, centrant tota l’atenció en l’experiència visual.

  • Disseny responsive: El disseny s’ha programat per adaptar-se a diferents mides de pantalla, assegurant que la composició es mantingui centrada i proporcionada, tal com es demostra a les captures finals.

Esbossos Visuals del Procés

Esbós a mà (Fase 1) Esbós a mà (Fase 2) Esbós digital (Color) Concepte-Resultat

5. Resultat Final i Captures

(Aquí pots inserir les teves captures de pantalla del projecte final dins del Folio)

Resolució 1920×1080 Resolució 1280×720

6. Enllaç al Projecte en Pantalla Completa

https://editor.p5js.org/javivillalon8/full/LXmfu3XRe

7. Valoració i Aprenentatges

El principal repte d’aquest projecte ha estat l’equilibri entre l’abstracció artística i la funcionalitat comunicativa. Aconseguir que una representació no convencional del temps fos intuïtiva i estèticament agradable ha requerit un procés continu de prova i error, especialment en l’ajust de la velocitat, el color i la jerarquia visual.

A nivell tècnic, aquest repte m’ha permès aprofundir en conceptes d’animació amb p5.js, la implementació de disseny responsive i la gestió d’una estructura de codi modular i ordenada. Creativament, ha estat un exercici molt enriquidor per explorar com la tecnologia pot servir per crear metàfores visuals i experiències poètiques a partir de dades quotidianes.

Debat0el Rellotge orbital

No hi ha comentaris.