Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
Snekw committed Feb 22, 2024
1 parent f6f735d commit 815b866
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 215 deletions.
67 changes: 20 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,49 +21,32 @@ The demo can be used as an example or a seed project. Local execution requires t

_Also known as Multi-set / Clustered Bar Chart_

This example shows creation of a Grouped Bar Chart made on user side by utilizing RectangleSeries. This is a variation of normal Bar Chart where groups of bars are spaced apart from each other for further categorizing.
This example shows creation of a Grouped Bar Chart made on user side with BarChart.
This is a variation of normal Bar Chart where groups of bars are spaced apart from each other for further categorizing.

Here's the creation of a Grouped Bar Chart using a pre-defined interface.

```javascript
// Create Chart.
const chart = barChart()
// Add groups.
chart.addGroups(['Group A', 'Group B'])
// Add categories & values.
chart
.addCategory({
name: 'Category #1',
// 'data' contain values for each group in same order as they were defined before.
data: [100, 200],
fill: new SolidFill().setColor(prettyColor1),
})
.addCategory({
name: 'Category #2',
// 'data' contain values for each group in same order as they were defined before.
data: [50, 160],
fill: new SolidFill().setColor(prettyColor2),
})
const barChart = lightningChart().BarChart()

// Add categories('Finland', 'Germany', 'UK) and subCategory & values.
barChart.setDataGrouped(
['Finland', 'Germany', 'UK'],
[
{ subCategory: 'Engineers', values: [48, 27, 24] },
{ subCategory: 'Sales', values: [19, 40, 14] },
{ subCategory: 'Marketing', values: [33, 33, 62] },
],
)
```

The actual Grouped Bar Chart logic just serves to provide a starting point for users to create their own API based on their needs and preferences.


## API Links

* [XY cartesian chart]
* [Rectangle series]
* [Solid FillStyle]
* [Transparent FillStyle]
* [Empty LineStyle]
* [RGBA color factory]
* [Color palettes]
* [UI elements builders]
* [UI position origins]
* [Rectangle Series]
* [Auto cursor modes]
* [Axis]
* [Scroll strategies]
* [Bar chart]
* [Bar chart Value Axis]
* [Bar chart Category Axis]


## Support
Expand All @@ -74,7 +57,7 @@ Official [API documentation][1] can be found on [LightningChart][2] website.

If the docs and other materials do not solve your problem as well as implementation help is needed, ask on [StackOverflow][3] (tagged lightningchart).

If you think you found a bug in the LightningChart JavaScript library, please contact support@lightningchart.com.
If you think you found a bug in the LightningChart JavaScript library, please contact sales@lightningchart.com.

Direct developer email support can be purchased through a [Support Plan][4] or by contacting [email protected].

Expand All @@ -87,17 +70,7 @@ Direct developer email support can be purchased through a [Support Plan][4] or b
© LightningChart Ltd 2009-2022. All rights reserved.


[XY cartesian chart]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/classes/ChartXY.html
[Rectangle series]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/classes/RectangleSeries.html
[Solid FillStyle]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/classes/SolidFill.html
[Transparent FillStyle]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/variables/emptyFill-1.html
[Empty LineStyle]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/variables/emptyLine.html
[RGBA color factory]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/functions/ColorRGBA.html
[Color palettes]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/variables/ColorPalettes.html
[UI elements builders]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/variables/UIElementBuilders.html
[UI position origins]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/variables/UIOrigins.html
[Rectangle Series]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/classes/RectangleSeries.html
[Auto cursor modes]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/enums/AutoCursorModes.html
[Axis]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/classes/Axis.html
[Scroll strategies]: https://lightningchart.com/js-charts/api-documentation/v5.0.1/variables/AxisScrollStrategies.html
[Bar chart]: https://lightningchart.com/js-charts/api-documentation/v5.1.0/interfaces/BarChart.html
[Bar chart Value Axis]: https://lightningchart.com/js-charts/api-documentation/v5.1.0/classes/BarChartValueAxis.html
[Bar chart Category Axis]: https://lightningchart.com/js-charts/api-documentation/v5.1.0/classes/BarChartCategoryAxis.html

Binary file modified groupedBars-cyberSpace.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified groupedBars-darkGold.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified groupedBars-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified groupedBars-lightNature.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified groupedBars-turquoiseHexagon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
205 changes: 37 additions & 168 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,171 +5,40 @@
const lcjs = require('@arction/lcjs')

// Extract required parts from LightningChartJS.
const {
lightningChart,
emptyLine,
AutoCursorModes,
UIOrigins,
LegendBoxBuilders,
AxisScrollStrategies,
AxisTickStrategies,
UIElementBuilders,
Themes,
} = lcjs

const lc = lightningChart()

