Viewport
Example where an element color changes based on viewport scroll position.
import { Simulator, LinearScaledVector, Kinetics, TriggerGateReducer, ClockComposer,} from "@yyyoichi/chrono-kinesis";import { DomVisualizer, ElementPhysics, IntersectionTriggerClock,} from "@yyyoichi/chrono-kinesis/dom";const simulation = new Simulator({ fixedStepSec: 1 / 20 });
// 要素が順スクロールでrootの50%に達したらOpacityを1にして、// 逆スクロールで10%に達したら0にする例です。
const rootEl = document.getElementById("viewport-root")!;const boxEl = document.getElementById("viewport-target-box")!;const onTriggerEl = document.getElementById("viewport-target-on-trigger")!;const offTriggerEl = document.getElementById("viewport-target-off-trigger")!;
// 順スクロールで50%に到達したらトリガーします。const onClock = new IntersectionTriggerClock(onTriggerEl, { direction: "forward", root: rootEl,});// 逆スクロールで10%に到達したらトリガーします。const offClock = new IntersectionTriggerClock(offTriggerEl, { direction: "backward", root: rootEl,});
const opacity = new LinearScaledVector( // onClockがトリガーされたら1、offClockがトリガーされたら0にします new TriggerGateReducer(onClock, offClock), { min: 100, max: 1000 },);const vis = new DomVisualizer() .noTranslate() .opacity((st) => `${Math.round(st.absolute[0]) / 1000}`);simulation.add({ clock: new ClockComposer(onClock, offClock), target: opacity, kinetics: new Kinetics([0]), physics: new ElementPhysics(boxEl, vis),});simulation.run();<div id="viewport-root" {...props} style={style + "overflow: auto; container-type: size;"}> <div style="height: 300px; width:100%"> <div id="viewport-target-box" style="position: relative; opacity: 0.1; height: 200px; width:50%; margin: 190px auto; background-color: cadetblue;" > <div id="viewport-target-on-trigger"></div> <div id="viewport-target-off-trigger"></div> </div> </div></div><style> /* 画面サイズ(viewpor-root)の相対サイズ分だけ、viewport-target-boxから離れた位置に配置します。 */ #viewport-target-on-trigger { width: 1px; height: 1px; position: absolute; top: 50cqh; margin: 0; } #viewport-target-off-trigger { width: 1px; height: 1px; position: absolute; top: 10cqh; margin: 0; }</style>---type Props = Omit<astroHTML.JSX.HtmlHTMLAttributes, "id">;const { style, ...props } = Astro.props;---
<div id="viewport-root" {...props} style={style + "overflow: auto; container-type: size;"}> <div style="height: 300px; width:100%"> <div id="viewport-target-box" style="position: relative; opacity: 0.1; height: 200px; width:50%; margin: 190px auto; background-color: cadetblue;" > <div id="viewport-target-on-trigger"></div> <div id="viewport-target-off-trigger"></div> </div> </div></div><style> /* 画面サイズ(viewpor-root)の相対サイズ分だけ、viewport-target-boxから離れた位置に配置します。 */ #viewport-target-on-trigger { width: 1px; height: 1px; position: absolute; top: 50cqh; margin: 0; } #viewport-target-off-trigger { width: 1px; height: 1px; position: absolute; top: 10cqh; margin: 0; }</style>
<script> import { Simulator, LinearScaledVector, Kinetics, TriggerGateReducer, ClockComposer, } from "@yyyoichi/chrono-kinesis"; import { DomVisualizer, ElementPhysics, IntersectionTriggerClock, } from "@yyyoichi/chrono-kinesis/dom"; const simulation = new Simulator({ fixedStepSec: 1 / 20 });
// 要素が順スクロールでrootの50%に達したらOpacityを1にして、 // 逆スクロールで10%に達したら0にする例です。
const rootEl = document.getElementById("viewport-root")!; const boxEl = document.getElementById("viewport-target-box")!; const onTriggerEl = document.getElementById("viewport-target-on-trigger")!; const offTriggerEl = document.getElementById("viewport-target-off-trigger")!;
// 順スクロールで50%に到達したらトリガーします。 const onClock = new IntersectionTriggerClock(onTriggerEl, { direction: "forward", root: rootEl, }); // 逆スクロールで10%に到達したらトリガーします。 const offClock = new IntersectionTriggerClock(offTriggerEl, { direction: "backward", root: rootEl, });
const opacity = new LinearScaledVector( // onClockがトリガーされたら1、offClockがトリガーされたら0にします new TriggerGateReducer(onClock, offClock), { min: 100, max: 1000 }, ); const vis = new DomVisualizer() .noTranslate() .opacity((st) => `${Math.round(st.absolute[0]) / 1000}`); simulation.add({ clock: new ClockComposer(onClock, offClock), target: opacity, kinetics: new Kinetics([0]), physics: new ElementPhysics(boxEl, vis), }); simulation.run();</script>