Cómo crear un Favicon que cambie automáticamente
El otro día encontré este creador de Favicon gratuito. Es una buena herramienta para crear un favicon (fiel a su nombre), pero a diferencia de otros generadores de favicon, este te permite crear uno desde cero comenzando con un personaje o un emoji. Naturalmente, tenía curiosidad por mirar el código para ver cómo funciona y, mientras lo hacía, me hizo pensar en diferentes direcciones. Me acordé de algo que leí que dice que es posible cambiar dinámicamente el favicon de un sitio web. En realidad, eso es lo que algunos sitios web usan como una especie de notificación para los usuarios: cambiar el favicon a un punto rojo o algún otro indicador que comunique que algo está sucediendo o ha cambiado en la página.
Comencé a explorar los emojis a través de emojipedia.org en busca de inspiración y fue entonces cuando se me ocurrió: ¿por qué no mostrar la hora con un emoji de reloj () y otros favicons relacionados? La idea es consultar la hora cada minuto y configurar el favicon con el emoji del reloj correspondiente indicando la hora actual.
Haremos exactamente eso en este artículo y funcionará con JavaScript simple. Sin embargo, como suelo utilizar Gatsby para sitios estáticos, también mostraremos cómo hacerlo en React. A partir de ahí, las ideas deberían poder utilizarse independientemente de lo que quieras hacer con tu favicon y cómo.
Aquí hay una función que toma un emoji como parámetro y devuelve una URL de datos válida que puede usarse como fuente de imagen (¡o favicon!):
// Thanks to https://formito.com/tools/faviconconst faviconHref = emoji = `data:image/svg+xml,svg xmlns=%22http://www.w3.org/2000/svg%22 width=%22256%22 height=%22256%22 viewBox=%220 0 100 100%22text x=%2250%%22 y=%2250%%22 dominant-baseline=%22central%22 text-anchor=%22middle%22 font-size=%2280%22${emoji}/text/svg`
Y aquí hay una función que apunta al favicon link
en head
y lo cambia a ese emoji:
const changeFavicon = emoji = { // Ensure we have access to the document, i.e. we are in the browser. if (typeof window === 'undefined') return const link = window.document.querySelector("link[rel*='icon']") || window.document.createElement("link") link.type = "image/svg+xml" link.rel = "shortcut icon" link.href = faviconHref(emoji) window.document.getElementsByTagName("head")[0].appendChild(link)}
(Agradezca esta respuesta de StackOverflow por ese pequeño truco para crear el enlace si no existe).
¡Siéntete libre de probarlos! Abra la consola JavaScript de DevTools, copie y pegue las dos funciones anteriores y llame changeFavicon(" ")
. Puedes hacerlo directamente en este sitio web y verás que el favicon cambia a ese increíble emoji bailando.
De regreso a nuestro proyecto de reloj/hora… Si queremos mostrar el emoji con el reloj emoji correcto mostrando la hora correcta, debemos determinarla a partir de la hora actual. Por ejemplo, si son las 10:00 queremos mostrar. Si son las 4.30 queremos mostrar. No hay emojis para todos los tiempos, así que mostraremos el mejor que tenemos. Por ejemplo, entre las 9:45 y las 10:14 queremos mostrar el reloj que marca las 10:00; de 10:15 a 10:44 queremos mostrar el reloj que marca las 10.30, etc.
Podemos hacerlo con esta función:
const currentEmoji = () = { // Add 15 minutes and round down to closest half hour const time = new Date(Date.now() + 15 * 60 * 1000) const hours = time.getHours() % 12 const minutes = time.getMinutes() 30 ? 0 : 30 return { "0.0": " ", "0.30": " ", "1.0": " ", "1.30": " ", "2.0": " ", "2.30": " ", "3.0": " ", "3.30": " ", "4.0": " ", "4.30": " ", "5.0": " ", "5.30": " ", "6.0": " ", "6.30": " ", "7.0": " ", "7.30": " ", "8.0": " ", "8.30": " ", "9.0": " ", "9.30": " ", "10.0": " ", "10.30": " ", "11.0": " ", "11.30": " ", }[`${hours}.${minutes}`]}
Ahora sólo tenemos que llamar changeFavicon(currentEmoji())
cada minuto aproximadamente. Si tuviéramos que hacerlo con JavaScript simple, un simple setInterval
sería el truco:
// One minuteconst delay = 60 * 1000// Change the favicon when the page gets loaded...const emoji = currentEmoji()changeFavicon(emoji)// ... and update it every minutesetInterval(() = { const emoji = currentEmoji() changeFavicon(emoji)}, delay)
La parte de reaccionar
Dado que mi blog funciona con Gatsby, quiero poder usar este código dentro de un componente de React, cambiando lo menos posible. Es inherentemente imperativo, a diferencia de la naturaleza declarativa de React, y además debe llamarse cada minuto. ¿Cómo podemos hacer eso?
Ingrese a Dan Abramov y su increíble publicación de blog. Dan es un gran escritor que puede explicar cosas complejas de una manera clara y le recomiendo encarecidamente que consulte este artículo, especialmente si desea comprender mejor los React Hooks. No es necesario que comprenda todo lo que contiene; uno de los puntos fuertes de los ganchos es que se pueden utilizar incluso sin comprender completamente la implementación interna. Lo importante es saber utilizarlo. Así es como se ve:
import { useEffect } from "react"import useInterval from "./useInterval"const delay = 60 * 1000const useTimeFavicon = () = { // Change the favicon when the component gets mounted... useEffect(() = { const emoji = currentEmoji() changeFavicon(emoji) }, []) // ... and update it every minute useInterval(() = { const emoji = currentEmoji() changeFavicon(emoji) }, delay)}
Finalmente, simplemente llame useTimeFavicon()
a su componente raíz y ¡listo! ¿Quieres verlo funcionar? Aquí hay un proyecto CodePen implementado donde puede verlo y aquí está el código del proyecto en sí.
Terminando
Lo que hicimos aquí fue improvisar tres piezas de código de tres fuentes diferentes para obtener el resultado que queremos . Los antiguos romanos dirían Divide et Impera. (Soy italiano, ¡así que por favor concédeme un poco de latín!). Eso significa "divide y vencerás". Si miras la tarea como una sola entidad, es posible que te sientas un poco ansioso: "¿Cómo puedo mostrar un favicon con la hora actual, siempre actualizada, en mi sitio web React?" Conseguir todos los detalles correctamente no es trivial.
La buena noticia es que no siempre es necesario abordar personalmente todos los detalles al mismo tiempo: es mucho más efectivo dividir el problema en subproblemas, y si alguno de ellos ya ha sido resuelto por otros, mucho más. ¡el mejor!
Suena a desarrollo web, ¿eh? No hay nada de malo en utilizar código escrito por otros, siempre que se haga de forma inteligente. Como dicen, no hay necesidad de reinventar la rueda y lo que tenemos aquí es una buena mejora para cualquier sitio web, ya sea que muestre notificaciones, actualizaciones de tiempo o cualquier cosa que se te ocurra.
Deja un comentario