// Define an interface for creating vertical bars.
let barChart
{
barChart = (options) => {
const figureThickness = 10
const figureGap = figureThickness * 0.25
const groupGap = figureGap * 3.0
const groups = []
const categories = []

// Create a XY-Chart and add a RectSeries to it for rendering rectangles.
const chart = lc
.ChartXY(options)
.setTitle('Grouped Bars (Employee Count)')
.setAutoCursorMode(AutoCursorModes.onHover)
// Disable mouse interactions (e.g. zooming and panning) of plotting area
.setMouseInteractions(false)
// Temporary fix for library-side bug. Remove after fixed.
.setPadding({ bottom: 30 })

// X-axis of the series
const axisX = chart
.getDefaultAxisX()
.setMouseInteractions(false)
.setScrollStrategy(undefined)
// Disable default ticks.
.setTickStrategy(AxisTickStrategies.Empty)

// Y-axis of the series
const axisY = chart
.getDefaultAxisY()
.setMouseInteractions(false)
.setTitle('Number of Employees')
.setInterval({ start: 0, end: 70, stopAxisAfter: false })
.setScrollStrategy(AxisScrollStrategies.fitting)

// cursor
//#region
// Modify AutoCursor.
chart.setAutoCursor((cursor) =>
cursor
.setPointMarkerVisible(false)
.setTickMarkerXVisible(false)
.setTickMarkerYVisible(false)
.setGridStrokeXStyle(emptyLine)
.setGridStrokeYStyle(emptyLine)
.setResultTable((table) => {
table.setOrigin(UIOrigins.CenterBottom)
}),
)
// Define function that creates a Rectangle series (for each category), that adds cursor functionality to it
const createSeriesForCategory = (category) => {
const series = chart.addRectangleSeries().setDefaultStyle((rect) => rect.setStrokeStyle(emptyLine))
// Change how marker displays its information.
series.setCursorResultTableFormatter((builder, series, figure) => {
// Find cached entry for the figure.
let entry = {
name: category.name,
value: category.data[category.figures.indexOf(figure)],
}
// Parse result table content from values of 'entry'.
return builder.addRow('Department:', entry.name).addRow('# of employees:', String(entry.value))
})
return series
}
//#endregion
// LegendBox
//#region
const legendBox = chart
.addLegendBox(LegendBoxBuilders.VerticalLegendBox)
// Dispose example UI elements automatically if they take too much space. This is to avoid bad UI on mobile / etc. devices.
.setAutoDispose({
type: 'max-width',
maxWidth: 0.2,
})
.setTitle('Department')

//#endregion
// Function redraws bars chart based on values of 'groups' and 'categories'
const redraw = () => {
let x = 0
for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {
const group = groups[groupIndex]
const xStart = x
for (const category of categories) {
const value = category.data[groupIndex]
if (value !== undefined) {
// Position figure of respective value.
const figure = category.figures[groupIndex]
figure.setDimensions({
x,
y: 0,
width: figureThickness,
height: value,
})
// Figure gap
x += figureThickness + figureGap
}
}
// Position CustomTick
group.tick.setValue((xStart + x - figureGap) / 2)

// Group gap
x += groupGap
}
axisX.setInterval({ start: -(groupGap + figureGap), end: x, stopAxisAfter: false })
}
const addGroups = (names) => {
for (const name of names)
groups.push({
name,
tick: axisX
.addCustomTick()
.setGridStrokeLength(0)
.setTextFormatter((_) => name),
})
}
const addCategory = (entry) => {
// Each category has its own series.
const series = createSeriesForCategory(entry).setName(entry.name)
entry.figures = entry.data.map((value) => series.add({ x: 0, y: 0, width: 0, height: 0 }))
legendBox.add(series)
categories.push(entry)
redraw()
}
// Return public methods of a bar chart interface.
return {
addCategory,
addGroups,
}
}
}

// Use bar chart interface to construct series
const chart = barChart({
// theme: Themes.darkGold
})

// Add groups
chart.addGroups(['Finland', 'Germany', 'UK'])

// Add categories of bars
const categories = ['Engineers', 'Sales', 'Marketing']
const data = [
[48, 27, 24],
[19, 40, 14],
[33, 33, 62],
]
data.forEach((data, i) =>
chart.addCategory({
name: categories[i],
data,
}),
)
const { lightningChart, AxisTickStrategies, LegendBoxBuilders, AxisScrollStrategies, BarChartSorting, Themes } = lcjs

const barChart = lightningChart()
.BarChart({
// theme: Themes.darkGold
})
.setTitle('Grouped Bars (Employee Count)')
.setValueLabels(undefined)
.setCursorResultTableFormatter((builder, category, value, bar) => {
builder.addRow('Department:', bar.subCategory).addRow('# of employees:', String(value))
return builder
})

barChart
.setDataGrouped(
['Finland', 'Germany', 'UK'],
[
{ subCategory: 'Engineers', values: [48, 27, 24] },
{ subCategory: 'Sales', values: [19, 40, 14] },
{ subCategory: 'Marketing', values: [33, 33, 62] },
],
)
.setSorting(BarChartSorting.None).set

barChart.valueAxis.setTitle('Number of Employees')

// Add LegendBox.
const legend = barChart
.addLegendBox(LegendBoxBuilders.VerticalLegendBox)
// Dispose example UI elements automatically if they take too much space. This is to avoid bad UI on mobile / etc. devices.
.setAutoDispose({
type: 'max-width',
maxWidth: 0.2,
})
.setTitle('Department')

legend.add(barChart)

0 comments on commit 815b866

Please sign in to comment.