import ChartJS, { ChartConfiguration } from 'chart.js/auto' export interface HistogramConstructor { root: HTMLElement axisLabels?: { x: string, y: string } title?: string width?: number } export default class Histogram { private chart: ChartJS<'bar', number[]> private width: number constructor(opts: HistogramConstructor) { this.width = opts.width || 400 const title = opts.title || 'Histogram' const axisLabels = opts.axisLabels || { x: 'Bins', y: 'Frequency' } const canvas = document.createElement('canvas') const draggable = document.createElement('drag-pane') draggable.setAttribute('heading', title ) draggable.setAttribute('key', title) draggable.appendChild(canvas) opts.root.appendChild(draggable) canvas.width = this.width const defaultChartOptions: ChartConfiguration<'bar', number[]> = { type: 'bar', data: { labels: [], datasets: [{ label: title, data: [], backgroundColor: 'rgba(54, 162, 235, 0.2)', borderColor: 'rgba(54, 162, 235, 1)', borderWidth: 1 }] }, options: { scales: { x: { title: { display: true, text: axisLabels.x } }, y: { title: { display: true, text: axisLabels.y }, beginAtZero: true } } } } this.chart = new ChartJS<'bar', number[]>(canvas, defaultChartOptions) } public applyData(data: number[], binSize: number): void { const { bins, frequencies } = this.calculateBins(data, binSize) this.chart.data.labels = bins this.chart.data.datasets[0].data = frequencies this.chart.update() } private calculateBins(data: number[], binSize: number): { bins: number[], frequencies: number[] } { const max = Math.max(...data) const min = Math.min(...data) // `bins` used as labels for the chart const bins = [] const frequencies = [] // gets the precision of the bin size float const precision = binSize.toString().split('.')[1]?.length || 1 for (let start = min; start <= max; start += binSize) { bins.push(`${+(start).toFixed(precision)}-${ +(start + binSize).toFixed(precision)}`) frequencies.push(0) } data.forEach(value => { const binIndex = Math.floor((value - min) / binSize) frequencies[binIndex]++ }) return { bins, frequencies } } }