Skip to content

Commit 84dd118

Browse files
author
Niilo Keinänen
committed
Initial
0 parents  commit 84dd118

12 files changed

+316
-0
lines changed

.github/workflows/gh-pages-deploy.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: GitHub Pages
2+
3+
on:
4+
push:
5+
branches: [master]
6+
7+
jobs:
8+
build:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- uses: actions/checkout@v2
13+
14+
- name: Use Node.js 16.x
15+
uses: actions/setup-node@v1
16+
with:
17+
node-version: "16.x"
18+
19+
- name: Build
20+
env:
21+
LCJS_LICENSE: ${{ secrets.LCJS_DEPLOY_LICENSE }}
22+
run: |
23+
npm install
24+
npm run build
25+
26+
- name: Deploy
27+
uses: peaceiris/actions-gh-pages@v3
28+
with:
29+
github_token: ${{ secrets.GITHUB_TOKEN }}
30+
publish_dir: ./dist
31+
publish_branch: gh-pages

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
dist
3+

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 LightningChart Ltd.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# JavaScript Nanosecond Timestamp Chart
2+
3+
![JavaScript Nanosecond Timestamp Chart](nanosecondTimestampsChart-darkGold.png)
4+
5+
This demo application belongs to the set of examples for LightningChart JS, data visualization library for JavaScript.
6+
7+
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.
8+
9+
The demo can be used as an example or a seed project. Local execution requires the following steps:
10+
11+
- Make sure that relevant version of [Node.js](https://nodejs.org/en/download/) is installed
12+
- Open the project folder in a terminal:
13+
14+
npm install # fetches dependencies
15+
npm start # builds an application and starts the development server
16+
17+
- The application is available at _http://localhost:8080_ in your browser, webpack-dev-server provides hot reload functionality.
18+
19+
20+
## Description
21+
22+
Demonstration of time series zoom in capabilities of LightningChart JS.
23+
24+
The example loads random generated time series data with **1 nanosecond time step**.
25+
To highlight how difficult this is, normal JavaScript numbers can't even accurately measure timestamps with this accuracy.
26+
Nanosecond timestamps must be loaded as [BigInts](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
27+
28+
This example showcases 1 day of data with data gaps and total 1 million data points.
29+
By default, the user sees the maximum zoomed in view (approximately 50 nanoseconds).
30+
Below, you can see a zoom band chart showing the complete data set. This is mainly added there to help understand how ridiculous the zoom in magnitude is.
31+
32+
For more details about nanosecond timestamp use cases, please refer to [Developer documentation](https://lightningchart.com/js-charts/docs/more-guides/nanosecond-timestamps/)
33+
34+
35+
## API Links
36+
37+
* [XY cartesian chart]
38+
* [Line series]
39+
* [Axis]
40+
* [Axis tick strategies]
41+
42+
43+
## Support
44+
45+
If you notice an error in the example code, please open an issue on [GitHub][0] repository of the entire example.
46+
47+
Official [API documentation][1] can be found on [LightningChart][2] website.
48+
49+
If the docs and other materials do not solve your problem as well as implementation help is needed, ask on [StackOverflow][3] (tagged lightningchart).
50+
51+
If you think you found a bug in the LightningChart JavaScript library, please contact sales@lightningchart.com.
52+
53+
Direct developer email support can be purchased through a [Support Plan][4] or by contacting sales@lightningchart.com.
54+
55+
[0]: https://github.com/Arction/
56+
[1]: https://lightningchart.com/lightningchart-js-api-documentation/
57+
[2]: https://lightningchart.com
58+
[3]: https://stackoverflow.com/questions/tagged/lightningchart
59+
[4]: https://lightningchart.com/support-services/
60+
61+
© LightningChart Ltd 2009-2022. All rights reserved.
62+
63+
64+
[XY cartesian chart]: https://lightningchart.com/js-charts/api-documentation/v7.1.0/classes/ChartXY.html
65+
[Line series]: https://lightningchart.com/js-charts/api-documentation/v7.1.0/classes/LineSeries.html
66+
[Axis]: https://lightningchart.com/js-charts/api-documentation/v7.1.0/classes/Axis.html
67+
[Axis tick strategies]: https://lightningchart.com/js-charts/api-documentation/v7.1.0/variables/AxisTickStrategies.html
68+
618 KB
Loading
468 KB
Loading

nanosecondTimestampsChart-light.png

198 KB
Loading
152 KB
Loading
608 KB
Loading

package.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"version": "2.0.0",
3+
"scripts": {
4+
"build": "webpack --mode production",
5+
"start": "webpack serve"
6+
},
7+
"license": "MIT",
8+
"private": true,
9+
"main": "./src/index.js",
10+
"devDependencies": {
11+
"clean-webpack-plugin": "^4.0.0",
12+
"copy-webpack-plugin": "^10.0.0",
13+
"html-webpack-plugin": "^5.5.0",
14+
"webpack": "^5.64.4",
15+
"webpack-cli": "^4.9.1",
16+
"webpack-dev-server": "^4.6.0",
17+
"webpack-stream": "^7.0.0"
18+
},
19+
"dependencies": {
20+
"@lightningchart/lcjs": "^7.1.0",
21+
"@lightningchart/xydata": "^1.4.0"
22+
},
23+
"lightningChart": {
24+
"eID": "0046"
25+
}
26+
}

src/index.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
const lcjs = require('@lightningchart/lcjs')
2+
const { AxisTickStrategies, emptyFill, lightningChart, Themes } = lcjs
3+
4+
const exampleContainer = document.getElementById('chart') || document.body
5+
if (exampleContainer === document.body) {
6+
exampleContainer.style.width = '100vw'
7+
exampleContainer.style.height = '100vh'
8+
exampleContainer.style.margin = '0px'
9+
}
10+
const containerChart1 = document.createElement('div')
11+
const containerChart2 = document.createElement('div')
12+
exampleContainer.append(containerChart1)
13+
exampleContainer.append(containerChart2)
14+
containerChart1.style.width = '100%'
15+
containerChart1.style.height = '80%'
16+
containerChart2.style.width = '100%'
17+
containerChart2.style.height = '20%'
18+
19+
//
20+
// Example data generation
21+
//
22+
// step between data points = 1 nanosecond
23+
const stepNs = BigInt(1)
24+
// total generated data set time range = 24 hours
25+
const dateRangeNs = BigInt(24) * BigInt(60) * BigInt(60) * BigInt(1000) * BigInt(1000) * BigInt(1000)
26+
const sampleCount = 1_000_000
27+
const data = {
28+
x: new BigInt64Array(sampleCount),
29+
y: [Number.NaN],
30+
}
31+
data.x[0] = BigInt('1741946159532000000') // ns big int timestamp
32+
let x = data.x[0] + stepNs
33+
let iArr = 1
34+
const groupCount = 10
35+
for (let i = 0; i < groupCount; i += 1) {
36+
for (let c = 0; c < Math.floor(sampleCount / groupCount); c += 1) {
37+
data.x[iArr] = x
38+
data.y[iArr] = Math.random()
39+
iArr++
40+
x += stepNs
41+
}
42+
data.x[iArr] = x
43+
data.y[iArr] = Number.NaN
44+
iArr++
45+
x += stepNs
46+
x += dateRangeNs / BigInt(groupCount)
47+
}
48+
data.y.length = data.x.length
49+
console.log('raw data', data)
50+
//
51+
// Actual nanosecond timestamp chart creation
52+
//
53+
const lc = lightningChart({
54+
resourcesBaseUrl: new URL(document.head.baseURI).origin + new URL(document.head.baseURI).pathname + 'resources/',
55+
})
56+
const chart = lc
57+
.ChartXY({
58+
container: containerChart1,
59+
defaultAxisX: {
60+
type: 'linear-highPrecision',
61+
},
62+
theme: Themes[new URLSearchParams(window.location.search).get('theme') || 'darkGold'] || undefined,
63+
})
64+
.setTitle('Nanosecond timestamp chart')
65+
66+
// NOTE: LCJS can't directly consume bigint64array
67+
// shift bigint64 data to start from near 0 in order to store it in float64array without losing nanosecond precision
68+
const xsShifted = new Float64Array(sampleCount)
69+
const shiftDate = new Date(Number(data.x[0] / BigInt('1000000')))
70+
shiftDate.setHours(0, 0, 0, 0)
71+
const shiftOrigin = shiftDate.getTime()
72+
const shiftOriginNanos = BigInt(shiftOrigin) * BigInt(1_000_000)
73+
for (let i = 0; i < sampleCount; i++) {
74+
xsShifted[i] = Number(data.x[i] - shiftOriginNanos) / 1_000_000
75+
}
76+
console.log('shifted data', xsShifted)
77+
78+
const series = chart
79+
.addPointLineAreaSeries({ dataPattern: 'ProgressiveX' })
80+
.setAreaFillStyle(emptyFill)
81+
.setStrokeStyle((stroke) => stroke.setThickness(-1))
82+
.appendSamples({ xValues: xsShifted, yValues: data.y })
83+
84+
chart.axisX
85+
.setTickStrategy(AxisTickStrategies.DateTime, (strategy) =>
86+
strategy
87+
// This will result in library accounting for the previous shift by first timestamp
88+
.setDateOrigin(shiftDate),
89+
)
90+
// Apply default view for demo purposes. Note that these are shifted millisecond timestamps.
91+
.setInterval({ start: 86159532.54587169, end: 86159532.54595785 })
92+
93+
// Add ZBC just to show the absurd zoom in capability
94+
const zoomBandChart = lc.ZoomBandChart({ container: containerChart2 })
95+
zoomBandChart.add(series)
96+
97+
// For more details refer to nanosecond timestamps section in developer documentation https://lightningchart.com/js-charts/docs/

webpack.config.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
const HtmlWebpackPlugin = require('html-webpack-plugin')
2+
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
3+
const CopyWebpackPlugin = require('copy-webpack-plugin')
4+
const path = require('path')
5+
const webpack = require('webpack')
6+
7+
const targetFolderName = 'dist'
8+
const outputPath = path.resolve(__dirname, targetFolderName)
9+
const packageJSON = require('./package.json')
10+
11+
module.exports = {
12+
mode: 'development',
13+
entry: {
14+
app: packageJSON.main,
15+
},
16+
devServer: {
17+
static: outputPath,
18+
compress: true,
19+
},
20+
resolve: {
21+
modules: [path.resolve('./src'), path.resolve('./node_modules')],
22+
extensions: ['.js'],
23+
},
24+
output: {
25+
filename: 'js/[name].[contenthash].bundle.js',
26+
chunkFilename: 'js/[name].[contenthash].bundle.js',
27+
path: outputPath,
28+
},
29+
optimization: {
30+
splitChunks: {
31+
chunks: 'all',
32+
cacheGroups: {
33+
// make separate 'vendor' chunk that contains any dependencies
34+
// allows for smaller file sizes and faster builds
35+
vendor: {
36+
test: /[\\/]node_modules[\\/]/,
37+
chunks: 'initial',
38+
name: 'vendor',
39+
priority: -10,
40+
reuseExistingChunk: true,
41+
},
42+
},
43+
},
44+
runtimeChunk: 'single',
45+
},
46+
plugins: [
47+
new CleanWebpackPlugin(),
48+
new HtmlWebpackPlugin({
49+
title: 'app',
50+
filename: path.resolve(__dirname, 'dist', 'index.html'),
51+
}),
52+
new CopyWebpackPlugin({
53+
patterns: [
54+
{
55+
from: './assets/**/*',
56+
to: `./examples/assets/${packageJSON.lightningChart.eID}/[name][ext]`,
57+
noErrorOnMissing: true,
58+
},
59+
{
60+
from: './node_modules/@lightningchart/lcjs/dist/resources',
61+
to: 'resources',
62+
noErrorOnMissing: true,
63+
},
64+
],
65+
}),
66+
new webpack.DefinePlugin({
67+
LCJS_LICENSE: "'" + process.env.LCJS_LICENSE + "'",
68+
}),
69+
],
70+
}

0 commit comments

Comments
 (0)