Skip to content

Commit 83b681d

Browse files
committed
feat(LFO): implement triangle wave
1 parent cbf6b63 commit 83b681d

1 file changed

Lines changed: 38 additions & 3 deletions

File tree

  • packages/components/visualization/LFO

packages/components/visualization/LFO/LFO.tsx

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ export const LFO = forwardRef<LFORef, LFOProps>((props, ref) => {
106106

107107
generateSineWave(svg)
108108
generateSquareWave(svg)
109+
generateTriangleWave(svg)
109110
}
110111

111112
const generateSineWave = (svg: d3.Selection<d3.BaseType, unknown, null, undefined>) => {
@@ -134,10 +135,11 @@ export const LFO = forwardRef<LFORef, LFOProps>((props, ref) => {
134135
const generateSquareWave = (svg: d3.Selection<d3.BaseType, unknown, null, undefined>) => {
135136
if (type !== 'square' || !svg) return
136137

137-
const halfHeight = 0.5 * amplitude
138-
const data = [{ x: 0, y: 0.5 }].concat(
138+
const centerY = 0.5
139+
const halfHeight = centerY * amplitude
140+
const data = [{ x: 0, y: centerY }].concat(
139141
d3.range(0, 4 * Math.PI * (frequency * 10), 0.01).map((x) => {
140-
const y = Math.floor(x / Math.PI) % 2 === 0 ? 0.5 + halfHeight : 0.5 - halfHeight
142+
const y = Math.floor(x / Math.PI) % 2 === 0 ? centerY + halfHeight : centerY - halfHeight
141143
return { x, y }
142144
}),
143145
)
@@ -157,6 +159,39 @@ export const LFO = forwardRef<LFORef, LFOProps>((props, ref) => {
157159
.attr('transform', `translate(${delay}, 0)`)
158160
}
159161

162+
const generateTriangleWave = (svg: d3.Selection<d3.BaseType, unknown, null, undefined>) => {
163+
if (type !== 'triangle' || !svg) return
164+
165+
const centerY = 0.5
166+
const data = d3.range(0, 4 * Math.PI * (frequency * 10), 0.01).map((x) => {
167+
// Adjust the phase so that the waveform starts in the middle of the rising segment
168+
// and ensure that the starting point is at the center of the Y-axis
169+
// By mapping the x value to the corresponding position in a cycle,
170+
// the waveform is in the middle of the rising segment when it starts
171+
const phase = ((x + Math.PI / 2) % (2 * Math.PI)) / Math.PI
172+
173+
let y
174+
if (phase < 1) y = phase * amplitude
175+
else y = (2 - phase) * amplitude
176+
y = y - amplitude / 2 + centerY
177+
return { x, y }
178+
})
179+
180+
const line = d3
181+
.line<{ x: number; y: number }>()
182+
.x((d) => xScale.current!(d.x))
183+
.y((d) => yScale.current!(d.y))
184+
185+
svg
186+
.append('path')
187+
.datum(data)
188+
.attr('fill', 'none')
189+
.attr('stroke', lineColor)
190+
.attr('stroke-width', lineWidth)
191+
.attr('d', line)
192+
.attr('transform', `translate(${delay}, 0)`)
193+
}
194+
160195
const { base, svg } = useStyle()
161196

162197
return (

0 commit comments

Comments
 (0)