スクロールで色相を変化

6種類の色相でのプレビューを並べてみたもの

秒数ごとに変えていた背景色を、スクロールするとランダムに変わるようにした。雑記ページスタイル・ガイドで、思う存分試せる。背景色の明るさは変わらないので、そんなに目に負担はかからないと想像しているが、本当のところはわからない。

スクロールに応じて変えるので、素直にやるならonscrollイベントを使うところだが、間引いても重いことがあるだろうし、Intersection Observerを利用した。トリガーをどうしようかと悩んだが、p要素ほど出てこず、たまに出てくる要素をすべて観察させると、どのページでもいい感じになった。

  • hr要素
  • pre要素
  • blockquote要素
  • li要素直下ではないol要素
  • li要素直下ではないul要素
  • figure要素
  • table要素
  • h2 + .metaline

対象はこれらの要素だ。見出しやセクショニング要素でも良さそうだが、それだと雑記記事であまり変わらなくなってしまうので、これら挿入される何かを対象にした。つまり、このリストが画面外に消えると、色相が変わる。olul要素はネストを考慮したセレクターになっている。また最後の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が複数あることが多いが、全部に反応する必要はないので最初だけを見ている。また、消えた時に色を変えるよう、isIntersectingfalseの時に色相を変更している。消えた時にすると、スクロールしすぎて戻るというありがちな行動パターンと、うまくなじむんじゃないかと考えた。

updateHue()模造紙風の背景色のコードを、少しだけ手直しし、秒数ではなくランダムにした。style属性にカスタム・プロパティーで色相(と明度)が仕込まれるところは同じだ。そのため、背景色他への反映はCSSがやってくれるので、呼ぶだけで済む。

あとは観察対象へ登録するだけだ。observe()はNodeListを受け取れないので、for..ofでばらまいた。forEach()を欲しがっていた割には、for...ofを好んで使うようになってしまった。breakしたい。