import type {PossibleVector2, SignalValue, Vector2Signal} from '@revideo/core'; import {CubicBezierSegment} from '../curves'; import type {PolynomialSegment} from '../curves/PolynomialSegment'; import {computed, vector2Signal} from '../decorators'; import {bezierCurveTo, lineTo, moveTo} from '../utils'; import type {BezierOverlayInfo} from './Bezier'; import {Bezier} from './Bezier'; import type {CurveProps} from './Curve'; export interface CubicBezierProps extends CurveProps { p0?: SignalValue; p0X?: SignalValue; p0Y?: SignalValue; p1?: SignalValue; p1X?: SignalValue; p1Y?: SignalValue; p2?: SignalValue; p2X?: SignalValue; p2Y?: SignalValue; p3?: SignalValue; p3X?: SignalValue; p3Y?: SignalValue; } /** * A node for drawing a cubic Bézier curve. * * @preview * ```tsx editor * import {makeScene2D, CubicBezier} from '@revideo/2d'; * import {createRef} from '@revideo/core'; * * export default makeScene2D(function* (view) { * const bezier = createRef(); * * view.add( * * ); * * yield* bezier().end(1, 1); * yield* bezier().start(1, 1).to(0, 1); * }); * ``` */ export class CubicBezier extends Bezier { /** * The start point of the Bézier curve. */ @vector2Signal('p0') public declare readonly p0: Vector2Signal; /** * The first control point of the Bézier curve. */ @vector2Signal('p1') public declare readonly p1: Vector2Signal; /** * The second control point of the Bézier curve. */ @vector2Signal('p2') public declare readonly p2: Vector2Signal; /** * The end point of the Bézier curve. */ @vector2Signal('p3') public declare readonly p3: Vector2Signal; public constructor(props: CubicBezierProps) { super(props); } @computed() protected segment(): PolynomialSegment { return new CubicBezierSegment(this.p0(), this.p1(), this.p2(), this.p3()); } protected overlayInfo(matrix: DOMMatrix): BezierOverlayInfo { const [p0, p1, p2, p3] = this.segment().transformPoints(matrix); const curvePath = new Path2D(); moveTo(curvePath, p0); bezierCurveTo(curvePath, p1, p2, p3); const handleLinesPath = new Path2D(); moveTo(handleLinesPath, p0); lineTo(handleLinesPath, p1); moveTo(handleLinesPath, p2); lineTo(handleLinesPath, p3); return { curve: curvePath, startPoint: p0, endPoint: p3, controlPoints: [p1, p2], handleLines: handleLinesPath, }; } }