Skip to content

Commit 290efce

Browse files
author
Niilo Keinänen
committed
v5.2.0
1 parent 77b2531 commit 290efce

File tree

3 files changed

+49
-97
lines changed

3 files changed

+49
-97
lines changed

README.md

+29-29
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# JavaScript Heatmap Spectrogram Chart
2-
3-
![JavaScript Heatmap Spectrogram Chart](spectrogram-darkGold.png)
4-
1+
# JavaScript Heatmap Spectrogram Chart
2+
3+
![JavaScript Heatmap Spectrogram Chart](spectrogram-darkGold.png)
4+
55
This demo application belongs to the set of examples for LightningChart JS, data visualization library for JavaScript.
66

77
LightningChart JS is entirely GPU accelerated and performance optimized charting library for presenting massive amounts of data. It offers an easy way of creating sophisticated and interactive charts and adding them to your website or web application.
@@ -15,10 +15,10 @@ The demo can be used as an example or a seed project. Local execution requires t
1515
npm start # builds an application and starts the development server
1616

1717
- The application is available at _http://localhost:8080_ in your browser, webpack-dev-server provides hot reload functionality.
18-
19-
20-
## Description
21-
18+
19+
20+
## Description
21+
2222
This example shows a simple use case for Heatmaps as a spectrogram.
2323

