const lcjsTrader = require('@lightningchart/lcjs-trader')
const lcjs = require('@lightningchart/lcjs')
const {
Themes,
MapTypes,
PalettedFill,
LUT,
regularColorSteps,
ColorRGBA,
AxisTickStrategies,
emptyTick,
emptyFill,
emptyLine,
FormattingFunctions,
} = lcjs
const container = document.getElementById('chart-container') || document.body
lcjsTrader.trader(TRADER_LICENSE).then(async (trader) => {
const lc = trader.lightningChart()
const gdpData = await fetch(`${document.head.baseURI}examples/assets/1100/gdp.json`).then((r) => r.json())
// Array<{ "Country Code", "Country Name", "Value", "Year" }>
const mapChart = lc
.Map({
type: MapTypes.World,
})
.setTitle('Country gross domestic products (hover mouse to see history)')
.setCursorMode(undefined)
const theme = mapChart.getTheme()
// Load last years GDP values from data set to Map chart
const yearMax = gdpData.reduce((prev, cur) => Math.max(prev, cur.Year), 0)
const dataLastYear = gdpData.filter((item) => item.Year === yearMax)
let gdpLastYearMin
let gdpLastYearMax
mapChart.invalidateRegionValues((region) => {
const value = dataLastYear.find((item) => item['Country Code'] === region.ISO_A3)?.Value
if (value === undefined) return undefined
gdpLastYearMin = gdpLastYearMin === undefined ? value : Math.min(value, gdpLastYearMin)
gdpLastYearMax = gdpLastYearMax === undefined ? value : Math.max(value, gdpLastYearMax)
return value
})
let mousePosition
let pointedRegion
mapChart.addEventListener('ready', () => {
// Color each country according to the GDP value
const lut = new LUT({
interpolate: true,
steps: regularColorSteps(gdpLastYearMin, gdpLastYearMax, theme.examples.badGoodColorPalette.slice(1), {
formatLabels: (value) =>
FormattingFunctions.NumericUnits(value, { getInnerStart: () => gdpLastYearMin, getInnerEnd: () => gdpLastYearMax }),
}),
// This property is used to specify fallback color for regions which have no data.
color: ColorRGBA(0, 0, 0, 0),
})
mapChart.setFillStyle(
new PalettedFill({
lut,
}),
)
mousePosition = { clientX: 600, clientY: 600 }
pointedRegion = { name: 'Algeria', ISO_A3: 'DZA' }
})
// Create a separate XY chart that is displayed when mouse is hovered over the Map. This shows extra information about the region.
const containerOverlayCursor = document.createElement('div')
container.append(containerOverlayCursor)
const chartOverlayCursor = lc
.ChartXY({
container: containerOverlayCursor,
theme,
interactable: false,
})
.setTitle('')
.setPadding({ left: 0, bottom: 0, right: 20, top: 0 })
.setBackgroundFillStyle(emptyFill)
.setBackgroundStrokeStyle(emptyLine)
.setSeriesBackgroundFillStyle(emptyFill)
.setSeriesBackgroundStrokeStyle(emptyLine)
chartOverlayCursor.getDefaultAxisX().setTickStrategy(AxisTickStrategies.Numeric, (ticks) =>
ticks
.setFormattingFunction((x) => x.toFixed(0))
.setExtremeTickStyle(theme.xAxisNumericTicks.majorTickStyle)
.setMinorTickStyle(emptyTick),
)
chartOverlayCursor
.getDefaultAxisY()
.setTickStrategy(AxisTickStrategies.Numeric, (ticks) => ticks.setFormattingFunction(FormattingFunctions.NumericUnits))
chartOverlayCursor.engine.setBackgroundFillStyle(emptyFill)
const overlayCursorWidth = 280
const overlayCursorHeight = 200
containerOverlayCursor.style.position = 'absolute'
containerOverlayCursor.style.top = '0px'
containerOverlayCursor.style.backgroundColor = theme.isDark ? 'rgba(0,0,0,0.7)' : 'rgba(255,255,255,0.9)'
containerOverlayCursor.style.border = 'solid 8px transparent'
containerOverlayCursor.style.borderRadius = '16px'
containerOverlayCursor.style.width = `${overlayCursorWidth}px`
containerOverlayCursor.style.height = `${overlayCursorHeight}px`
containerOverlayCursor.style.transition = 'left 0.2s, top 0.2s, opacity 0.5s'
containerOverlayCursor.style.opacity = '0.0'
containerOverlayCursor.style.pointerEvents = 'none'
const overlayCursorGDPSeries = chartOverlayCursor.addPointLineAreaSeries({ schema: { x: { pattern: 'progressive' }, y: { pattern: null } } })
.setAreaFillStyle(emptyFill)
.setPointFillStyle(emptyFill)
mapChart.regions.addEventListener('pointermove', (event, region) => {
mousePosition = event
pointedRegion = region
})
mapChart.addEventListener('pointerleave', () => {
mousePosition = undefined
pointedRegion = undefined
})
let prevRegion
setInterval(() => {
if (pointedRegion && mousePosition) {
const containerBounds = container.getBoundingClientRect()
containerOverlayCursor.style.left = `${Math.max(
mousePosition.clientX - (overlayCursorWidth + 10 + containerBounds.left),
10,
)}px`
containerOverlayCursor.style.top = `${Math.max(mousePosition.clientY - (overlayCursorHeight + 10 + containerBounds.top), 10)}px`
containerOverlayCursor.style.opacity = '1.0'
if (pointedRegion !== prevRegion) {
chartOverlayCursor.setTitle(`${pointedRegion.name} GDP`)
const data = gdpData
.filter((item) => item['Country Code'] === pointedRegion.ISO_A3)
.map((item) => ({ x: item.Year, y: item.Value }))
overlayCursorGDPSeries.clear().appendJSON(data)
}
chartOverlayCursor.engine.layout()
} else {
containerOverlayCursor.style.opacity = '0.0'
}
prevRegion = pointedRegion
}, 1000 / 60)
})
Interactive World GDP Map - Editor
Example of using MapChart for data analysis and drill-down.
Countries are colored based on their gross domestic product value (year 2016). The highest GDPs are highlighted with green or "positive" colors (depends on active color theme).
By placing the mouse cursor above a country, that country's GDP history is displayed in a overlay line chart.