作成サンプル
css custom variable で数値を渡すことができます。
css には calc() という 数値を計算する関数があります。
css には min() max() clamp() という値の範囲を制限する為の関数があります。
つまり、こういうことができます。
See the Pen wheel event example by juner clarinet (@juner) on CodePen.
※ code pen 領域でマウスのホイールや タッチパッドの スクロールジェスチャーを試してみてください。
ソース
<input id=scale type="number" min=1 value=200 placeholder="--base-scale" />
<ul id="target">
<template id="template">
<li>
<span class="property"><span class="title">deltaMode:</span><span class="delta-mode"></span></span>,
<span class="property"><span class="title">deltaX:</span><span class="delta-x"></span></span>,
<span class="property"><span class="title">deltaY:</span><span class="delta-y"></span></span>,
<span class="property"><span class="title">deltaZ:</span><span class="delta-z"></span></span>,
<span class="property"><span class="title">wheelDelta:</span><span class="wheel-delta"></span></span>,
<span class="property"><span class="title">wheelDeltaX:</span><span class="wheel-delta-x"></span></span>,
<span class="property"><span class="title">wheelDeltaY:</span><span class="wheel-delta-y"></span></span>
</li>
</template>
</ul>
<script type="module">
{
// #region base scale
scale.valueAsNumber = Number(
getComputedStyle(document.body).getPropertyValue("--base-scale"),
);
scale.addEventListener("input", updateBaseScale);
updateBaseScale();
function updateBaseScale() {
const scaleNum = scale.valueAsNumber;
const body = document.body;
if (isNaN(scaleNum)) body.style.removeProperty("--base-scale");
else body.style.setProperty("--base-scale", scaleNum);
}
// #endregion
// #region wheel event
document
.querySelector(":root")
.addEventListener("wheel", wheel, { passive: false });
function wheel(e) {
e.preventDefault();
e.stopPropagation();
(async ({
deltaMode,
deltaX,
deltaY,
deltaZ,
wheelDelta,
wheelDeltaX,
wheelDeltaY,
}) => {
await timeout();
const $temp = template.content.cloneNode(true);
const $li = $temp.querySelector("li");
// #region deltaMode
(($e, deltaMode) => {
$e.innerText = ((deltaMode) => {
if (WheelEvent.DOM_DELTA_PIXEL === deltaMode)
return `DOM_DELTA_PIXEL(${deltaMode})`;
if (WheelEvent.DOM_DELTA_LINE === deltaMode)
return `DOM_DELTA_LINE(${deltaMode})`;
if (WheelEvent.DOM_DELTA_PAGE === deltaMode)
return `DOM_DELTA_PAGE(${deltaMode})`;
return `${deltaMode}`;
})(deltaMode);
$e.classList.add(`delta-mode-${deltaMode}`);
})($li.querySelector(".delta-mode"), deltaMode);
// #endregion
// #region other property
[
[$li.querySelector(".delta-x"), deltaX],
[$li.querySelector(".delta-y"), deltaY],
[$li.querySelector(".delta-z"), deltaZ],
[$li.querySelector(".wheel-delta"), wheelDelta],
[$li.querySelector(".wheel-delta-x"), wheelDeltaX],
[$li.querySelector(".wheel-delta-y"), wheelDeltaY],
].forEach((v) => {
const [$e, value] = v;
$e.innerText = value;
$e.style.setProperty("--value", value);
});
// #endregion
target.insertAdjacentElement("afterbegin", $li);
const removeTarget = target.querySelectorAll(":nth-child(1n+100 of li)");
for (const rt of [...removeTarget]) rt.remove();
})(e);
}
// #endregion
function timeout(milliseconds) {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
}
</script>
<style>
:root {
/** delta の 色変換用スケール */
--base-scale: 500;
height: 100vh;
width: 100vw;
overflow: hidden;
display: flex;
flex-flow: column nowrap;
container-type: size;
body {
display: contents;
ul {
flex: 1 1 auto;
display: flex;
flex-flow: column nowrap;
padding: 0;
margin: 0;
overflow: hidden;
gap: 2px;
li {
.delta-mode {
color: var(--delta-mode-color, currentcolor);
background-color: var(--delta-mode-background-color, transparent);
&.delta-mode-0 {
--delta-mode-color: white;
--delta-mode-background-color: green;
}
&.delta-mode-1 {
--delta-mode-background-color: yellow;
}
&.delta-mode-2 {
--delta-mode-color: white;
--delta-mode-background-color: blue;
}
}
.property {
display: inline flow-root;
}
.title {
font-size: 0.5em;
}
.delta-x,
.delta-y,
.delta-z,
.wheel-delta,
.wheel-delta-x,
.wheel-delta-y {
background-color: oklab(
100% 0 clamp(-0.5, calc(var(--value) / var(--base-scale)), 0.5)
);
}
}
}
& > ul {
pointer-events: none;
}
}
}
</style>
ポイント
色の調整方法
色変換については次の様なコードで実現しています。
.delta-x,
.delta-y,
.delta-z,
.wheel-delta,
.wheel-delta-x,
.wheel-delta-y {
background-color: oklab(
100% 0 clamp(-0.5, calc(var(--value) / var(--base-scale)), 0.5)
);
}
--base-scale
は :root で定義しており、 動作見た感じ 200 に設定してあります。そのうち js で変更できると面白いかもしれません。
--value
は js から設定している各 delta の値です。
oklab() は 色 関数の一つで今回の L a b の b ……つまり 青と黄色の色合いの値を 算出しています。
値の範囲が外に出てしまうと不都合の場合は clamp() 関数で 最大と最小を範囲に収めるとよいです。
要素数の制限
要素数の制限は次の様に実装してあります。
const removeTarget = target.querySelectorAll(":nth-child(1n+100 of li)");
for (const rt of [...removeTarget]) rt.remove();
:nth-child(1n+100 of li)
により ul#target
内にある 100 件目以降の li 要素を削除対象として逐次削除を行っております。
以上。