NgtsScrollControls
import { ChangeDetectionStrategy, Component } from '@angular/core';import { SobaWrapper } from '@soba/wrapper.ts';import { NgtCanvas, provideNgtRenderer } from 'angular-three/dom';import { SceneGraph } from './scene-graph';
@Component({ selector: 'app-scroll-controls', template: ` <ngt-canvas [camera]="{ position: [0, 0, 5], fov: 50 }"> <app-soba-wrapper *canvasContent [controls]="null" [grid]="false"> <app-scene-graph /> </app-soba-wrapper> </ngt-canvas> `, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'scroll-controls-demo relative block h-full' }, imports: [NgtCanvas, SobaWrapper, SceneGraph],})export default class ScrollControls { static clientProviders = [provideNgtRenderer()];}import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, signal } from '@angular/core';import { injectStore, NgtArgs } from 'angular-three';import { NgtsCanvasScrollContent, NgtsScrollControls } from 'angular-three-soba/controls';
@Component({ selector: 'app-scroll-content', template: ` <ngt-group canvasScrollContent> <!-- Page 1 --> <ngt-mesh [position]="[0, 0, 0]"> <ngt-box-geometry *args="[2, 2, 2]" /> <ngt-mesh-standard-material color="#ff6b6b" /> </ngt-mesh>
<!-- Page 2 --> <ngt-mesh [position]="[0, -viewportHeight, 0]"> <ngt-sphere-geometry *args="[1.2, 32, 32]" /> <ngt-mesh-standard-material color="#4ecdc4" /> </ngt-mesh>
<!-- Page 3 --> <ngt-mesh [position]="[0, -viewportHeight * 2, 0]"> <ngt-torus-knot-geometry *args="[0.8, 0.3, 128, 32]" /> <ngt-mesh-standard-material color="#a29bfe" /> </ngt-mesh> </ngt-group> `, schemas: [CUSTOM_ELEMENTS_SCHEMA], changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgtArgs, NgtsCanvasScrollContent],})export class ScrollContent { private store = injectStore();
viewportHeight = this.store.viewport().height;}
@Component({ selector: 'app-scene-graph', template: ` <ngts-scroll-controls [(progress)]="progress" [options]="{ pages: 3, damping: 0.15 }"> <app-scroll-content /> </ngts-scroll-controls>
<ngt-ambient-light [intensity]="0.5" /> <ngt-point-light [position]="[10, 10, 10]" [intensity]="Math.PI" /> `, schemas: [CUSTOM_ELEMENTS_SCHEMA], changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgtArgs, NgtsScrollControls, ScrollContent],})export class SceneGraph { protected readonly Math = Math; progress = signal(0);}NgtsScrollControls enables scroll-based interactions within a Three.js canvas. It creates a scrollable container that can be used to control animations and camera movements based on scroll position.
Usage
import { NgtsScrollControls, NgtsCanvasScrollContent } from 'angular-three-soba/controls';<ngts-scroll-controls [options]="{ pages: 3, damping: 0.1 }"> <ngt-group canvasScrollContent> <!-- 3D content that moves with scroll --> </ngt-group></ngts-scroll-controls>Companion Directives
NgtsCanvasScrollContent
A directive that automatically positions a group based on scroll progress. Apply to an ngt-group element.
<ngt-group canvasScrollContent> <!-- 3D content that moves with scroll --></ngt-group>NgtsHTMLScrollContent
A directive that automatically transforms an HTML element based on scroll progress. Apply to a div element.
<div htmlScrollContent> <!-- HTML content that scrolls in sync with 3D content --></div>Properties and Methods
| Property/Method | Description |
|---|---|
progress | A model that tracks the current scroll progress (0-1). |
offset | The damped scroll offset value. |
delta | The change in offset since last frame. |
range(from, distance, margin?) | Returns linear progress (0-1) within a scroll range. |
curve(from, distance, margin?) | Returns sinusoidal progress (0-1) within a scroll range. |
visible(from, distance, margin?) | Returns true if currently within the specified range. |
Accessing Scroll Utilities
@Component({ template: ` <ngts-scroll-controls [options]="{ pages: 3 }"> <ngt-group canvasScrollContent> <ngt-mesh [position]="[0, 0, 0]"> <ngt-box-geometry /> <ngt-mesh-standard-material /> </ngt-mesh> </ngt-group> </ngts-scroll-controls> `, imports: [NgtsScrollControls, NgtsCanvasScrollContent], schemas: [CUSTOM_ELEMENTS_SCHEMA],})class ScrollScene { scrollControls = viewChild.required(NgtsScrollControls);
constructor() { effect(() => { // Access scroll utilities const visible = this.scrollControls().visible(0, 1 / 3); const progress = this.scrollControls().range(0, 1 / 3); }); }}Options
Properties
| name | type | description |
|---|---|---|
| eps | number | Precision threshold for detecting scroll changes. Default: 0.00001 |
| horizontal | boolean | Whether to enable horizontal scrolling instead of vertical. Default: false |
| infinite | boolean | Whether to enable infinite/continuous scrolling (experimental). Default: false |
| pages | number | Defines the length of the scroll area. Each page is height:100%. Default: 1 |
| distance | number | A factor that increases scroll bar travel distance. Default: 1 |
| damping | number | Friction/smoothing duration in seconds. Default: 0.25 |
| maxSpeed | number | Maximum scroll speed in units per second. Default: Infinity |
| prepend | boolean | If true, attaches the scroll container before the canvas element. Default: false |
| enabled | boolean | Whether scroll controls are enabled. Default: true |
| style | object | Additional CSS styles to apply to the scroll container. Default: {} |