秒数ごとに変えていた背景色を、スクロールするとランダムに変わるようにした。雑記ページやスタイル・ガイドで、思う存分試せる。背景色の明るさは変わらないので、そんなに目に負担はかからないと想像しているが、本当のところはわからない。
スクロールに応じて変えるので、素直にやるならonscroll
イベントを使うところだが、間引いても重いことがあるだろうし、Intersection Observerを利用した。トリガーをどうしようかと悩んだが、p
要素ほど出てこず、たまに出てくる要素をすべて観察させると、どのページでもいい感じになった。
hr
要素pre
要素blockquote
要素li
要素直下ではないol
要素li
要素直下ではないul
要素figure
要素table
要素h2 + .metaline
対象はこれらの要素だ。見出しやセクショニング要素でも良さそうだが、それだと雑記記事であまり変わらなくなってしまうので、これら挿入される何かを対象にした。つまり、このリストが画面外に消えると、色相が変わる。ol
とul
要素はネストを考慮したセレクターになっている。また最後のh2 + .metaline
は、トップページや特集ページのため、特別に追加した。
const updateHueOnScroll = () => {
const updateOnHide = (entries) => {
if (entries[0].isIntersecting) {
return;
}
/* global updateHue */
updateHue();
};
const elements = document.querySelectorAll("hr, pre, blockquote, :not(li) > ol, :not(li) > ul, figure, table, h2 + .metaline");
const observer = new IntersectionObserver(updateOnHide);
for (const element of elements) {
observer.observe(element);
}
};
色々観察している関係上、entries
が複数あることが多いが、全部に反応する必要はないので最初だけを見ている。また、消えた時に色を変えるよう、isIntersecting
がfalse
の時に色相を変更している。消えた時にすると、スクロールしすぎて戻るというありがちな行動パターンと、うまくなじむんじゃないかと考えた。
updateHue()
は模造紙風の背景色のコードを、少しだけ手直しし、秒数ではなくランダムにした。style
属性にカスタム・プロパティーで色相(と明度)が仕込まれるところは同じだ。そのため、背景色他への反映はCSSがやってくれるので、呼ぶだけで済む。
あとは観察対象へ登録するだけだ。observe()
はNodeListを受け取れないので、for..of
でばらまいた。forEach()
を欲しがっていた割には、for...of
を好んで使うようになってしまった。break
したい。