11import * as d3 from 'd3'
2- import { forwardRef , useEffect , useImperativeHandle , useRef , useState } from 'react'
2+ import { forwardRef , useEffect , useImperativeHandle , useRef } from 'react'
33import { useResizeObserver } from '../../../lib/hooks/useResizeObserver'
44import { cn , validValue } from '../../../lib/utils'
55import { LFOProps , LFORef } from './types'
@@ -21,7 +21,7 @@ export const LFO = forwardRef<LFORef, LFOProps>((props, ref) => {
2121 const {
2222 type = TYPE ,
2323 frequency : _frequency = FREQUENCY ,
24- delay = DELAY ,
24+ delay : _delay = DELAY ,
2525 speed : _speed = SPEED ,
2626 min = MIN ,
2727 max = MAX ,
@@ -30,15 +30,21 @@ export const LFO = forwardRef<LFORef, LFOProps>((props, ref) => {
3030 ...restProps
3131 } = props
3232
33- const speed = validValue ( _speed , 0.1 , 1 )
3433 const frequency = validValue ( _frequency , 0 , 1 )
34+ const speed = validValue ( _speed , 0.1 , 1 )
35+ const delay = validValue ( _delay , 1 , 100 )
3536
3637 const LFORef = useRef < LFORef | null > ( null )
3738 const xScale = useRef < d3 . ScaleLinear < number , number > | null > ( null )
3839 const yScale = useRef < d3 . ScaleLinear < number , number > | null > ( null )
3940
4041 useImperativeHandle ( ref , ( ) => LFORef . current as LFORef )
4142
43+ useEffect ( ( ) => {
44+ generateScales ( )
45+ generateWave ( )
46+ } , [ speed , frequency , delay ] )
47+
4248 const dimensions = useResizeObserver ( LFORef , WIDTH , HEIGHT , ( ) => {
4349 generateScales ( )
4450 generateWave ( )
@@ -54,11 +60,6 @@ export const LFO = forwardRef<LFORef, LFOProps>((props, ref) => {
5460 yScale . current = d3 . scaleLinear ( ) . domain ( [ min , max ] ) . range ( [ height , 0 ] )
5561 }
5662
57- useEffect ( ( ) => {
58- generateScales ( )
59- generateWave ( )
60- } , [ speed , frequency ] )
61-
6263 const generateWave = ( ) => {
6364 generateSineWave ( )
6465 }
@@ -67,19 +68,32 @@ export const LFO = forwardRef<LFORef, LFOProps>((props, ref) => {
6768 if ( type !== 'sine' ) return
6869
6970 const { width, height } = dimensions . current
70-
7171 const svg = d3 . select ( LFORef . current ) . select ( 'svg' ) . attr ( 'width' , width ) . attr ( 'height' , height )
7272 svg . selectAll ( '*' ) . remove ( )
7373
74- const data = d3 . range ( 0 , 4 * Math . PI * ( speed * 10 ) , 0.01 ) . map ( ( x ) => ( {
75- x,
76- y : Math . sin ( x ) * frequency * ( max - min ) * 0.5 + ( max + min ) / 2 ,
77- } ) )
74+ if ( delay > 0 ) {
75+ svg
76+ . append ( 'line' )
77+ . attr ( 'x1' , 0 )
78+ . attr ( 'y1' , height / 2 )
79+ . attr ( 'x2' , delay )
80+ . attr ( 'y2' , height / 2 )
81+ . attr ( 'stroke' , lineColor )
82+ . attr ( 'stroke-width' , lineWidth )
83+ }
84+
85+ const data = d3 . range ( 0 , 4 * Math . PI * ( speed * 10 ) , 0.01 ) . map ( ( x ) => {
86+ return {
87+ x,
88+ y : Math . sin ( x ) * frequency * ( max - min ) * 0.5 + ( max + min ) / 2 ,
89+ }
90+ } )
7891
7992 const line = d3
8093 . line < { x : number ; y : number } > ( )
8194 . x ( ( d ) => xScale . current ! ( d . x ) )
8295 . y ( ( d ) => yScale . current ! ( d . y ) )
96+ . curve ( d3 . curveBasis )
8397
8498 svg
8599 . append ( 'path' )
@@ -88,6 +102,8 @@ export const LFO = forwardRef<LFORef, LFOProps>((props, ref) => {
88102 . attr ( 'stroke' , lineColor )
89103 . attr ( 'stroke-width' , lineWidth )
90104 . attr ( 'd' , line )
105+ // -1 to fix the gap between the line and the delay line
106+ . attr ( 'transform' , `translate(${ delay - 0.8 } , 0)` )
91107 }
92108
93109 const { base, svg } = useStyle ( )
0 commit comments