Es ist das Erste, wonach Ihre Augen suchen, wenn Sie zwischen Tabs wechseln.
Das ist eine Möglichkeit, zu erklären, was ein Favicon ist. Der Tab-Bereich ist weitaus wertvollerer Bildschirmplatz, als die meisten annehmen. Richtig gemacht, kann es neben einem Label mit Icon auch die perfekte Werbetafel sein, um darzustellen, was auf einer Webseite stattfindet oder was gerade passiert.

Favicons sind tatsächlich am nützlichsten, wenn Sie nicht auf einem Tab aktiv sind. Hier ist ein Beispiel
Stellen Sie sich vor, Sie sichern Fotos von Ihrem letzten Sommerurlaub auf einem Cloud-Dienst. Während sie hochgeladen werden, haben Sie einen neuen Tab geöffnet, um Details über die Orte zu sammeln, an denen Sie im Urlaub waren, um diese Fotos später zu annotieren. Das eine führte zum anderen, und jetzt schauen Sie Casey Neistat auf dem siebten Tab. Aber Sie können Ihren YouTube-Marathon nicht fortsetzen, ohne in angstvollen Intervallen auf die Cloud-Service-Seite zurückzublicken, um zu sehen, ob die Fotos hochgeladen wurden.
Genau in dieser Situation können wir kreativ werden! Was wäre, wenn wir die Pixel in diesem Favicon dynamisch ändern und den Upload-Fortschritt anzeigen könnten? Genau das werden wir in diesem Artikel tun.
In unterstützten Browsern können wir mit Hilfe von JavaScript, dem HTML <canvas>-Element und etwas jahrhundertealter Geometrie eine Lade-/Fortschrittsanimation als Favicon anzeigen.
Direkt einsteigen, wir beginnen mit dem einfachsten Teil: Hinzufügen der Icon- und Canvas-Elemente zum HTML.
<head>
<link rel="icon" type="image/png" href="" width=32px>
</head>
<body>
<canvas width=32 height=32></canvas>
</body>
In der praktischen Anwendung möchten Sie das <canvas>-Element auf der Seite ausblenden, und eine Möglichkeit, dies zu tun, ist das HTML-Attribut hidden.
<canvas hidden width=32 height=32></canvas>
Ich lasse das <canvas>-Element auf der Seite sichtbar, damit Sie sowohl das Favicon- als auch das Canvas-Bild zusammen animieren sehen können.
Sowohl das Favicon als auch das Canvas erhalten eine Standard-Favicon-Größe: 32 mal 32 Pixel.
Zu Demozwecken füge ich, um die Ladeanimation auszulösen, einen Button zur Seite hinzu, der die Animation beim Klicken startet. Dies kommt ebenfalls ins HTML
<button>Load</button>
Nun richten wir das JavaScript ein. Zuerst eine Prüfung auf Canvas-Unterstützung
onload = ()=> {
canvas = document.querySelector('canvas'),
context = canvas.getContext('2d');
if (!!context) {
/* if canvas is supported */
}
};
Als Nächstes fügen wir den Event-Handler für den Button-Klick hinzu, der die Animation im Canvas auslöst.
button = document.querySelector('button');
button.addEventListener('click', function() {
/* A variable to track the drawing intervals */
n = 0,
/* Interval speed for the animation */
loadingInterval = setInterval(drawLoader, 60);
});
drawLoader wird die Funktion sein, die mit Intervallen von jeweils 60 Millisekunden zeichnet. Bevor wir sie codieren, möchte ich den Stil der Linien des zu zeichnenden Quadrats definieren. Machen wir einen Farbverlauf.
/* Style of the lines of the square that'll be drawn */
let gradient = context.createLinearGradient(0, 0, 32, 32);
gradient.addColorStop(0, '#c7f0fe');
gradient.addColorStop(1, '#56d3c9');
context.strokeStyle = gradient;
context.lineWidth = 8;
In drawLoader zeichnen wir die Linien prozentual: Während der ersten 25 Intervalle wird die obere Linie schrittweise gezeichnet; im zweiten Viertel wird die rechte Linie gezeichnet; und so weiter.
Der Animationseffekt wird erzielt, indem das <canvas>-Element in jedem Intervall gelöscht wird, bevor die Linie(n) aus dem vorherigen Intervall etwas länger gezeichnet werden.
Während jedes Intervalls wird, nachdem das Zeichnen auf dem Canvas abgeschlossen ist, schnell in ein PNG-Bild umgewandelt und als Favicon zugewiesen.
function drawLoader() {
with(context) {
clearRect(0, 0, 32, 32);
beginPath();
/* Up to 25% */
if (n<=25){
/*
(0,0)-----(32,0)
*/
// code to draw the top line, incrementally
}
/* Between 25 to 50 percent */
else if(n>25 && n<=50){
/*
(0,0)-----(32,0)
|
|
(32,32)
*/
// code to draw the top and right lines.
}
/* Between 50 to 75 percent */
else if(n>50 && n<= 75){
/*
(0,0)-----(32,0)
|
|
(0,32)----(32,32)
*/
// code to draw the top, right and bottom lines.
}
/* Between 75 to 100 percent */
else if(n>75 && n<=100){
/*
(0,0)-----(32,0)
| |
| |
(0,32)----(32,32)
*/
// code to draw all four lines of the square.
}
stroke();
}
// Convert the Canvas drawing to PNG and assign it to the favicon
favicon.href = canvas.toDataURL('image/png');
/* When finished drawing */
if (n === 100) {
clearInterval(loadingInterval);
return;
}
// Increment the variable used to keep track of the drawing intervals
n++;
}
Nun zur Mathematik und zum Code zum Zeichnen der Linien.
So zeichnen wir die obere Linie in jedem Intervall während der ersten 25 Intervalle schrittweise
n = current interval,
x = x-coordinate of the line’s end point at a given interval.
(y-coordinate of the end point is 0 and start point of the line is 0,0)
Nach Abschluss aller 25 Intervalle ist der Wert von x 32 (die Größe des Favicons und des Canvas).
Also…
x/n = 32/25
x = (32/25) * n
Der Code, um diese Mathematik anzuwenden und die Linie zu zeichnen, lautet
moveTo(0, 0); lineTo((32/25)*n, 0);
Für die nächsten 25 Intervalle (rechte Linie) zielen wir ähnlich auf die y-Koordinate ab.
moveTo(0, 0); lineTo(32, 0);
moveTo(32, 0); lineTo(32, (32/25)*(n-25));
Und hier ist die Anweisung zum Zeichnen aller vier Linien mit dem Rest des Codes.
function drawLoader() {
with(context) {
clearRect(0, 0, 32, 32);
beginPath();
/* Up to 25% of the time assigned to draw */
if (n<=25){
/*
(0,0)-----(32,0)
*/
moveTo(0, 0); lineTo((32/25)*n, 0);
}
/* Between 25 to 50 percent */
else if(n>25 && n<=50){
/*
(0,0)-----(32,0)
|
|
(32,32)
*/
moveTo(0, 0); lineTo(32, 0);
moveTo(32, 0); lineTo(32, (32/25)*(n-25));
}
/* Between 50 to 75 percent */
else if(n>50 && n<= 75){
/*
(0,0)-----(32,0)
|
|
(0,32)----(32,32)
*/
moveTo(0, 0); lineTo(32, 0);
moveTo(32, 0); lineTo(32, 32);
moveTo(32, 32); lineTo(-((32/25)*(n-75)), 32);
}
/* Between 75 to 100 percent */
else if(n>75 && n<=100){
/*
(0,0)-----(32,0)
| |
| |
(0,32)----(32,32)
*/
moveTo(0, 0); lineTo(32, 0);
moveTo(32, 0); lineTo(32, 32);
moveTo(32, 32); lineTo(0, 32);
moveTo(0, 32); lineTo(0, -((32/25)*(n-100)));
}
stroke();
}
// Convert the Canvas drawing to PNG and assign it to the favicon
favicon.href = canvas.toDataURL('image/png');
/* When finished drawing */
if (n === 100) {
clearInterval(loadingInterval);
return;
}
// Increment the variable used to keep track of drawing intervals
n++;
}
Das war's! Sie können den Demo-Code von diesem GitHub-Repo sehen und herunterladen. Bonus: Wenn Sie nach einem kreisförmigen Lader suchen, schauen Sie sich dieses Repo an.
Sie können jede beliebige Form verwenden, und wenn Sie das fill-Attribut bei der Canvas-Zeichnung verwenden, erhalten Sie einen anderen Effekt.
Nur neugierig, warum die
if(!!context)-Prüfung anstelle von nurif(context)? Konvertiert!!nicht einfach einen Wahrheitwert intrue, was genau dasselbe ist, wasif(condition)prüft? Gibt es einen Fall, den ich übersehe, den dies besser behandelt?+1
Hab mich dasselbe gefragt, als ich den Anwendungsfall gesehen habe!
Das liegt daran, dass
contextkein boolescher Wert ist, sodass man nicht einfachif(context)sagen kann; das ist so, als würde manif(3)sagen, was nicht viel Sinn ergibt. (Auch wenn ich nicht weiß, wie JS diese Fälle gerade behandelt)Um einen booleschen Wert zu erhalten, wird
contextzuerst mit einem!negiert, was immer ein Boolesches zurückgibt. Da dieser Boolesche aber falsch herum ist, negieren wir ihn mit einem weiteren!.Wenn
contextalsonullwäre, würde!contexttruezurückgeben, also machen wir!!context(Sie können es als!(!context)betrachten), um das zu bekommen, was wir brauchen, nämlichfalse.Und wenn es existiert, wäre
!contextfalsch, also machen wir wieder!!context, umtrueals Ergebnis zu erhalten.Scott, du hast Recht :) siehe https://developer.mozilla.org/en-US/docs/Glossary/Truthy
Favicon kann auch als eine Art scrollender Text-Messenger verwendet werden: https://kawalekkodu.pl/wiadomosc-z-czapy-czyli-o-nietypowym-wykorzystaniu-favicon
PS. Denken Sie daran, dass setInterval/setTimeout in inaktiven Tabs langsamer wird und stoppt.
Die Zeile, die dem Favicon zugewiesen wird, scheint bei mir nicht zu funktionieren. Die Ausführung von „favicon.href = …“ gibt den Konsolenfehler „favicon is not defined“ aus. Vorschläge?
Konrad, untersuche den Code im GitHub-Repo, der am Ende des Artikels verlinkt ist. Die Datei script.js zeigt die erforderliche Deklaration: favicon = document.querySelector(‘link[rel*=”icon”]’);
Preethi, vielleicht könnte die Bearbeitung des Artikels, um diese Codezeile aufzunehmen, Verwirrung beseitigen.
In Chrome beobachtet, dass die Animation schnell ist, wenn der Tab aktiv ist, und langsam, wenn der Tab nicht aktiv ist. Eine Performance-Optimierung, nehme ich an.
Das ist keine Optimierung. Das ist, was ich in meinem obigen Kommentar erwähnt habe. Schauen Sie sich das an.
Wirklich coole Idee!
Gibt es jedoch eine Alternative zu
setInterval, da es in inaktiven Tabs extrem langsam wird?Ja, bitte schauen Sie sich meinen Kommentar oben an. Dort gibt es einen Link zu meinem Blog, aber in polnischer Sprache (nutzen Sie Google Translator), und dort gibt es auch eine Lösung.
Alle zeitbasierten APIs werden langsamer, wenn der Tab inaktiv ist. Dies ist eine bewusste Entscheidung der Browser, um die Akkulaufzeit und andere Computerressourcen zu schonen. In einem realen Szenario würden Sie wahrscheinlich Live-Fortschrittsdaten verwenden, sodass die Animation zwar ruckelig sein kann, aber nicht „langsam“ wird, nur weil der Tab inaktiv ist. Eine Alternative, wenn es Ihnen nur um die Animation geht und nicht um die Anzeige tatsächlicher Daten, ist die Erkennung der tatsächlich zwischen den einzelnen Frames verstrichenen Zeit und das Zeichnen Ihres Canvas als Prozentsatz der Zeit anstatt des einfachen Inkrements um 1 pro Frame. Die Bildrate wird zwar immer noch langsamer, wenn der Tab inaktiv ist, aber die Animation hat trotzdem eine konsistente Dauer.
Das ist brillant! Der Demo-Link und der GitHub-Code machen es wirklich klar (der Code im Artikel fehlen einige wichtige Teile)
Bis jetzt habe ich nur Twitters Favicon für Benachrichtigungen gesehen (sogar in meiner Lesezeichenleiste). Das ist ein schöner Trick, den ich gerne verwenden würde