Ich habe eine Pause von der Arbeit gemacht und einige kleine, persönliche Projekte (Spielzeuge) begonnen. Eines dieser kleinen Projekte ist potato.horse, wo ich all meine Kritzeleien, visuellen Kurzgeschichten und Witze aufbewahre. Schau es dir an!
Allerdings handelt dieser Beitrag nicht von meiner Auszeit, anderen Experimenten oder der Website selbst. Die Leute scheinen eine bestimmte Technik zu mögen, die ich im Design verwendet habe, insbesondere den Hintergrundeffekt, der zwischen Farben wechselt, wenn der Benutzer durch die Inhalte blättert.
Einige haben mich gefragt, wie dieser Effekt implementiert wurde (bis hin zum Lesen des minifizierten Codes, was sehr schmeichelhaft ist).
Hier ist also eine kurze Zusammenfassung, gefolgt von einigen Erklärungen.
export const useRainbowBg = () =>
useEffect(() => {
const cb = () => {
const viewportHeight = window.innerHeight
const contentHeight = document.body.getBoundingClientRect().height
const viewportsPerRotation = Math.min(
3,
contentHeight / viewportHeight
)
const from = 51
const progress =
window.scrollY / (viewportHeight * viewportsPerRotation)
const h = (from + 360 * progress) % 360
document.body.style.backgroundColor = `hsl(${h}deg, 100%, 50%)`
}
window.addEventListener('scroll', cb, { passive: true })
return () => window.removeEventListener('scroll', cb)
})
Kurz gesagt, ich ordne die Scrollposition dem Farbton in der HSL-Farbnotation zu. Lassen Sie uns das aufschlüsseln.
Farbmodelle
Es gibt viele Möglichkeiten, Farben in CSS zu beschreiben, wobei RGB (links) und HSL (rechts) die beiden gebräuchlichsten sind.
RGB ist eine additive Farbpalette. Das bedeutet, dass die Mischung von 100% Rot, Grün und Blau Weiß ergibt, die Mischung von 100% Rot und 100% Grün, aber 0% Blau, Gelb ergibt und so weiter. Dies unterscheidet sich von, sagen wir, der Verwendung von Ölfarben oder dem CMYK-Farbmodell, wo der resultierende Ton Schwarz(-lich) wäre1.
Wir sind diesen Ansatz gewohnt, weil er sich leicht im Code beschreiben lässt, aber Farben in Bezug auf Farbton, Sättigung und Luminanz anzugeben, erscheint natürlicher, besonders wenn Sie einen Design-Hintergrund haben oder ... wissen Sie, ein Mensch sind, der eine menschliche Sprache verwendet.
Als Entwickler haben wir uns an RGB gewöhnt, aber in gesprochener Sprache wäre die Verwendung von RGB unnatürlich und verwirrend. Façade wäre in RGB sehr schwer zu bedienen.
Auf der anderen Seite ist HSL oft viel intuitiver zu handhaben. Wenn ich zum Beispiel eine Farbe etwas kälter machen möchte, kann ich einfach den Farbtonregler ein wenig in Richtung Blau verschieben und sollte dem näher kommen, was ich mir vorstelle. Mit RGB, wenn wir die Farbe kälter erscheinen lassen, indem wir mehr Blau einbeziehen, wird der resultierende Ton etwas heller, da die blaue Komponente zur Gesamtlichtstärke beiträgt. Das bedeutet, dass Sie die Rot- und Grünwerte senken müssten, um dies auszugleichen.
Um zu sehen, wie das in der Praxis funktioniert, maximieren Sie die blaue Farbe im folgenden Beispiel.
Das Erste, was auffällt, ist, dass alle Töne ins Blaue verschoben sind und die Gesamthelligkeit des Bildes zugenommen hat. Im Falle des Effekts, über den wir sprechen, wäre das unerwünscht.
Versuchen wir nun dasselbe mit dem HSL-Farbrad. Ziehen Sie den Regler nach links, um **ca. 90 Grad**
In diesem Szenario verwandelt die Verwendung von HSL nicht nur Susan in einen Vampir, sondern behält auch ein ähnliches2 Helligkeitsniveau bei. Und genau das suche ich.
Was ich damit meine
Wie funktioniert das? Kurz gesagt, ich ordne die Scrollposition dem Farbton in der HSL-Farbnotation zu. Rafal, 2 Tage zuvor
...bedeutet, dass jedes Mal, wenn wir ein Scroll-Ereignis erkennen, ich versuche, es einem Winkel auf dem Farbkreis zuzuordnen.
Ich wollte nicht mit Rot beginnen, da es mich hungrig machen würde und das Basisschwarz-Gelb besser zum Design passt, also habe ich eine kleine Anfangsverschiebung angewendet – daher const from = 51 als Anfangsoffset gesetzt.
Und was die grundlegende Implementierung betrifft, das war's!
Nun gibt es drei weitere Verbesserungsbereiche.
useRainbow Leistung
Wir lösen bei jedem Scrollen eine Neudarstellung aus, daher war ich etwas besorgt, dass ältere Mobilgeräte oder sogar einige High-End-Laptops, die an 4k-Bildschirme angeschlossen sind, keine stabilen 60fps erreichen könnten. Aber ich bin bisher mit den Ergebnissen zufrieden. Die Verwendung von passiven Ereignis-Listenern hat einen kleinen Leistungsschub gebracht, besonders auf Mobilgeräten.
Wenn ich feststelle, dass die Leistung ein Problem darstellt, insbesondere bei mehr Inhalt weiter unten, werde ich mich wahrscheinlich darauf konzentrieren,
- den unnötigen Aufruf von
getBoundingClientRectbei jedem Scroll-Handler-Aufruf zu entfernen und - Hintergrundfarbänderungen mithilfe von
requestAnimationFramezu verzögern oder zu drosseln.
Ich erwarte, dass die erste Verbesserung einen gewissen Einfluss hat, aber die Vorteile der zweiten sollten vernachlässigbar sein.
Messen, bevor optimiert wird. Obsession mit der Leistung macht nur Sinn, wenn Probleme spürbar werden, sei es durch einen Rückgang der Framerate oder eine Auswirkung auf den Akku. Ihr iPhone Pro hat mehr Rechenleistung als viele Low-End-Laptops, daher ist es eine gute Idee, auch auf diesen Geräten zu testen. Es ist gut, ein mieses altes Android-Handy genau zu diesem Zweck zu haben, wenn Sie ein paar Euro übrig haben.
Wahrnehmungsuniforme Farbräume
Sie haben vielleicht bemerkt, dass in den vorherigen Abbildungen einige voll gesättigte Farben dunkler erschienen als andere. Das liegt daran, dass die Farbräume, die wir normalerweise beim Programmieren verwenden, nicht widerspiegeln, wie das menschliche Auge funktioniert. Ich überlasse die ausführliche Erklärung jemandem, der viel erfahrener ist als ich, aber es reicht zu sagen (starke Vereinfachung!), dass im Allgemeinen die gleiche Menge Rot/Grün/Gelb heller erscheint als Blau. Das bedeutet, dass in einigen Fällen der Text auf der Seite schwerer zu lesen sein wird.
Vorerst ist das kein Problem, da ich diese Sache gerade erst online gestellt habe und die Titel nur eine sekundäre Funktion haben. Aber es gibt eine Lösung für das Problem, und sie ist nicht übermäßig kompliziert: Verwenden Sie einen wahrnehmungsuniformen Farbraum. Es gibt eine Reihe von Bibliotheken, die dies direkt anbieten, sowohl in JavaScript/TypeScript als auch in CSS/Sass/<Wählen Sie hier Ihren CSS-Geschmack>. hsluv scheint ein guter Ausgangspunkt zu sein.
Barrierefreiheit
Beachten Sie, dass ich mich auf den visuellen Effekt selbst konzentrieren werde und nicht den Rest der Website bespreche (z. B. Alt-Tags, Dokumentenstruktur usw.). Ich möchte mich auf Kontrast, Farbenblindheit und Personen konzentrieren, die auf prefers-reduced-motion angewiesen sind. Die Website ist ein lebendiges Dokument; es gibt immer viel zu verbessern. Zum Beispiel kann der Kontrast an einigen nicht kritischen Stellen ein Problem darstellen. Ich freue mich über Feedback und Implementierung: melden Sie sich bei mir!.
Farbenblindheit
Ich wollte sicherstellen, dass der Effekt die Website für farbenblinde Menschen nicht komplett unbrauchbar macht. Daher konzentrierte ich mich auf die häufigsten Typen: Deuteranomalie und Protanomalie (Rot-Grün-Farbenblindheit), führte aber auch breitere Tests durch. Ich verwendete Photoshop und Colorblindly (Chrome-Erweiterung) für einige rudimentäre Prüfungen.
prefers-reduced-motion
Die CSS-Medienfunktion
—MDNprefers-reduced-motionwird verwendet, um zu erkennen, ob der Benutzer angefordert hat, dass das System die Menge an nicht wesentlicher Bewegung minimiert.
Diese Website enthält nicht viele Animationen (abgesehen von den Little Sausage Angels, die Sie sehen, wenn Sie auf "Teilen" klicken), aber ich habe mich gefragt, ob Menschen, die auf prefers-reduced-motion angewiesen sind, möchten, dass die Hintergrundfarbe konstant bleibt.
Die kurze Antwort lautet: Ich weiß es nicht. Meine Intuition ist, dass rotierende Farben nicht wirklich als Bewegung gelten, aber meine Erfahrung und mein Verständnis des Problems sind, gelinde gesagt, begrenzt. In solchen Situationen verlasse ich mich lieber auf Benutzerforschung als auf Vermutungen.
Glücklicherweise hatte die Website ihre fünf Minuten Ruhm auf Reddit, was sich als gute Gelegenheit erwies, Feedback zu sammeln. Keiner der Benutzer hat bisher ein Problem mit dem Hintergrundeffekt angesprochen. Ich habe auch das Glück, eine Reihe von Barrierefreiheitsspezialisten zu kennen, wie z. B. Sandrina Pereira. Ihr Vorschlag war, dass (a) Hintergrundanimationen definitiv als Bewegung gelten und (b) der Effekt vielleicht natürlich wirkt, weil er ein direktes Ergebnis einer Benutzerinteraktion ist.
Zusammenfassung
Das Geocities-Web der späten 90er Jahre wirkte verspielt und seltsam. Es machte Spaß auf eine ungehemmte, etwas weniger performative Weise. Ich wollte diesen Look and Feel in die Website einbringen. Aber trotzdem wollte ich es nicht esoterisch machen, bis zu dem Punkt, an dem Sie Ihr Hipster-Level auf 9000 erhöhen und es ausschließlich über Netscape 7 durchsuchen müssten. All das, während Sie das neue Nirvana Unplugged Album hören.
Ich wollte immer noch eine gute UX auf Mobilgeräten und Desktops und etwas Platz für Ostereier (etwas, das man nicht tun kann, wenn man in der seltsamen und missbräuchlichen Beziehung mit sozialen Medien lebt, an die wir uns so gewöhnt haben).
Als Kind hatte ich sechs Websites erstellt, bevor ich überhaupt zum ersten Mal Zugang zum Internet hatte. Jetzt, nachdem ich drei Jahre lang ausgebrannt war und sogar über einen Jobwechsel nachdachte, war es das erste Mal, dass ich ernsthaft Spaß am Programmieren hatte. Ich hatte vergessen, wie viel Spaß das machte!
Jetzt geh raus, streichel deine Katze und mach Sachen!
PS. Schauen Sie sich Cameron's World an.
PPS. Der Code für interaktive Diagramme ist auf GitHub zu finden.
Sehr clever, danke fürs Teilen. Welchen Ansatz würden Sie wählen, wenn Sie einen bestimmten Farbsatz verwenden möchten?
Freut mich, dass es Ihnen gefallen hat!
Dies hängt davon ab, welche Art von Farben/Farbpaletten Sie erhalten möchten, aber der einfachste Ansatz wäre, die Scrollposition einem Gradientenwert zuzuordnen.
Nehmen wir an, die Gradientenschritte (alle Ihre Übergangsfarben) sind in einem Array definiert. Sie sollten so etwas tun können
In dem Sinne, dass wir in meinem Beispiel über die 360 möglichen Farbwerte im HSL-Farbrad iterieren.
Wenn Sie andere Einschränkungen haben, können Sie möglicherweise eine einfachere Lösung finden (z. B. eine Funktion anstelle eines Arrays verwenden, mit Mischmodi herumspielen...).
Cool! Das ist sehr interessant für mich, da ich ein reines Color-Picker-Paket erstellt habe, das ich auf eine sehr geringe Dateigröße und eine minimale Benutzererfahrung ausgelegt habe.
https://www.npmjs.com/package/@yaireo/color-picker
Dieser Artikel hat mir einige gute Ideen gegeben.