Wie man ein Favicon erstellt, das sich automatisch ändert

Avatar of Carlo Martinucci
Carlo Martinucci am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Ich bin neulich auf diesen kostenlosen Favicon-Maker gestoßen. Es ist ein schönes Werkzeug, um ein Favicon zu erstellen (dem Namen alle Ehre), aber im Gegensatz zu anderen Favicon-Generatoren können Sie damit eines von Grund auf mit einem Zeichen oder Emoji erstellen. Natürlich war ich neugierig, den Code anzusehen, um zu sehen, wie es funktioniert, und während ich das tat, dachte ich in verschiedene Richtungen. Ich erinnerte mich an etwas, das ich gelesen hatte, dass es möglich ist, das Favicon einer Website *dynamisch* zu ändern. Das ist tatsächlich etwas, das einige Websites als eine Art Benachrichtigung für Benutzer verwenden: Sie ändern das Favicon zu einem roten Punkt oder einem anderen Indikator, der kommuniziert, dass etwas auf der Seite passiert oder sich geändert hat.

Ich begann, die Emojis über emojipedia.org nach Inspiration zu durchsuchen, und da traf es mich: Warum nicht die Zeit mit einem Uhr-Emoji (🕛) und anderen verwandten Favicons anzeigen? Die Idee ist, jede Minute die Zeit zu überprüfen und das Favicon mit dem entsprechenden Uhr-Emoji einzustellen, das die aktuelle Zeit anzeigt.

Das werden wir in diesem Artikel genau tun, und es funktioniert mit reinem JavaScript. Da ich jedoch häufig Gatsby für statische Websites verwende, zeigen wir auch, wie man es in React macht. Von dort aus sollten die Ideen verwendbar sein, unabhängig davon, was Sie mit Ihrem Favicon tun möchten und wie.

Hier ist eine Funktion, die ein Emoji als Parameter nimmt und eine gültige Data-URL zurückgibt, die als Bildquelle (oder Favicon!) verwendet werden kann.

// Thanks to https://formito.com/tools/favicon
const 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%22><text x=%2250%%22 y=%2250%%22 dominant-baseline=%22central%22 text-anchor=%22middle%22 font-size=%2280%22>${emoji}</text></svg>`

Und hier ist eine Funktion, die das Favicon <link> im <head> anspricht und es durch dieses Emoji ersetzt.

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)
}

(Ein besonderer Dank geht an diese StackOverflow-Antwort für diesen netten kleinen Trick, um den Link zu erstellen, falls er nicht existiert.)

Probieren Sie die Funktionen gerne aus! Öffnen Sie die JavaScript-Konsole der Entwicklertools, kopieren Sie die beiden obigen Funktionen und fügen Sie sie ein und rufen Sie changeFavicon("💃") auf. Sie können das direkt auf dieser Website tun, und Sie werden sehen, wie sich das Favicon zu diesem großartigen tanzenden Emoji ändert.

Zurück zu unserem Uhr-/Zeitprojekt… Wenn wir das Emoji mit der richtigen Uhr anzeigen möchten, die die korrekte Zeit anzeigt, müssen wir sie aus der aktuellen Zeit ermitteln. Zum Beispiel wollen wir, wenn es 10:00 Uhr ist, 🕙 anzeigen. Wenn es 4:30 Uhr ist, wollen wir 🕟 anzeigen. Es gibt nicht für jede einzelne Zeit Emojis, daher werden wir das beste anzeigen, das wir haben. Zum Beispiel wollen wir zwischen 9:45 und 10:14 Uhr die Uhr anzeigen, die 10:00 Uhr anzeigt; von 10:15 bis 10:44 Uhr wollen wir die Uhr anzeigen, die 10:30 Uhr markiert, usw.

Das können wir mit dieser Funktion tun.

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}`]
}

Jetzt müssen wir nur noch changeFavicon(currentEmoji()) etwa jede Minute aufrufen. Wenn wir das mit reinem JavaScript machen müssten, würde ein einfaches setInterval den Trick machen.

// One minute
const delay = 60 * 1000

// Change the favicon when the page gets loaded...
const emoji = currentEmoji()
changeFavicon(emoji)

// ... and update it every minute
setInterval(() => {
  const emoji = currentEmoji()
  changeFavicon(emoji)
}, delay)

Der React-Teil

Da mein Blog von Gatsby betrieben wird, möchte ich diesen Code in einer React-Komponente verwenden und dabei so wenig wie möglich ändern. Er ist von Natur aus imperativ, im Gegensatz zur deklarativen Natur von React, und muss außerdem jede Minute aufgerufen werden. Wie können wir das tun?

Hier kommt Dan Abramov und sein erstaunlicher Blogbeitrag ins Spiel. Dan ist ein großartiger Autor, der komplexe Dinge klar erklären kann, und ich empfehle dringend, diesen Artikel zu lesen, insbesondere wenn Sie React Hooks besser verstehen möchten. Sie müssen nicht unbedingt alles darin verstehen – eine der Stärken von Hooks ist, dass sie auch ohne vollständiges Verständnis der internen Implementierung verwendet werden können. Wichtig ist zu wissen, wie man sie benutzt. So sieht das aus.

import { useEffect } from "react"
import useInterval from "./useInterval"

const delay = 60 * 1000

const 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)
}

Rufen Sie schließlich einfach useTimeFavicon() in Ihrer Root-Komponente auf, und Sie sind bereit! Möchten Sie es in Aktion sehen? Hier ist ein bereitgestelltes CodePen-Projekt, in dem Sie es sehen können, und hier ist der Projektcode selbst.

Zusammenfassung

Was wir hier getan haben, war, **drei Code-Stücke aus drei verschiedenen Quellen zusammenzufügen, um das gewünschte Ergebnis zu erzielen**. Alte Römer hätten gesagt Divide et Impera. (Ich bin Italiener, also bitte gestatten Sie mir ein wenig Latein!). Das bedeutet „Teile und herrsche“. Wenn Sie die Aufgabe als eine einzige Einheit betrachten, sind Sie vielleicht ein wenig besorgt: „Wie kann ich ein Favicon mit der aktuellen Zeit auf meiner React-Website anzeigen, das immer aktuell ist?“ Alle Details richtig hinzubekommen, ist nicht trivial.

Die gute Nachricht ist, dass Sie nicht immer alle Details gleichzeitig selbst angehen müssen: Es ist viel effektiver, das Problem in Teilprobleme zu zerlegen, und wenn eines davon bereits von anderen gelöst wurde, umso besser!

Klingt nach Webentwicklung, nicht wahr? Es ist nichts falsch daran, von anderen geschriebenen Code zu verwenden, solange es weise geschieht. Wie man so schön sagt, muss das Rad nicht neu erfunden werden, und was wir hier haben, ist eine schöne Verbesserung für jede Website – ob sie Benachrichtigungen, Zeitaktualisierungen oder was auch immer Sie sich vorstellen, anzeigt.