Skip to main content

Interactive Components

@wangyaoshen/locus-interaction provides several interactive components for creating engaging user experiences.

InteractivePoint

A draggable point component.

import { InteractivePoint } from '@wangyaoshen/locus-interaction';

const point = new InteractivePoint({
position: [100, 100], // Initial position
color: '#E91E63', // Color
radius: 15, // Radius
interactive: true, // Enable interaction
constrain: horizontal(100), // Constraint function
onMove: (pos) => { // Move callback
console.log('New position:', pos);
},
});

// Get/set position
point.getPosition(); // [100, 100]
point.setPosition([200, 200]);

// Drag control
point.startDrag();
point.drag([150, 150]);
point.endDrag();

// Keyboard control
point.moveByKey([1, 0], 10); // Move right 10 pixels

// State subscription
point.subscribe((state) => {
console.log('State changed:', state);
});

Configuration Options

OptionTypeDefaultDescription
positionVector2[0, 0]Initial position
colorstring'#E91E63'Point color
radiusnumber10Point radius
interactivebooleantrueEnable/disable interaction
constrainConstraintFunction-Movement constraint
onMove(pos: Vector2) => void-Move callback

Slider

A slider control for numeric values.

import { Slider } from '@wangyaoshen/locus-interaction';

const slider = new Slider({
min: 0, // Minimum value
max: 100, // Maximum value
value: 50, // Current value
step: 1, // Step value
direction: 'horizontal', // Direction
length: 200, // Track length
position: [100, 100], // Track start position
onChange: (value) => { // Value change callback
console.log('New value:', value);
},
});

// Get/set value
slider.getValue(); // 50
slider.setValue(75);

// Increment/decrement
slider.increment();
slider.decrement();

Configuration Options

OptionTypeDefaultDescription
minnumber0Minimum value
maxnumber100Maximum value
valuenumber50Initial value
stepnumber1Step increment
direction'horizontal' | 'vertical''horizontal'Slider direction
lengthnumber200Track length
positionVector2[0, 0]Track start position
onChange(value: number) => void-Value change callback

InteractiveLine

A draggable line segment with movable endpoints.

import { InteractiveLine } from '@wangyaoshen/locus-interaction';

const line = new InteractiveLine({
start: [0, 0], // Start point
end: [100, 100], // End point
constrainStart: horizontal(0), // Start point constraint
constrainEnd: vertical(100), // End point constraint
onChange: (start, end) => {
console.log('Line changed:', start, end);
},
});

// Get line properties
line.getLength(); // Line length
line.getMidpoint(); // Midpoint position

Configuration Options

OptionTypeDefaultDescription
startVector2[0, 0]Start point position
endVector2[100, 100]End point position
constrainStartConstraintFunction-Start point constraint
constrainEndConstraintFunction-End point constraint
onChange(start, end) => void-Change callback

InteractiveCurve

A Bezier curve with draggable control points.

import { InteractiveCurve } from '@wangyaoshen/locus-interaction';

// Cubic Bezier curve
const curve = new InteractiveCurve({
type: 'cubic',
start: [0, 0],
control1: [30, 100],
control2: [70, 100],
end: [100, 0],
editableEndpoints: true, // Allow endpoint editing
showControlLines: true, // Show control lines
onChange: (points) => {
console.log('Curve changed:', points);
},
});

// Get points on curve
curve.getPointAt(0.5); // Point at t=0.5
curve.getSamplePoints(50); // 50 sample points
curve.getTangentAt(0.5); // Tangent at t=0.5

Configuration Options

OptionTypeDefaultDescription
type'quadratic' | 'cubic''cubic'Curve type
startVector2-Start point
control1Vector2-First control point
control2Vector2-Second control point (cubic only)
endVector2-End point
editableEndpointsbooleantrueAllow endpoint editing
showControlLinesbooleantrueShow control lines
onChange(points: CurvePoints) => void-Change callback

Math Utilities

The package includes 2D vector and matrix operations:

import { Vector2, add, sub, scale, dist, normalize } from '@wangyaoshen/locus-interaction';

const v1: Vector2 = [100, 200];
const v2: Vector2 = [50, 50];

add(v1, v2); // [150, 250]
sub(v1, v2); // [50, 150]
scale(v1, 2); // [200, 400]
dist(v1, v2); // Distance between points
normalize(v1); // Unit vector