2424
Spectrogram is a visual representation of the spectrum of frequencies. Spectrograms can be used to visualize any wave form. Most often spectrograms are used to display audio signals.
@@ -84,10 +84,10 @@ for (let row = 0; row < strideSize; row += 1) {
8484
[createchannelsplitter]: https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createChannelSplitter
8585
[createsciptprocessor]: https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createScriptProcessor
8686
[start-rendering]: https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext/startRendering
87-
88-
89-
## API Links
90-
87+
88+
89+
## API Links
90+
9191
* [Heatmap Grid Series Intensity]
9292
* [Paletted Fill Style]
9393
* [LUT]
@@ -97,10 +97,10 @@ for (let row = 0; row < strideSize; row += 1) {
9797
* [Color factory HSV]
9898
* [Empty fill style]
9999
* [Empty line style]
100-
101-
102-
## Support
103-
100+
101+
102+
## Support
103+
104104
If you notice an error in the example code, please open an issue on [GitHub][0] repository of the entire example.
105105

106106
Official [API documentation][1] can be found on [LightningChart][2] website.
@@ -116,17 +116,17 @@ Direct developer email support can be purchased through a [Support Plan][4] or b
116116
[2]: https://lightningchart.com
117117
[3]: https://stackoverflow.com/questions/tagged/lightningchart
118118
[4]: https://lightningchart.com/support-services/
119-
119+
120120
© LightningChart Ltd 2009-2022. All rights reserved.
121-
122-
123-
[Heatmap Grid Series Intensity]: https://lightningchart.com/js-charts/api-documentation/v5.1.0/classes/HeatmapGridSeriesIntensityValues.html
124-
[Paletted Fill Style]: https://lightningchart.com/js-charts/api-documentation/v5.1.0/classes/PalettedFill.html
125-
[LUT]: https://lightningchart.com/js-charts/api-documentation/v5.1.0/classes/LUT.html
126-
[Dashboard]: https://lightningchart.com/js-charts/api-documentation/v5.1.0/classes/Dashboard.html
127-
[Automatic axis scrolling options]: https://lightningchart.com/js-charts/api-documentation/v5.1.0/variables/AxisScrollStrategies.html
128-
[Automatic axis tick placement options]: https://lightningchart.com/js-charts/api-documentation/v5.1.0/variables/AxisTickStrategies.html
129-
[Color factory HSV]: https://lightningchart.com/js-charts/api-documentation/v5.1.0/functions/ColorHSV.html
130-
[Empty fill style]: https://lightningchart.com/js-charts/api-documentation/v5.1.0/variables/emptyFill-1.html
131-
[Empty line style]: https://lightningchart.com/js-charts/api-documentation/v5.1.0/variables/emptyLine.html
132-
121+
122+
123+
[Heatmap Grid Series Intensity]: https://lightningchart.com/js-charts/api-documentation/v5.2.0/classes/HeatmapGridSeriesIntensityValues.html
124+
[Paletted Fill Style]: https://lightningchart.com/js-charts/api-documentation/v5.2.0/classes/PalettedFill.html
125+
[LUT]: https://lightningchart.com/js-charts/api-documentation/v5.2.0/classes/LUT.html
126+
[Dashboard]: https://lightningchart.com/js-charts/api-documentation/v5.2.0/classes/Dashboard.html
127+
[Automatic axis scrolling options]: https://lightningchart.com/js-charts/api-documentation/v5.2.0/variables/AxisScrollStrategies.html
128+
[Automatic axis tick placement options]: https://lightningchart.com/js-charts/api-documentation/v5.2.0/variables/AxisTickStrategies.html
129+
[Color factory HSV]: https://lightningchart.com/js-charts/api-documentation/v5.2.0/functions/ColorHSV.html
130+
[Empty fill style]: https://lightningchart.com/js-charts/api-documentation/v5.2.0/variables/emptyFill-1.html
131+
[Empty line style]: https://lightningchart.com/js-charts/api-documentation/v5.2.0/variables/emptyLine.html
132+

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"webpack-stream": "^7.0.0"
1818
},
1919
"dependencies": {
20-
"@arction/lcjs": "^5.1.1",
20+
"@arction/lcjs": "^5.2.0",
2121
"@arction/xydata": "^1.4.0"
2222
},
2323
"lightningChart": {

src/index.js

+19-67
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,7 @@
55
const lcjs = require('@arction/lcjs')
66

77
// Extract required parts from LightningChartJS.
8-
const {
9-
lightningChart,
10-
PalettedFill,
11-
LUT,
12-
emptyFill,
13-
emptyLine,
14-
AxisScrollStrategies,
15-
AxisTickStrategies,
16-
ColorHSV,
17-
synchronizeAxisIntervals,
18-
regularColorSteps,
19-
Themes,
20-
} = lcjs
8+
const { lightningChart, PalettedFill, LUT, emptyLine, AxisScrollStrategies, AxisTickStrategies, regularColorSteps, Themes } = lcjs
219

2210
const AudioContext = window.AudioContext || window.webkitAudioContext
2311
// Create a new audio context,
@@ -182,7 +170,6 @@ const remapDataToTwoDimensionalMatrix = (data, strideSize, tickCount) => {
182170

183171
/**
184172
* Create a chart for a channel
185-
* @param {lcjs.Dashboard} dashboard Dashboard to create the chart in
186173
* @param {number} channelIndex Current channel index
187174
* @param {number} rows Data row count
188175
* @param {number} columns Data column count
@@ -191,17 +178,7 @@ const remapDataToTwoDimensionalMatrix = (data, strideSize, tickCount) => {
191178
* @param {number} minDecibels dB amount that matches value 0 in data (Uint8).
192179
* @param {number} maxDecibels dB amount that matches value 255 in data (Uint8).
193180
*/
194-
const createChannel = (dashboard, channelIndex, rows, columns, maxFreq, duration, minDecibels, maxDecibels) => {
195-
// Create a new chart in a specified row
196-
const chart = dashboard
197-
.createChartXY({
198-
columnIndex: 0,
199-
columnSpan: 1,
200-
rowIndex: channelIndex,
201-
rowSpan: 1,
202-
})
203-
// Hide the chart title
204-
.setTitleFillStyle(emptyFill)
181+
const createChannel = (chart, channelIndex, rows, columns, maxFreq, duration, minDecibels, maxDecibels) => {
205182
const theme = chart.getTheme()
206183

207184
// Define function that maps Uint8 [0, 255] to Decibels.
@@ -218,9 +195,11 @@ const createChannel = (dashboard, channelIndex, rows, columns, maxFreq, duration
218195
// Use half of the fft data range
219196
y: Math.ceil(maxFreq / 2),
220197
}
198+
const yAxis = chart.addAxisY({ iStack: 1 - channelIndex }).setMargins(channelIndex < 1 ? 15 : 0, channelIndex > 0 ? 15 : 0)
221199
// Create the series
222200
const series = chart
223201
.addHeatmapGridSeries({
202+
yAxis,
224203
// Data columns, defines horizontal resolution
225204
columns: columns,
226205
// Use half of the fft data range
@@ -254,23 +233,14 @@ const createChannel = (dashboard, channelIndex, rows, columns, maxFreq, duration
254233
)
255234

256235
// Set default X axis settings
257-
series.axisX
258-
.setInterval({ start: start.x, end: end.x, stopAxisAfter: false })
259-
.setTickStrategy(AxisTickStrategies.Empty)
260-
.setTitleMargin(0)
261-
.setScrollStrategy(undefined)
262-
.setMouseInteractions(false)
263-
// Set default chart settings
264-
chart.setPadding({ left: 0, top: 8, right: 8, bottom: 1 }).setMouseInteractions(false)
265-
// Set default X axis settings
266-
series.axisY
236+
yAxis
267237
.setInterval({ start: start.y, end: end.y, stopAxisAfter: false })
268238
.setTitle(`Channel ${channelIndex + 1} (Hz)`)
269239
.setScrollStrategy(AxisScrollStrategies.fitting)
270240

271241
return {
272-
chart,
273242
series,
243+
yAxis,
274244
}
275245
}
276246

@@ -279,25 +249,22 @@ const createChannel = (dashboard, channelIndex, rows, columns, maxFreq, duration
279249
* @param {WaveFormData} data Data set to render
280250
*/
281251
const renderSpectrogram = async (data) => {
282-
// Create a dashboard with enough rows for the number of channels in data set
283-
// NOTE: Using `Dashboard` is no longer recommended for new applications. Find latest recommendations here: https://lightningchart.com/js-charts/docs/basic-topics/grouping-charts/
284-
const dashboard = lc
285-
.Dashboard({
252+
const chart = lc
253+
.ChartXY({
286254
theme: Themes[new URLSearchParams(window.location.search).get('theme') || 'darkGold'] || undefined,
287-
numberOfColumns: 1,
288-
numberOfRows: data.channels.length,
289255
})
290-
// Hide the dashboard splitter
291-
.setSplitterStyle(emptyLine)
292-
293-
// Collection of created charts
294-
const charts = []
295-
256+
.setTitle('Spectrogram chart 2 channels')
257+
chart
258+
.getDefaultAxisX()
259+
.setTickStrategy(AxisTickStrategies.Numeric)
260+
.setScrollStrategy(AxisScrollStrategies.fitting)
261+
.setTitle(`Duration (s)`)
262+
chart.getDefaultAxisY().dispose()
296263
// Create channels and set data for each channel
297264
for (let i = 0; i < data.channels.length; i += 1) {
298265
// Create a chart for the channel
299266
const ch = createChannel(
300-
dashboard,
267+
chart,
301268
i,
302269
data.stride,
303270
data.tickCount,
@@ -317,32 +284,17 @@ const renderSpectrogram = async (data) => {
317284
iColumn: 0,
318285
values: remappedData,
319286
})
320-
// Add the created chart and series to collection
321-
charts.push(ch)
322287
}
323288

324-
// Style to bottom most chart axis to use it as the common axis for each chart
325-
charts[charts.length - 1].series.axisX
326-
.setTickStrategy(AxisTickStrategies.Numeric)
327-
.setScrollStrategy(AxisScrollStrategies.fitting)
328-
.setTitle(`Duration (s)`)
329-
330289
// Add LegendBox.
331-
const legend = dashboard
290+
const legend = chart
332291
.addLegendBox()
292+
.add(chart)
333293
// Dispose example UI elements automatically if they take too much space. This is to avoid bad UI on mobile / etc. devices.
334294
.setAutoDispose({
335295
type: 'max-width',
336296
maxWidth: 0.3,
337297
})
338-
.setPosition({ x: 100, y: 50 })
339-
.setOrigin({ x: 1, y: 0 })
340-
charts.forEach((c) => legend.add(c.chart))
341-
// Link chart X axis scales
342-
const syncedAxes = charts.map((chart) => chart.series.axisX)
343-
synchronizeAxisIntervals(...syncedAxes)
344-
345-
return dashboard
346298
}
347299

348300
;(async () => {
@@ -360,7 +312,7 @@ const renderSpectrogram = async (data) => {
360312
// Process the loaded wave form to prepare it for being added to the chart
361313
const processed = await processWaveForm(waveform)
362314
// Create a dashboard from the processed waveform data
363-
const dashboard = renderSpectrogram(processed)
315+
renderSpectrogram(processed)
364316
}
365317
// Check if audio context was started
366318
if (audioCtx.state === 'suspended') {

0 commit comments

Comments
 (0)