├── deploy.sh
├── .gitignore
├── src
├── index.ts
├── Telemap
│ ├── StackedPercentTelemap.ts
│ ├── LineTelemap.ts
│ ├── StackedTelemap.ts
│ ├── TwoAxisTelemap.ts
│ └── AbstractTelemap.ts
├── Display
│ ├── LineTeledisplay.ts
│ ├── TwoAxisTeledisplay.ts
│ ├── StackedPercentTeledisplay.ts
│ ├── StackedTeledisplay.ts
│ └── AbstractTeledisplay.ts
├── Telemation.ts
├── Drawer
│ ├── LineChartDrawer.ts
│ ├── StackedPercentChartDrawer.ts
│ ├── StackedChartDrawer.ts
│ └── AbstractChartDrawer.ts
├── Teletip.ts
├── Telegend.ts
├── Telecolumn.ts
├── Telecanvas.ts
└── Telechart.ts
├── webpack.prod.js
├── webpack.dev.js
├── make-sources-tar.sh
├── README.md
├── tslint.json
├── webpack.common.js
├── package.json
├── dist
├── telechart.css
├── index.html
└── data
│ ├── 1
│ └── overview.json
│ ├── 2
│ └── overview.json
│ ├── 3
│ └── overview.json
│ ├── 4
│ └── overview.json
│ └── 5
│ └── overview.json
└── tsconfig.json
/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | git pull origin master
4 | npm run build
5 | ./make-sources-tar.sh
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .code
3 | dist/*
4 | !dist/index.html
5 | !dist/data
6 | !dist/telechart.css
7 | node_modules
8 | package-lock.json
9 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Telechart } from './Telechart'
2 |
3 | export { Telechart }
4 | export default Telechart
5 | ; (window as any).Telechart = Telechart
6 |
--------------------------------------------------------------------------------
/webpack.prod.js:
--------------------------------------------------------------------------------
1 | const extend = require('webpack-merge')
2 |
3 | module.exports = extend(require('./webpack.common'), {
4 | mode: 'production',
5 | devtool: false,
6 | })
--------------------------------------------------------------------------------
/webpack.dev.js:
--------------------------------------------------------------------------------
1 | const extend = require('webpack-merge')
2 |
3 | module.exports = extend(require('./webpack.common'), {
4 | mode: 'development',
5 | devtool: 'inline-source-map',
6 | })
--------------------------------------------------------------------------------
/make-sources-tar.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | tar -czf dist/sources.tar.gz --exclude="node_modules" --exclude="package-lock.json" --exclude="dist/telechart.min.js" --exclude="dist/sources.tar.gz" * .gitignore
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 5 charts for Telegram April 2019 Coding Contest
2 |
3 | To see how it looks just do this:
4 |
5 | ```bash
6 | git clone https://github.com/native-elements/telechart && cd telechart
7 | npm install
8 | npm run demo
9 | ```
10 |
11 | After that new browser tab shall open.
12 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "error",
3 | "extends": [
4 | "tslint:recommended"
5 | ],
6 | "jsRules": {},
7 | "rules": {
8 | "semicolon": false,
9 | "arrow-parens": false,
10 | "quotemark": {
11 | "options": "single"
12 | },
13 | "align": false,
14 | "ordered-imports": false,
15 | "no-console": false,
16 | "object-literal-sort-keys": false,
17 | "max-line-length": false
18 | },
19 | "rulesDirectory": []
20 | }
--------------------------------------------------------------------------------
/webpack.common.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | entry: ['./src/index.ts'],
5 | module: {
6 | rules: [
7 | {
8 | test: /\.tsx?$/,
9 | use: 'ts-loader',
10 | exclude: /node_modules/
11 | }
12 | ]
13 | },
14 | resolve: {
15 | extensions: [ '.tsx', '.ts', '.js' ]
16 | },
17 | output: {
18 | filename: 'telechart.min.js',
19 | path: path.resolve(__dirname, 'dist')
20 | }
21 | }
--------------------------------------------------------------------------------
/src/Telemap/StackedPercentTelemap.ts:
--------------------------------------------------------------------------------
1 | import { StackedTelemap } from './StackedTelemap'
2 | import Telechart from '../index';
3 | import { StackedPercentChartDrawer } from '../Drawer/StackedPercentChartDrawer'
4 |
5 | export class StackedPercentTelemap extends StackedTelemap {
6 |
7 | constructor(telechart: Telechart) {
8 | super(telechart)
9 | this.drawers.push(new StackedPercentChartDrawer(telechart, { noGuides: true, noMilestones: true, topPadding: this.topPadding, bottomPadding: this.bottomPadding }))
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "telechart",
3 | "version": "0.0.1",
4 | "description": "",
5 | "scripts": {
6 | "build": "webpack --config webpack.prod.js",
7 | "watch": "webpack -w --config webpack.dev.js",
8 | "demo": "npm run build && http-server ./dist -o -p 9876",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "author": "Valery Shibanov",
12 | "license": "MIT",
13 | "dependencies": {
14 | "http-server": "^0.12.3"
15 | },
16 | "devDependencies": {
17 | "css-loader": "^2.1.1",
18 | "mini-css-extract-plugin": "^0.5.0",
19 | "ts-loader": "^5.3.3",
20 | "typescript": "^3.3.3333",
21 | "webpack": "^4.29.6",
22 | "webpack-cli": "^3.2.3",
23 | "webpack-merge": "^4.2.1"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Telemap/LineTelemap.ts:
--------------------------------------------------------------------------------
1 | import { AbstractTelemap } from './AbstractTelemap'
2 | import { Telecolumn } from '../Telecolumn'
3 | import { Telechart } from '../Telechart'
4 | import { LineChartDrawer } from '../Drawer/LineChartDrawer'
5 |
6 | export class LineTelemap extends AbstractTelemap {
7 |
8 | constructor(telechart: Telechart) {
9 | super(telechart)
10 | this.drawers.push(new LineChartDrawer(telechart, { noGuides: true, noMilestones: true, topPadding: this.topPadding, bottomPadding: this.bottomPadding }))
11 | }
12 |
13 | public addColumn(column: Telecolumn) {
14 | this.drawers.forEach(d => d.addColumn(column))
15 | super.addColumn(column)
16 | }
17 |
18 | protected drawColumns() {
19 | for (const drawer of this.drawers) {
20 | drawer.drawColumns()
21 | }
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/Telemap/StackedTelemap.ts:
--------------------------------------------------------------------------------
1 | import { AbstractTelemap } from './AbstractTelemap'
2 | import { Telecolumn } from '../Telecolumn'
3 | import { Telechart } from '../Telechart'
4 | import { StackedChartDrawer } from '../Drawer/StackedChartDrawer'
5 |
6 | export class StackedTelemap extends AbstractTelemap {
7 |
8 | constructor(telechart: Telechart) {
9 | super(telechart)
10 | this.drawers.push(new StackedChartDrawer(telechart, { noGuides: true, noMilestones: true, topPadding: this.topPadding, bottomPadding: this.bottomPadding }))
11 | }
12 |
13 | public addColumn(column: Telecolumn) {
14 | this.drawers.forEach(d => d.addColumn(column))
15 | super.addColumn(column)
16 | }
17 |
18 | protected drawColumns() {
19 | for (const drawer of this.drawers) {
20 | drawer.drawColumns()
21 | }
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/Telemap/TwoAxisTelemap.ts:
--------------------------------------------------------------------------------
1 | import { AbstractTelemap } from './AbstractTelemap'
2 | import { Telechart } from '../Telechart'
3 | import { LineChartDrawer } from '../Drawer/LineChartDrawer'
4 | import { Telecolumn } from '../Telecolumn'
5 |
6 | export class TwoAxisTelemap extends AbstractTelemap {
7 |
8 | constructor(telechart: Telechart) {
9 | super(telechart)
10 | this.drawers.push(new LineChartDrawer(telechart, { topPadding: this.topPadding, bottomPadding: this.bottomPadding }))
11 | this.drawers.push(new LineChartDrawer(telechart, { noGuides: true, noMilestones: true, topPadding: this.topPadding, bottomPadding: this.bottomPadding }))
12 | }
13 |
14 | public addColumn(column: Telecolumn) {
15 | if (this.columns.length === 0) {
16 | this.drawers[0].addColumn(column)
17 | } else if (this.columns.length === 1) {
18 | this.drawers[1].addColumn(column)
19 | }
20 | super.addColumn(column)
21 | }
22 |
23 | protected drawColumns() {
24 | if (!this.firstDrawer) {
25 | return
26 | }
27 | for (const drawer of this.drawers as LineChartDrawer[]) {
28 | drawer.drawColumns()
29 | }
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/Display/LineTeledisplay.ts:
--------------------------------------------------------------------------------
1 | import { AbstractTeledisplay } from './AbstractTeledisplay'
2 | import { LineChartDrawer } from '../Drawer/LineChartDrawer'
3 | import { Telechart } from '../Telechart'
4 | import { Telecolumn } from '../Telecolumn'
5 |
6 | export class LineTeledisplay extends AbstractTeledisplay {
7 |
8 | constructor(telechart: Telechart) {
9 | super(telechart)
10 | this.drawers.push(new LineChartDrawer(telechart, { isRangeDisplay: true, lineWidth: 2, topPadding: 15, bottomPadding: 40 + this.telechart.telemap.height }))
11 | }
12 |
13 | public addColumn(column: Telecolumn) {
14 | super.addColumn(column)
15 | this.drawers.forEach(d => d.addColumn(column))
16 | }
17 |
18 | public draw() {
19 | if (!this.firstDrawer) {
20 | return
21 | }
22 | this.firstDrawer.drawGuides(this.axisColor)
23 | for (const drawer of this.drawers as LineChartDrawer[]) {
24 | drawer.drawMilestones(this.axisTextColor)
25 | drawer.drawCurrentLine(this.lineColor)
26 | drawer.drawColumns()
27 | drawer.drawGuides(undefined, this.axisTextColor)
28 | drawer.drawCurrentPoints()
29 | }
30 | this.updateTeletip()
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/Telemation.ts:
--------------------------------------------------------------------------------
1 | export class Telemation {
2 |
3 | public static create(to: number): Telemation
4 | public static create(from: number, to: number, duration: number): Telemation
5 |
6 | public static create(a: number, b?: number, c?: number) {
7 | if (arguments.length === 1) {
8 | return new Telemation(0, a, 0)
9 | }
10 | return new Telemation(a, b!, c!)
11 | }
12 |
13 | public finished: boolean
14 | protected start: number
15 |
16 | constructor(public from: number, public to: number, protected duration: number) {
17 | this.start = Date.now()
18 | this.finished = !duration
19 | }
20 |
21 | public update(to: number): Telemation
22 | public update(from: number, to: number, duration: number): Telemation
23 |
24 | public update(a: number, b?: number, c?: number): Telemation {
25 | if (arguments.length === 1) {
26 | this.from = 0
27 | this.to = a
28 | this.duration = 0
29 | } else {
30 | this.from = a
31 | this.to = b!
32 | this.duration = c!
33 | }
34 | this.finished = !this.duration
35 |
36 | return this
37 | }
38 |
39 | get value() {
40 | if (this.finished) {
41 | return this.to
42 | }
43 | const p = Math.min(1, Math.max(0, ((Date.now() - this.start)) / this.duration))
44 | if (p === 1) {
45 | this.finished = true
46 | return this.to
47 | } else if (p === 0) {
48 | return this.from
49 | }
50 | return (this.from + (this.to - this.from) * (p * (2 - p)))
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/Drawer/LineChartDrawer.ts:
--------------------------------------------------------------------------------
1 | import { AbstractChartDrawer, IAbstractChartDrawerOptions } from './AbstractChartDrawer'
2 | import { Telecolumn } from '../Telecolumn'
3 | import { Telechart} from '../Telechart'
4 |
5 | export interface ILineChartDrawerOptions extends IAbstractChartDrawerOptions {
6 | lineWidth?: number
7 | }
8 |
9 | export class LineChartDrawer extends AbstractChartDrawer {
10 | public lineWidth: number
11 |
12 | constructor(telechart: Telechart, options?: ILineChartDrawerOptions) {
13 | super(telechart, options)
14 | this.lineWidth = options && options.lineWidth ? options.lineWidth : 1
15 | }
16 |
17 | public drawColumns() {
18 | const c = this.telecanvas
19 | c.save()
20 | c.setClippingRect(0, 0, c.width, c.height - this.bottomPadding + 30)
21 | this.columns.forEach(col => this.drawColumn(col))
22 | c.restore()
23 | if (!this.borders.maxX.finished || !this.borders.maxY.finished || (!this.isZeroStart && !this.borders.minY.finished)) {
24 | this.telechart.redraw()
25 | }
26 | }
27 |
28 | public drawColumn(column: Telecolumn) {
29 | if (!column.opacity.value) {
30 | return
31 | }
32 | const c = this.telecanvas
33 | const allVals = this.getInDisplayColumnValues(column)
34 | if (allVals.length) {
35 | let opacity = Math.round(column.opacity.value * 255).toString(16)
36 | if (opacity.length === 1) {
37 | opacity = '0' + opacity
38 | }
39 | c.path(allVals.map(i => [this.getCanvasX(i.x), this.getCanvasY(i.y)] as [number, number]), column.color + opacity, this.lineWidth)
40 | if (!column.opacity.finished) {
41 | this.telechart.redraw()
42 | }
43 | }
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/Display/TwoAxisTeledisplay.ts:
--------------------------------------------------------------------------------
1 | import { AbstractTeledisplay } from './AbstractTeledisplay'
2 | import { LineChartDrawer } from '../Drawer/LineChartDrawer'
3 | import { Telecolumn } from '../Telecolumn'
4 | import { Telechart } from '../Telechart'
5 |
6 | export class TwoAxisTeledisplay extends AbstractTeledisplay {
7 |
8 | constructor(telechart: Telechart) {
9 | super(telechart)
10 | this.drawers.push(new LineChartDrawer(telechart, { isRangeDisplay: true, lineWidth: 2, topPadding: 15, bottomPadding: 40 + this.telechart.telemap.height }))
11 | this.drawers.push(new LineChartDrawer(telechart, { isRangeDisplay: true, noMilestones: true, lineWidth: 2, topPadding: 15, bottomPadding: 40 + this.telechart.telemap.height }))
12 | }
13 |
14 | public addColumn(column: Telecolumn) {
15 | super.addColumn(column)
16 | if (this.columns.length === 1) {
17 | this.drawers[0].addColumn(column)
18 | } else if (this.columns.length === 2) {
19 | this.drawers[1].addColumn(column)
20 | }
21 | }
22 |
23 | public draw() {
24 | if (!this.firstDrawer) {
25 | return
26 | }
27 | for (let n = 0; n < this.drawers.length; n++) {
28 | const drawer = this.drawers[n] as LineChartDrawer
29 | if (n === 0) {
30 | drawer.drawMilestones(this.axisTextColor)
31 | drawer.drawCurrentLine(this.lineColor)
32 | }
33 | drawer.drawGuides(this.theme === 'dark' ? '#3b4453' : '#eaebed')
34 | }
35 | for (const drawer of this.drawers) {
36 | drawer.drawColumns()
37 | }
38 | for (let n = 0; n < this.drawers.length; n++) {
39 | const drawer = this.drawers[n] as LineChartDrawer
40 | drawer.drawGuides(undefined, this.columns[n].color, n === 0 ? 'left' : 'right')
41 | drawer.drawCurrentPoints()
42 | }
43 | this.updateTeletip()
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/Display/StackedPercentTeledisplay.ts:
--------------------------------------------------------------------------------
1 | import { AbstractTeledisplay } from './AbstractTeledisplay'
2 | import { Telechart } from '../Telechart'
3 | import { Telecolumn } from '../Telecolumn'
4 | import { StackedChartDrawer } from '../Drawer/StackedChartDrawer'
5 | import { StackedPercentChartDrawer } from '../Drawer/StackedPercentChartDrawer'
6 | import { ITeletipContent } from '../Teletip'
7 |
8 | export class StackedPercentTeledisplay extends AbstractTeledisplay {
9 | protected drawers: StackedChartDrawer[] = []
10 |
11 | constructor(telechart: Telechart) {
12 | super(telechart)
13 | this.drawers.push(new StackedPercentChartDrawer(telechart, { isRangeDisplay: true, topPadding: 15, bottomPadding: 40 + this.telechart.telemap.height }))
14 | }
15 |
16 | public addColumn(column: Telecolumn) {
17 | super.addColumn(column)
18 | this.drawers.forEach(d => d.addColumn(column))
19 | }
20 |
21 | public draw() {
22 | if (!this.firstDrawer) {
23 | return
24 | }
25 | const textColor = this.theme === 'dark' ? '#ECF2F87F' : '#2525297F'
26 | const c = this.telecanvas
27 | c.text('100%', [0, this.firstDrawer.topPadding - 6], textColor, undefined, 11)
28 | for (const drawer of this.drawers as StackedPercentChartDrawer[]) {
29 | drawer.drawMilestones(this.axisTextColor)
30 | drawer.drawColumns()
31 | drawer.drawGuides(this.axisColor, textColor, undefined, (label) => label + '%')
32 | drawer.drawCurrentLine(this.theme === 'dark' ? '#dfe6eb7F' : '#3b4a5a7F')
33 | }
34 | this.updateTeletip()
35 | }
36 |
37 | protected getTeletipContent(currentColumns: Telecolumn[]): ITeletipContent {
38 | const sum = currentColumns.reduce((r, v) => r + v.currentPoint!.y, 0)
39 | const values = currentColumns.map(col => {
40 | return {
41 | name: col.name,
42 | color: col.color,
43 | value: this.telechart.formatNumber(col.currentPoint!.y),
44 | percentage: Math.round(col.currentPoint!.y / sum * 100),
45 | }
46 | })
47 | return { title: this.telechart.getDateString(currentColumns[0]!.currentPoint!.x, 'D, j M Y'), values }
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/Display/StackedTeledisplay.ts:
--------------------------------------------------------------------------------
1 | import { AbstractTeledisplay } from './AbstractTeledisplay'
2 | import { Telechart } from '../Telechart'
3 | import { Telecolumn } from '../Telecolumn'
4 | import { StackedChartDrawer } from '../Drawer/StackedChartDrawer'
5 |
6 | interface IStackedTeledisplayOptions {
7 | rectangle?: boolean
8 | }
9 |
10 | export class StackedTeledisplay extends AbstractTeledisplay {
11 | protected drawers: StackedChartDrawer[] = []
12 | protected rectangle: boolean
13 |
14 | constructor(telechart: Telechart, options?: IStackedTeledisplayOptions) {
15 | super(telechart)
16 | this.rectangle = options && options.rectangle ? true : false
17 | this.drawers.push(new StackedChartDrawer(telechart, {
18 | isRangeDisplay: true,
19 | topPadding: 15,
20 | bottomPadding: 40 + this.telechart.telemap.height,
21 | rectangle: this.rectangle,
22 | }))
23 | }
24 |
25 | public addColumn(column: Telecolumn) {
26 | super.addColumn(column)
27 | this.drawers.forEach(d => d.addColumn(column))
28 | }
29 |
30 | public draw() {
31 | if (!this.firstDrawer) {
32 | return
33 | }
34 | for (const drawer of this.drawers as StackedChartDrawer[]) {
35 | drawer.drawMilestones(this.axisTextColor)
36 | drawer.drawColumns()
37 | drawer.drawGuides(this.axisColor, this.theme === 'dark' ? '#ECF2F87F' : '#2525297F')
38 | if (!this.rectangle) {
39 | drawer.drawCurrentLine(this.theme === 'dark' ? '#dfe6eb7F' : '#3b4a5a7F')
40 | }
41 | }
42 | this.updateTeletip()
43 | }
44 |
45 | protected onMouseMove(x: number, y: number) {
46 | if (!this.rectangle) {
47 | super.onMouseMove(x, y)
48 | return
49 | }
50 | if (!this.drawers.length || !this.firstDrawer || !this.firstDrawer.bordersAnimationFinished) {
51 | return
52 | }
53 | if (x >= 0 && y >= 0 && x < this.telecanvas.width && y < this.height) {
54 | const val = this.firstDrawer.getXValue(x - this.telecanvas.width / this.drawers[0].valuesLength / 2)
55 | if (this.columns.reduce((r, c) => c.setCurrentX(val) || r, false)) {
56 | this.telechart.redraw()
57 | }
58 | }
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/Drawer/StackedPercentChartDrawer.ts:
--------------------------------------------------------------------------------
1 | import { Telecolumn } from '../Telecolumn'
2 | import { StackedChartDrawer } from './StackedChartDrawer'
3 | import { Telemation } from '../Telemation'
4 |
5 | export class StackedPercentChartDrawer extends StackedChartDrawer {
6 | protected guidesCount = 4
7 |
8 | public drawColumns() {
9 | let prev: number[]|undefined
10 | const borders = { minX: this.borders.minX.value, maxX: this.borders.maxX.value, minY: 0, maxY: this.borders.maxY.value }
11 | const colsValues: Array<{ col: Telecolumn, values: Array<{ x: number, y: number }> }> = []
12 | for (const col of this.columns) {
13 | if (!col.opacity.value) {
14 | continue
15 | }
16 | colsValues.push({ col, values: this.getInDisplayColumnValues(col, [borders.minX, borders.maxX]) })
17 | }
18 | if (!colsValues.length) {
19 | return
20 | }
21 | for (let n = colsValues[0].values.length - 1; n >= 0; n--) {
22 | const sum = colsValues.reduce((r, v) => r + v.values[n].y * v.col.opacity.value, 0)
23 | for (const colVals of colsValues) {
24 | colVals.values[n] = { x: colVals.values[n].x, y: colVals.values[n].y / sum * 100 }
25 | }
26 | }
27 | for (const colVals of colsValues) {
28 | const result = this.drawValues(colVals.col, colVals.values, [borders.minX, borders.maxX], prev)
29 | if (result && !prev) {
30 | prev = result
31 | } else if (result) {
32 | for (let n = result.length - 1; n >= 0; n--) {
33 | prev![n] = prev![n] + result[n]
34 | }
35 | }
36 | }
37 | if (!this.borders.maxX.finished || !this.borders.maxY.finished) {
38 | this.telechart.redraw()
39 | }
40 | }
41 |
42 | protected getNewBorders(duration?: number) {
43 | const result = {
44 | minX: Math.min(...this.columns.filter(c => c.visible).map(c => c.getMinX(this.isRangeDisplay))),
45 | maxX: Math.max(...this.columns.filter(c => c.visible).map(c => c.getMaxX(this.isRangeDisplay))),
46 | minY: 0,
47 | maxY: 100,
48 | }
49 | return {
50 | minX: duration && this.borders ? Telemation.create(this.borders.minX.value, result.minX, 100) : Telemation.create(result.minX),
51 | maxX: duration && this.borders ? Telemation.create(this.borders.maxX.value, result.maxX, 100) : Telemation.create(result.maxX),
52 | minY: duration && this.borders ? Telemation.create(this.borders.minY.value, result.minY, duration) : Telemation.create(result.minY),
53 | maxY: duration && this.borders ? Telemation.create(this.borders.maxY.value, result.maxY, duration) : Telemation.create(result.maxY),
54 | }
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/dist/telechart.css:
--------------------------------------------------------------------------------
1 | .telechart {
2 | position: relative;
3 | font-family: sans-serif;
4 | user-select: none;
5 | -webkit-tap-highlight-color: transparent;
6 | }
7 | .telechart-heading {
8 | margin-bottom: 10px;
9 | display: flex;
10 | position: relative
11 | }
12 | .telechart-heading-title {
13 | font-size: 20px;
14 | font-weight: bold;
15 | }
16 | .telechart-heading-range {
17 | font-size: 14px;
18 | font-weight: bold;
19 | position: absolute;
20 | right: 0;
21 | top: 4px;
22 | opacity: 1;
23 | transition: opacity .1s;
24 | }
25 | .telechart-heading-range.blink {
26 | opacity: .5;
27 | }
28 | .telechart-tip {
29 | background: #fff;
30 | position: absolute;
31 | border: #e3e3e3 1px solid;
32 | box-shadow: 1px 1px 4px rgba(0, 0, 0, .1);
33 | border-radius: 10px;
34 | transition: .1s;
35 | padding: 7px 9px;
36 | white-space: nowrap;
37 | font-size: 13px;
38 | color: #222;
39 | min-width: 130px;
40 | }
41 | .telechart-tip.dark {
42 | background: #222836;
43 | border-color: #202a37;
44 | color: #fff;
45 | }
46 | .telechart-tip table {
47 | width: 100%;
48 | }
49 | .telechart-tip table td {
50 | padding: 0 3px;
51 | }
52 | .telechart-tip table tr:first-child td {
53 | column-span: 2;
54 | font-weight: bold;
55 | }
56 | .telegend {
57 | padding-top: 16px;
58 | }
59 | .telegend-telement {
60 | display: inline-block;
61 | font-size: 15px;
62 | border-radius: 100px;
63 | padding: 8px 18px 10px;
64 | cursor: pointer;
65 | margin: 6px 6px 0 0;
66 | box-sizing: border-box;
67 | position: relative;
68 | font-weight: bold;
69 | border: 2px solid;
70 | line-height: 15px;
71 | }
72 | .telegend-telement.visible {
73 | color: #fff !important;
74 | }
75 | .telegend-telement > * {
76 | position: relative
77 | }
78 | .telegend-element-back {
79 | position: absolute;
80 | left: -2px;
81 | top: -2px;
82 | right: -2px;
83 | bottom: -2px;
84 | box-sizing: border-box;
85 | box-shadow: none;
86 | border-radius: 100px;
87 | transition: box-shadow .5s;
88 | }
89 | .telegend-telement.visible .telegend-element-back {
90 | box-shadow: inset 0 0 20px 20px;
91 | }
92 | .telegend-element-checkbox {
93 | display: inline-block;
94 | margin-left: -6px;
95 | margin-right: -9px;
96 | position: relative;
97 | width: 12px;
98 | height: 5px;
99 | top: -3px;
100 | opacity: 0;
101 | border-bottom: 2.5px solid #fff;
102 | border-left: 2.5px solid #fff;
103 | transform: rotate(0deg);
104 | transition: transform .6s, width .3s, margin .3s, opacity .3s;
105 | }
106 | .telegend-telement.visible .telegend-element-checkbox {
107 | opacity: 1;
108 | width: 12px;
109 | height: 5px;
110 | transform: rotate(-45deg);
111 | margin-right: 6px;
112 | }
113 | .telegend-element-label {
114 | display: inline-block;
115 | vertical-align: top;
116 | }
--------------------------------------------------------------------------------
/src/Teletip.ts:
--------------------------------------------------------------------------------
1 | import { Telechart } from './Telechart'
2 |
3 | export interface ITeletipContent {
4 | title: string,
5 | values: Array<{ name: string, color: string, value: number|string, percentage?: number|string }>,
6 | }
7 |
8 | export class Teletip {
9 | protected readonly element: HTMLDivElement
10 | private themeProperty: 'light'|'dark' = 'light'
11 |
12 | constructor(protected readonly telechart: Telechart, protected parentElement: HTMLElement) {
13 | this.element = parentElement.appendChild(document.createElement('div'))
14 | this.element.classList.add('telechart-tip')
15 | this.theme = telechart.theme
16 | this.hide()
17 | }
18 |
19 | get theme() {
20 | return this.themeProperty
21 | }
22 |
23 | set theme(value) {
24 | this.themeProperty = value
25 | if (value === 'dark') {
26 | this.element.classList.add('dark')
27 | } else {
28 | this.element.classList.remove('dark')
29 | }
30 | }
31 |
32 | public show() {
33 | this.element.style.display = 'block'
34 | }
35 |
36 | public hide() {
37 | this.element.style.display = 'none'
38 | }
39 |
40 | public setCoordinates(value: [number, number]) {
41 | this.element.style.display = 'block'
42 | const width = this.element.offsetWidth
43 | const height = this.element.offsetHeight
44 | const parentWidth = this.parentElement.clientWidth
45 | let top = value[1] - height + 33 /*header height*/ - 15
46 | let left = value[0] - width - 15
47 | if (top < 33) {
48 | top = 33
49 | }
50 | if (left < 0) {
51 | left = value[0] + 15
52 | }
53 | if (left + width > parentWidth) {
54 | left = value[0] - width - 15
55 | }
56 | this.element.style.left = `${left}px`
57 | this.element.style.top = `${top}px`
58 | }
59 |
60 | public setContent(content: ITeletipContent) {
61 | while (this.element.firstChild) {
62 | this.element.removeChild(this.element.firstChild);
63 | }
64 | const table = this.element.appendChild(document.createElement('table'))
65 | const titleRow = table.insertRow()
66 | const titleCell = titleRow.insertCell()
67 | titleCell.innerText = content.title
68 | titleCell.colSpan = content.values[0].percentage ? 3 : 2
69 |
70 | content.values.forEach(val => {
71 | const row = table.insertRow()
72 | if (val.percentage) {
73 | const perc = row.insertCell()
74 | perc.style.textAlign = 'right'
75 | perc.innerHTML = '' + val.percentage + '%'
76 | }
77 | const name = row.insertCell()
78 | const value = row.insertCell()
79 | name.innerText = val.name
80 | value.innerText = String(val.value)
81 | value.style.color = val.color
82 | value.style.fontWeight = 'bold'
83 | value.style.textAlign = 'right'
84 | })
85 | }
86 |
87 | public draw() {/* */}
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/src/Display/AbstractTeledisplay.ts:
--------------------------------------------------------------------------------
1 | import { Telecolumn } from '../Telecolumn'
2 | import { Telechart } from '../Telechart'
3 | import { AbstractChartDrawer } from '../Drawer/AbstractChartDrawer'
4 | import { ITeletipContent } from '../Teletip'
5 |
6 | export abstract class AbstractTeledisplay {
7 | public theme: 'light'|'dark' = 'light'
8 | protected columns: Telecolumn[] = []
9 | protected drawers: AbstractChartDrawer[] = []
10 |
11 | constructor(protected readonly telechart: Telechart) {
12 | this.telechart.telecanvas.addMouseMoveListener(this.onMouseMove.bind(this))
13 | this.theme = telechart.theme
14 | }
15 |
16 | public abstract draw(): void
17 |
18 | get axisColor() {
19 | return this.theme === 'dark' ? '#FFFFFF19' : '#182D3B19'
20 | }
21 |
22 | get axisTextColor() {
23 | return this.theme === 'dark' ? '#A3B1C2' : '#8E8E93'
24 | }
25 |
26 | get lineColor() {
27 | return this.theme === 'dark' ? '#3b4a5a' : '#dfe6eb'
28 | }
29 |
30 | get firstDrawer() {
31 | return this.drawers.length ? this.drawers[0] : undefined
32 | }
33 |
34 | get telecanvas() {
35 | return this.telechart.telecanvas
36 | }
37 |
38 | get height() {
39 | return this.telecanvas.height - this.telechart.telemap.height
40 | }
41 |
42 | public addColumn(column: Telecolumn) {
43 | this.columns.push(column)
44 | }
45 |
46 | public removeColumn(column: Telecolumn) {
47 | this.columns.splice(this.columns.indexOf(column), 1)
48 | this.drawers.forEach(d => d.removeColumn(column))
49 | }
50 |
51 | public recalcBorders(duration: number = 0) {
52 | this.drawers.forEach(d => d.recalcBorders(duration))
53 | this.telechart.redraw()
54 | }
55 |
56 | protected getTeletipContent(currentColumns: Telecolumn[]): ITeletipContent {
57 | const values = currentColumns.map(col => {
58 | return { name: col.name, color: col.color, value: this.telechart.formatNumber(col.currentPoint!.y) }
59 | })
60 |
61 | return { title: this.telechart.getDateString(currentColumns[0]!.currentPoint!.x, 'D, j M Y'), values }
62 | }
63 |
64 | protected updateTeletip() {
65 | const curColumns = this.columns.filter(col => col.currentPoint)
66 | if (curColumns.length) {
67 | const pos = this.firstDrawer!.getCanvasX(curColumns[0]!.currentPoint!.x)
68 | if (pos < 0 || pos > this.telecanvas.width) {
69 | this.telechart.teletip.hide()
70 | } else {
71 | this.telechart.teletip.setContent(this.getTeletipContent(curColumns))
72 | this.telechart.teletip.setCoordinates([
73 | this.firstDrawer!.getCanvasX(curColumns[0]!.currentPoint!.x),
74 | this.firstDrawer!.getCanvasY(Math.max(...curColumns.map(c => c.currentPoint!.y))),
75 | ])
76 | this.telechart.teletip.show()
77 | }
78 | } else {
79 | this.telechart.teletip.hide()
80 | }
81 | }
82 |
83 | protected onMouseMove(x: number, y: number) {
84 | if (!this.drawers.length || !this.firstDrawer || !this.firstDrawer.bordersAnimationFinished) {
85 | return
86 | }
87 | if (x >= 0 && y >= 0 && x < this.telecanvas.width && y < this.height) {
88 | const val = this.firstDrawer.getXValue(x)
89 | if (this.columns.reduce((r, c) => c.setCurrentX(val) || r, false)) {
90 | this.telechart.redraw()
91 | }
92 | }
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/src/Telegend.ts:
--------------------------------------------------------------------------------
1 | import { Telechart } from './Telechart'
2 | import { Telecolumn } from './Telecolumn'
3 |
4 | export class Telegend {
5 | protected columns: Array<{ telecolumn: Telecolumn, element: HTMLElement, onClick: () => void }> = []
6 | protected element: HTMLElement
7 | private themeProperty: 'light'|'dark' = 'light'
8 |
9 | constructor(protected telechart: Telechart, parentElement: HTMLElement) {
10 | this.element = document.createElement('div')
11 | this.element.classList.add('telegend')
12 | parentElement.appendChild(this.element)
13 | }
14 |
15 | get theme() {
16 | return this.themeProperty
17 | }
18 |
19 | set theme(value) {
20 | this.themeProperty = value
21 | this.element.classList.toggle('dark', value === 'dark')
22 | }
23 |
24 | public addColumn(telecolumn: Telecolumn) {
25 | const element = document.createElement('div')
26 | element.classList.add('telegend-telement')
27 | if (telecolumn.visible) {
28 | element.classList.add('visible')
29 | }
30 | element.style.borderColor = telecolumn.color
31 | element.style.color = telecolumn.color
32 | this.element.appendChild(element)
33 |
34 | const back = document.createElement('div')
35 | back.style.color = telecolumn.color
36 | back.classList.add('telegend-element-back')
37 |
38 | const checkbox = document.createElement('div')
39 | checkbox.classList.add('telegend-element-checkbox')
40 |
41 | const label = document.createElement('div')
42 | label.classList.add('telegend-element-label')
43 | label.innerText = telecolumn.name
44 |
45 | element.appendChild(back)
46 | element.appendChild(checkbox)
47 | element.appendChild(label)
48 | let timeout: number|undefined
49 | const onClick = () => {
50 | this.columns.forEach(c => c.telecolumn.setCurrentX(null))
51 | telecolumn.visible = !telecolumn.visible
52 | element.classList.toggle('visible', telecolumn.visible)
53 | this.telechart.teledisplay.recalcBorders(200)
54 | this.telechart.telemap.recalcBorders(200)
55 | this.telechart.redraw()
56 | }
57 | const onDown = () => {
58 | if (timeout) {
59 | return
60 | }
61 | timeout = setTimeout(() => {
62 | timeout = undefined
63 | this.columns.forEach(c => c.telecolumn.visible = true)
64 | telecolumn.visible = false
65 | this.columns.forEach(c => c.onClick())
66 | }, 500)
67 | }
68 | const onUp = () => {
69 | if (timeout) {
70 | clearTimeout(timeout)
71 | timeout = undefined
72 | onClick()
73 | }
74 | }
75 | const onMove = () => {
76 | if (timeout) {
77 | clearTimeout(timeout)
78 | timeout = undefined
79 | }
80 | }
81 | element.addEventListener('touchstart', onDown)
82 | element.addEventListener('mousedown', onDown)
83 | element.addEventListener('mouseup', onUp)
84 | element.addEventListener('touchmove', onMove)
85 | element.addEventListener('mousemove', onMove)
86 | this.columns.push({ telecolumn, element, onClick })
87 | }
88 |
89 | public removeColumn(column: Telecolumn) {
90 | this.columns.forEach((c, i) => {
91 | if (c.telecolumn === column) {
92 | this.element.removeChild(c.element)
93 | this.columns.splice(i, 1)
94 | }
95 | })
96 | }
97 |
98 | public draw() {/**/}
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Telechart Example
7 |
8 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | Download sources
78 | Switch to Night Mode
79 |
80 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/src/Telecolumn.ts:
--------------------------------------------------------------------------------
1 | import { Telechart } from './Telechart'
2 | import { Telemation } from './Telemation'
3 |
4 | export interface ITelechartColumnData {
5 | id: string
6 | name: string
7 | values: Array<{ x: number, y: number}>
8 | color: string
9 | }
10 |
11 | export class Telecolumn {
12 | public readonly id: string|number
13 | public readonly name: string
14 | public readonly color: string
15 | public readonly values: Array<{ x: number, y: number}>
16 | public opacity: Telemation
17 | public current: { x: number, y: number }|null = null
18 | public config!: { background: string }
19 | private visibleProperty = true
20 | private readonly telechart: Telechart
21 | private currentRange: { from: number, to: number }|null = null
22 | private themeProperty: 'light'|'dark' = 'light'
23 |
24 | constructor(telechart: Telechart, data: ITelechartColumnData) {
25 | this.telechart = telechart
26 | this.id = data.id
27 | this.name = data.name
28 | this.values = data.values
29 | this.color = data.color
30 | this.theme = telechart.theme
31 | this.opacity = this.visible ? Telemation.create(1) : Telemation.create(0)
32 | }
33 |
34 | get theme() {
35 | return this.themeProperty
36 | }
37 |
38 | set theme(value) {
39 | this.themeProperty = value
40 | if (value === 'dark') {
41 | this.config = {
42 | ...this.config,
43 | background: '#242f3e',
44 | }
45 | } else {
46 | this.config = {
47 | ...this.config,
48 | background: '#fff',
49 | }
50 | }
51 | }
52 |
53 | get visible() {
54 | return this.visibleProperty
55 | }
56 |
57 | set visible(value: boolean) {
58 | if (value !== this.visibleProperty) {
59 | this.visibleProperty = value
60 | this.opacity = value ? Telemation.create(0, 1, 200) : Telemation.create(1, 0, 200)
61 | }
62 | }
63 |
64 | get currentValues() {
65 | return this.currentRange ? this.values.filter(v => v.x >= this.currentRange!.from && v.x <= this.currentRange!.to) : []
66 | }
67 |
68 | public getMinX(inCurrentRange = false): number {
69 | if (inCurrentRange && this.currentRange) {
70 | return this.currentRange.from
71 | }
72 | const result = this.values.reduce((res: number|null, val) => {
73 | return res === null ? val.x : Math.min(res, val.x)
74 | }, null)
75 | return result ? result : 0
76 | }
77 |
78 | public getMaxX(inCurrentRange = false): number {
79 | if (inCurrentRange && this.currentRange) {
80 | return this.currentRange.to
81 | }
82 | const result = this.values.reduce((res: number|null, val) => {
83 | return res === null ? val.x : Math.max(res, val.x)
84 | }, null)
85 | return result ? result : 0
86 | }
87 |
88 | public getMinY(inCurrentRange = false): number {
89 | const values = inCurrentRange && this.currentRange ? this.currentValues : this.values
90 | const result = values.reduce((res: number|null, val) => {
91 | return res === null ? val.y : Math.min(res, val.y)
92 | }, null)
93 | return result ? result : 0
94 | }
95 |
96 | public getMaxY(inCurrentRange = false): number {
97 | const values = inCurrentRange && this.currentRange ? this.currentValues : this.values
98 | const result = values.reduce((res: number|null, val) => {
99 | return res === null ? val.y : Math.max(res, val.y)
100 | }, null)
101 | return result ? result : 0
102 | }
103 |
104 | public setCurrentX(value: number|null) {
105 | const oldValue = this.current
106 | if (value === null) {
107 | this.current = null
108 | } else {
109 | const currentValues = this.currentValues
110 | if (!currentValues) {
111 | return
112 | }
113 | let min: { val: number, index: number }|null = null
114 | for (let n = 0, length = currentValues.length; n < length; n++) {
115 | const v = currentValues[n]
116 | if (!min) {
117 | min = { val: v.x, index: n }
118 | }
119 | if (Math.abs(v.x - value) < min.val) {
120 | min = { val: Math.abs(v.x - value), index: n }
121 | }
122 | }
123 | if (min!) {
124 | this.current = currentValues[min!.index]
125 | }
126 | }
127 | if (this.current !== oldValue) {
128 | return true
129 | }
130 | }
131 |
132 | get currentPoint(): { x: number, y: number }|null {
133 | return this.current
134 | }
135 |
136 | public setCurrentRange(from: number, to: number) {
137 | this.currentRange = { from, to }
138 | }
139 |
140 | }
141 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Basic Options */
4 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
5 | "module": "es6", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
6 | // "lib": [], /* Specify library files to be included in the compilation. */
7 | "allowJs": false, /* Allow javascript files to be compiled. */
8 | // "checkJs": true, /* Report errors in .js files. */
9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */
11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
12 | "sourceMap": true, /* Generates corresponding '.map' file. */
13 | // "outFile": "./dist/telechart.js", /* Concatenate and emit output to single file. */
14 | "outDir": "./dist", /* Redirect output structure to the directory. */
15 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
16 | // "composite": true, /* Enable project compilation */
17 | // "removeComments": true, /* Do not emit comments to output. */
18 | // "noEmit": true, /* Do not emit outputs. */
19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */
20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
22 |
23 | /* Strict Type-Checking Options */
24 | "strict": true, /* Enable all strict type-checking options. */
25 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
26 | // "strictNullChecks": true, /* Enable strict null checks. */
27 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */
28 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
29 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
30 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
31 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
32 |
33 | /* Additional Checks */
34 | // "noUnusedLocals": true, /* Report errors on unused locals. */
35 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
36 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
37 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
38 |
39 | /* Module Resolution Options */
40 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
41 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
42 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
43 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
44 | // "typeRoots": [], /* List of folders to include type definitions from. */
45 | // "types": [], /* Type declaration files to be included in compilation. */
46 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
47 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
48 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
49 |
50 | /* Source Map Options */
51 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
52 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
53 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
54 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
55 |
56 | /* Experimental Options */
57 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
58 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
59 | }
60 | }
--------------------------------------------------------------------------------
/src/Drawer/StackedChartDrawer.ts:
--------------------------------------------------------------------------------
1 | import { Telecolumn } from '../Telecolumn'
2 | import { Telemation } from '../Telemation'
3 | import { Telechart } from '../Telechart'
4 | import { AbstractChartDrawer, IAbstractChartDrawerOptions } from './AbstractChartDrawer'
5 |
6 | interface IStackedChartDrawerOptions extends IAbstractChartDrawerOptions {
7 | noCurrent?: boolean
8 | rectangle?: boolean
9 | }
10 |
11 | export class StackedChartDrawer extends AbstractChartDrawer {
12 | public valuesLength = 0
13 | public noCurrent: boolean
14 | public rectangle: boolean
15 |
16 | constructor(telechart: Telechart, options?: IStackedChartDrawerOptions) {
17 | super(telechart, options)
18 | this.noCurrent = options && options.noCurrent ? true : false
19 | this.rectangle = options && options.rectangle ? true : false
20 | }
21 |
22 | get currentPoint() {
23 | if (!this.noCurrent && this.columns.length && this.columns[0].currentPoint) {
24 | return this.columns[0].currentPoint.x
25 | }
26 | }
27 |
28 | public drawColumns() {
29 | let prev: number[]|undefined
30 | const borders = { minX: this.borders.minX.value, maxX: this.borders.maxX.value, minY: 0, maxY: this.borders.maxY.value }
31 | for (const col of this.columns) {
32 | let result
33 | if (this.rectangle) {
34 | result = this.drawColumn(col, prev, borders)
35 | } else {
36 | result = this.drawValues(col, this.getInDisplayColumnValues(col, [borders.minX, borders.maxX]),
37 | [borders.minX, borders.maxX], prev,
38 | )
39 | }
40 | if (result && !prev) {
41 | prev = result
42 | } else if (result) {
43 | for (let n = result.length - 1; n >= 0; n--) {
44 | prev![n] = prev![n] + result[n]
45 | }
46 | }
47 | }
48 | if (!this.borders.maxX.finished || !this.borders.maxY.finished) {
49 | this.telechart.redraw()
50 | }
51 | }
52 |
53 | public drawColumn(column: Telecolumn, prev?: number[], borders?: { minX: number, maxX: number, minY: number, maxY: number }): number[]|undefined {
54 | if (!column.opacity.value) {
55 | return
56 | }
57 | const c = this.telecanvas
58 | const horBorders = borders ? [borders.minX, borders.maxX] as [number, number] : undefined
59 | const verBorders = borders ? [borders.minY, borders.maxY] as [number, number] : undefined
60 | const allVals = this.getInDisplayColumnValues(column, horBorders)
61 | if (allVals.length) {
62 | const currentPoint = this.currentPoint
63 | const colOpacityVal = column.opacity.value
64 | let opacity = Math.round((currentPoint ? .5 : 1) * 255).toString(16)
65 | if (opacity.length === 1) {
66 | opacity = '0' + opacity
67 | }
68 | const result: number[] = []
69 | const path: Array<[number, number]> = []
70 | const valsPrep: Array<{ x: number, y: number, height: number }> = []
71 | let current: Array<[number, number]>|undefined
72 | this.valuesLength = allVals.length
73 | for (let n = 0; n < allVals.length; n++) {
74 | const x = this.getCanvasX(allVals[n].x, horBorders)
75 | const ySt = this.getCanvasY(0)
76 | let height = ySt - this.getCanvasY(allVals[n].y, verBorders)
77 | if (colOpacityVal < 1) {
78 | height *= colOpacityVal
79 | }
80 | const y = ySt - height - (prev ? prev[n] : 0)
81 | if (colOpacityVal === 1 && height < 2) {
82 | height = 2
83 | }
84 | if (n) {
85 | path[path.length - 1][0] = x
86 | }
87 | path.push([x, y])
88 | path.push([x, y])
89 | valsPrep.push({ x, y, height })
90 | result.push(height)
91 | if (allVals[n].x === currentPoint) {
92 | current = [[x, y], [n + 1 < allVals.length ? this.getCanvasX(allVals[n + 1].x, horBorders) : x + 30, y]]
93 | current.push([current[current.length - 1][0], y + height])
94 | current.push([x, y + height])
95 | }
96 | }
97 | for (let n = valsPrep.length - 1; n >= 0; n--) {
98 | path.push([path[n * 2 + 1][0], valsPrep[n].y + valsPrep[n].height])
99 | path.push([path[n * 2][0], valsPrep[n].y + valsPrep[n].height])
100 | }
101 | c.shape(path, column.color + opacity)
102 | if (current) {
103 | c.shape(current, column.color)
104 | }
105 | if (!column.opacity.finished) {
106 | this.telechart.redraw()
107 | }
108 | return result
109 | }
110 | }
111 |
112 | public drawValues(column: Telecolumn, values: Array<{ x: number, y: number }>, borders: [number, number], prev?: number[]) {
113 | const c = this.telecanvas
114 | if (values.length) {
115 | const colOpacityVal = column.opacity.value
116 | const result: number[] = []
117 | const path: Array<[number, number]> = []
118 | const valsPrep: Array<{ x: number, y: number, height: number }> = []
119 | this.valuesLength = values.length
120 | for (let n = 0; n < values.length; n++) {
121 | const x = this.getCanvasX(values[n].x, borders)
122 | const ySt = this.getCanvasY(0)
123 | let height = ySt - this.getCanvasY(values[n].y)
124 | if (colOpacityVal < 1) {
125 | height *= colOpacityVal
126 | }
127 | const y = ySt - height - (prev ? prev[n] : 0)
128 | if (colOpacityVal === 1 && height < 2) {
129 | height = 2
130 | }
131 | path.push([x, y])
132 | valsPrep.push({ x, y, height })
133 | result.push(height)
134 | }
135 | for (let n = valsPrep.length - 1; n >= 0; n--) {
136 | path.push([path[n][0], valsPrep[n].y + valsPrep[n].height])
137 | }
138 | c.shape(path, column.color)
139 | if (!column.opacity.finished) {
140 | this.telechart.redraw()
141 | }
142 | return result
143 | }
144 | }
145 |
146 | protected getNewBorders(duration?: number) {
147 | const result = {
148 | minX: Math.min(...this.columns.filter(c => c.visible).map(c => c.getMinX(this.isRangeDisplay))),
149 | maxX: Math.max(...this.columns.filter(c => c.visible).map(c => c.getMaxX(this.isRangeDisplay))),
150 | minY: 0,
151 | maxY: this.columns.filter(c => c.visible).map(c => c.getMaxY(this.isRangeDisplay)).reduce((r, v) => r + v, 0),
152 | }
153 | return {
154 | minX: duration && this.borders ? Telemation.create(this.borders.minX.value, result.minX, 100) : Telemation.create(result.minX),
155 | maxX: duration && this.borders ? Telemation.create(this.borders.maxX.value, result.maxX, 100) : Telemation.create(result.maxX),
156 | minY: Telemation.create(result.minY),
157 | maxY: duration && this.borders ? Telemation.create(this.borders.maxY.value, result.maxY, duration) : Telemation.create(result.maxY),
158 | }
159 | }
160 |
161 | }
162 |
--------------------------------------------------------------------------------
/dist/data/4/overview.json:
--------------------------------------------------------------------------------
1 | {"columns":[["x",1523059200000,1523145600000,1523232000000,1523318400000,1523404800000,1523491200000,1523577600000,1523664000000,1523750400000,1523836800000,1523923200000,1524009600000,1524096000000,1524182400000,1524268800000,1524355200000,1524441600000,1524528000000,1524614400000,1524700800000,1524787200000,1524873600000,1524960000000,1525046400000,1525132800000,1525219200000,1525305600000,1525392000000,1525478400000,1525564800000,1525651200000,1525737600000,1525824000000,1525910400000,1525996800000,1526083200000,1526169600000,1526256000000,1526342400000,1526428800000,1526515200000,1526601600000,1526688000000,1526774400000,1526860800000,1526947200000,1527033600000,1527120000000,1527206400000,1527292800000,1527379200000,1527465600000,1527552000000,1527638400000,1527724800000,1527811200000,1527897600000,1527984000000,1528070400000,1528156800000,1528243200000,1528329600000,1528416000000,1528502400000,1528588800000,1528675200000,1528761600000,1528848000000,1528934400000,1529020800000,1529107200000,1529193600000,1529280000000,1529366400000,1529452800000,1529539200000,1529625600000,1529712000000,1529798400000,1529884800000,1529971200000,1530057600000,1530144000000,1530230400000,1530316800000,1530403200000,1530489600000,1530576000000,1530662400000,1530748800000,1530835200000,1530921600000,1531008000000,1531094400000,1531180800000,1531267200000,1531353600000,1531440000000,1531526400000,1531612800000,1531699200000,1531785600000,1531872000000,1531958400000,1532044800000,1532131200000,1532217600000,1532304000000,1532390400000,1532476800000,1532563200000,1532649600000,1532736000000,1532822400000,1532908800000,1532995200000,1533081600000,1533168000000,1533254400000,1533340800000,1533427200000,1533513600000,1533600000000,1533686400000,1533772800000,1533859200000,1533945600000,1534032000000,1534118400000,1534204800000,1534291200000,1534377600000,1534464000000,1534550400000,1534636800000,1534723200000,1534809600000,1534896000000,1534982400000,1535068800000,1535155200000,1535241600000,1535328000000,1535414400000,1535500800000,1535587200000,1535673600000,1535760000000,1535846400000,1535932800000,1536019200000,1536105600000,1536192000000,1536278400000,1536364800000,1536451200000,1536537600000,1536624000000,1536710400000,1536796800000,1536883200000,1536969600000,1537056000000,1537142400000,1537228800000,1537315200000,1537401600000,1537488000000,1537574400000,1537660800000,1537747200000,1537833600000,1537920000000,1538006400000,1538092800000,1538179200000,1538265600000,1538352000000,1538438400000,1538524800000,1538611200000,1538697600000,1538784000000,1538870400000,1538956800000,1539043200000,1539129600000,1539216000000,1539302400000,1539388800000,1539475200000,1539561600000,1539648000000,1539734400000,1539820800000,1539907200000,1539993600000,1540080000000,1540166400000,1540252800000,1540339200000,1540425600000,1540512000000,1540598400000,1540684800000,1540771200000,1540857600000,1540944000000,1541030400000,1541116800000,1541203200000,1541289600000,1541376000000,1541462400000,1541548800000,1541635200000,1541721600000,1541808000000,1541894400000,1541980800000,1542067200000,1542153600000,1542240000000,1542326400000,1542412800000,1542499200000,1542585600000,1542672000000,1542758400000,1542844800000,1542931200000,1543017600000,1543104000000,1543190400000,1543276800000,1543363200000,1543449600000,1543536000000,1543622400000,1543708800000,1543795200000,1543881600000,1543968000000,1544054400000,1544140800000,1544227200000,1544313600000,1544400000000,1544486400000,1544572800000,1544659200000,1544745600000,1544832000000,1544918400000,1545004800000,1545091200000,1545177600000,1545264000000,1545350400000,1545436800000,1545523200000,1545609600000,1545696000000,1545782400000,1545868800000,1545955200000,1546041600000,1546128000000,1546214400000,1546300800000,1546387200000,1546473600000,1546560000000,1546646400000,1546732800000,1546819200000,1546905600000,1546992000000,1547078400000,1547164800000,1547251200000,1547337600000,1547424000000,1547510400000,1547596800000,1547683200000,1547769600000,1547856000000,1547942400000,1548028800000,1548115200000,1548201600000,1548288000000,1548374400000,1548460800000,1548547200000,1548633600000,1548720000000,1548806400000,1548892800000,1548979200000,1549065600000,1549152000000,1549238400000,1549324800000,1549411200000,1549497600000,1549584000000,1549670400000,1549756800000,1549843200000,1549929600000,1550016000000,1550102400000,1550188800000,1550275200000,1550361600000,1550448000000,1550534400000,1550620800000,1550707200000,1550793600000,1550880000000,1550966400000,1551052800000,1551139200000,1551225600000,1551312000000,1551398400000,1551484800000,1551571200000,1551657600000,1551744000000,1551830400000,1551916800000,1552003200000,1552089600000,1552176000000,1552262400000,1552348800000,1552435200000,1552521600000,1552608000000,1552694400000,1552780800000,1552867200000,1552953600000,1553040000000,1553126400000,1553212800000,1553299200000,1553385600000,1553472000000,1553558400000,1553644800000,1553731200000,1553817600000,1553904000000,1553990400000,1554076800000,1554163200000,1554249600000,1554336000000,1554422400000,1554508800000],["y0",30600800,31327000,35296200,36671400,38742200,39538200,40365200,42177400,41253800,42994000,41398800,42850400,43624400,44164400,43575200,42069200,42733200,40369800,40467800,43160200,47773400,46834200,43145800,64329200,38156800,36229800,34755800,36527000,33582800,31686200,32552000,30499600,29413400,30605200,29920600,27942600,26974600,24874400,24546600,24789000,25654200,26277000,24491600,24444600,24416600,24593400,25214400,24817200,25938600,25223200,23816000,23189200,22654200,22579000,22185600,23108800,22146600,19930200,22292000,19980600,21812600,19632600,21635800,20944800,20299200,20543000,20725800,20119400,20247600,17315200,19133200,19691000,20111200,19735400,17922600,18467200,19467400,18115600,19175200,17285400,18604800,18150200,18689400,19497800,19688800,20074200,19243000,20180600,19962400,19130800,19464800,20429200,20254600,21029800,20104400,19559400,18572400,19560800,20320200,20534000,20865800,20705000,20326600,19589400,20039800,20672000,20448600,20431400,20203000,19807800,19114600,19737000,20446400,19984200,19013000,21106600,18543800,16215800,16996600,16285200,16812800,18398000,17487600,19092400,18394000,18933000,19541600,19880800,20069600,19929800,18914400,18397600,18944200,20357400,19935200,19857200,19392000,18742600,18331000,18930400,19992400,19907600,20189800,19738000,18392200,17742200,18294600,19626800,19650000,20076800,20142200,19624800,18711200,19298400,20398200,20290600,20346200,21254200,20288000,19139800,19492200,19611800,19389000,18652400,17296600,16267200,17129200,21290200,19845000,19130600,19087400,18704600,19270000,19601800,20168800,18454200,18388800,18521200,18595400,18921800,18961600,20607400,18806000,18761800,18780400,19312600,19751200,20555800,21416400,11018800,19735000,19565600,19622600,20178400,20873400,21822600,20152400,20210000,20094000,19408600,20045200,21272800,22675200,20556600,20628800,20193800,23418000,21550800,22184600,23645000,21168000,21156400,20624600,20763600,22816400,22499400,22984000,19503000,19126800,18676000,18452400,18917800,19860600,21129200,18835600,18816400,18739400,19215600,18999000,19278200,21011000,20021200,21848400,19470600,18784200,18774400,19653200,21242600,18834800,18868800,18462200,18098000,18211600,19367800,20742800,18762000,18738000,18249600,18001600,18234400,19228200,20551600,19084200,19204600,19331800,19235600,18789800,19783000,20253000,20858800,20679600,20483200,20695800,20676000,21407600,23004600,22544800,22397600,22540600,22594800,22962600,23580800,23441600,23028200,23179200,23496800,22729200,23086200,22961000,23396400,22557200,22907400,23239000,22632800,22261200,23621600,24424200,23286600,22865400,22802600,22799400,22745400,22599800,24371000,23400200,24004200,24141000,23751000,22954000,22941400,23675000,23115600,23478800,22618800,22171600,21867600,22016200,22925600,24285600,23554800,25214800,22918800,22629200,23121600,24037200,22052600,21490000,20981000,21275000,21153200,21562000,22737000,20606400,20894400,20349200,20001800,20993600,21822600,23157400,20812400,20631600,20920000,20787600,20625600,21468200,23499200,21612800,21550000,21703600,21410600,22272400,22455600,23961000,22611600,23301400,22674600,21071000,24589200,23748400,22198400,21311200,22167400,23862400,23883200,22336800,21860800,21619000,21934000,23330600,23336400,19579600,22230200,22727600,22706600,21370000]],"types":{"y0":"bar","x":"x"},"names":{"y0":"Views"},"colors":{"y0":"#64ADED"}}
--------------------------------------------------------------------------------
/dist/data/1/overview.json:
--------------------------------------------------------------------------------
1 | {"columns":[["x",1523059200000,1523145600000,1523232000000,1523318400000,1523404800000,1523491200000,1523577600000,1523664000000,1523750400000,1523836800000,1523923200000,1524009600000,1524096000000,1524182400000,1524268800000,1524355200000,1524441600000,1524528000000,1524614400000,1524700800000,1524787200000,1524873600000,1524960000000,1525046400000,1525132800000,1525219200000,1525305600000,1525392000000,1525478400000,1525564800000,1525651200000,1525737600000,1525824000000,1525910400000,1525996800000,1526083200000,1526169600000,1526256000000,1526342400000,1526428800000,1526515200000,1526601600000,1526688000000,1526774400000,1526860800000,1526947200000,1527033600000,1527120000000,1527206400000,1527292800000,1527379200000,1527465600000,1527552000000,1527638400000,1527724800000,1527811200000,1527897600000,1527984000000,1528070400000,1528156800000,1528243200000,1528329600000,1528416000000,1528502400000,1528588800000,1528675200000,1528761600000,1528848000000,1528934400000,1529020800000,1529107200000,1529193600000,1529280000000,1529366400000,1529452800000,1529539200000,1529625600000,1529712000000,1529798400000,1529884800000,1529971200000,1530057600000,1530144000000,1530230400000,1530316800000,1530403200000,1530489600000,1530576000000,1530662400000,1530748800000,1530835200000,1530921600000,1531008000000,1531094400000,1531180800000,1531267200000,1531353600000,1531440000000,1531526400000,1531612800000,1531699200000,1531785600000,1531872000000,1531958400000,1532044800000,1532131200000,1532217600000,1532304000000,1532390400000,1532476800000,1532563200000,1532649600000,1532736000000,1532822400000,1532908800000,1532995200000,1533081600000,1533168000000,1533254400000,1533340800000,1533427200000,1533513600000,1533600000000,1533686400000,1533772800000,1533859200000,1533945600000,1534032000000,1534118400000,1534204800000,1534291200000,1534377600000,1534464000000,1534550400000,1534636800000,1534723200000,1534809600000,1534896000000,1534982400000,1535068800000,1535155200000,1535241600000,1535328000000,1535414400000,1535500800000,1535587200000,1535673600000,1535760000000,1535846400000,1535932800000,1536019200000,1536105600000,1536192000000,1536278400000,1536364800000,1536451200000,1536537600000,1536624000000,1536710400000,1536796800000,1536883200000,1536969600000,1537056000000,1537142400000,1537228800000,1537315200000,1537401600000,1537488000000,1537574400000,1537660800000,1537747200000,1537833600000,1537920000000,1538006400000,1538092800000,1538179200000,1538265600000,1538352000000,1538438400000,1538524800000,1538611200000,1538697600000,1538784000000,1538870400000,1538956800000,1539043200000,1539129600000,1539216000000,1539302400000,1539388800000,1539475200000,1539561600000,1539648000000,1539734400000,1539820800000,1539907200000,1539993600000,1540080000000,1540166400000,1540252800000,1540339200000,1540425600000,1540512000000,1540598400000,1540684800000,1540771200000,1540857600000,1540944000000,1541030400000,1541116800000,1541203200000,1541289600000,1541376000000,1541462400000,1541548800000,1541635200000,1541721600000,1541808000000,1541894400000,1541980800000,1542067200000,1542153600000,1542240000000,1542326400000,1542412800000,1542499200000,1542585600000,1542672000000,1542758400000,1542844800000,1542931200000,1543017600000,1543104000000,1543190400000,1543276800000,1543363200000,1543449600000,1543536000000,1543622400000,1543708800000,1543795200000,1543881600000,1543968000000,1544054400000,1544140800000,1544227200000,1544313600000,1544400000000,1544486400000,1544572800000,1544659200000,1544745600000,1544832000000,1544918400000,1545004800000,1545091200000,1545177600000,1545264000000,1545350400000,1545436800000,1545523200000,1545609600000,1545696000000,1545782400000,1545868800000,1545955200000,1546041600000,1546128000000,1546214400000,1546300800000,1546387200000,1546473600000,1546560000000,1546646400000,1546732800000,1546819200000,1546905600000,1546992000000,1547078400000,1547164800000,1547251200000,1547337600000,1547424000000,1547510400000,1547596800000,1547683200000,1547769600000,1547856000000,1547942400000,1548028800000,1548115200000,1548201600000,1548288000000,1548374400000,1548460800000,1548547200000,1548633600000,1548720000000,1548806400000,1548892800000,1548979200000,1549065600000,1549152000000,1549238400000,1549324800000,1549411200000,1549497600000,1549584000000,1549670400000,1549756800000,1549843200000,1549929600000,1550016000000,1550102400000,1550188800000,1550275200000,1550361600000,1550448000000,1550534400000,1550620800000,1550707200000,1550793600000,1550880000000,1550966400000,1551052800000,1551139200000,1551225600000,1551312000000,1551398400000,1551484800000,1551571200000,1551657600000,1551744000000,1551830400000,1551916800000,1552003200000,1552089600000,1552176000000,1552262400000,1552348800000,1552435200000,1552521600000,1552608000000,1552694400000,1552780800000,1552867200000,1552953600000,1553040000000,1553126400000,1553212800000,1553299200000,1553385600000,1553472000000,1553558400000,1553644800000,1553731200000,1553817600000,1553904000000,1553990400000,1554076800000,1554163200000,1554249600000,1554336000000,1554422400000,1554508800000],["y0",930,890,900,980,1120,1250,1220,1030,960,1390,1300,1200,1030,880,1820,1680,1190,1320,1790,1610,1210,1170,1300,1080,1320,1200,970,760,1230,1250,1040,1020,1300,1290,970,900,1050,1040,980,1070,1410,1080,1000,1100,1070,1010,940,1160,1110,990,1070,830,940,1070,1160,1040,1020,1120,1210,3030,2530,1660,1170,1240,1180,1000,1170,720,1010,1300,1020,1180,1080,960,1050,880,950,970,1360,1020,1280,1140,1150,1100,1100,1260,1280,1540,1360,1250,1060,1330,930,1060,940,1190,1320,1180,1050,1210,1370,1330,950,1270,1130,1300,1170,1530,1110,1380,1240,1390,1150,1230,1340,1160,1140,1380,1690,1460,1240,1610,1320,1360,1320,1460,1450,1330,1080,1720,1600,1250,1570,1530,1610,1860,1450,1560,1690,1560,1730,1600,2170,1540,1940,1430,1410,1840,1790,1850,1620,1520,2190,1870,1550,2080,1560,1720,2040,1810,1890,2000,1900,2270,2060,1890,1930,1590,2030,1890,1810,1620,1690,1310,1700,1530,1970,2080,1620,1510,1990,1720,1750,1870,1740,1620,1840,1980,1910,1790,2080,1820,1530,2140,2440,2130,2430,2180,2080,2190,2090,1910,2440,1940,2680,3310,2510,2200,3020,2550,2450,2800,2450,2780,3020,2680,2210,2550,3160,2870,2690,3140,2820,2850,2160,2540,3050,2720,2540,3000,2630,2660,2780,2350,2510,2980,2650,2770,2220,3000,2950,2450,2610,2270,2200,2200,2920,2600,2470,2180,2480,2400,2450,2970,2830,2740,2680,2750,2200,2720,2270,3100,3510,3400,2920,2240,2330,2660,3400,3240,2940,3300,3760,3270,3460,3340,2820,2300,2830,2690,2760,2570,2420,2730,2480,3000,3260,2920,2750,2660,3130,3480,2530,3140,2200,2970,2900,2510,2500,2660,2970,2810,3200,2640,2790,3360,2690,2750,2810,3090,3080,2490,2810,2570,2630,2370,3320,2610,2300,2670,2470,2680,3270,3580,3000,2670,2540,2740,2940,2800,3590,3000,3130,3030,2460,2400,2610,3240,4010,2880,2930,2890,3240,2600,3530,2850,3580,3480,3210,3150,2730,3240,2720,3210,3090,3310,2670,2750,2540,2600,2930,3400,3050,3480,2930],["y1",1060,990,1140,1090,1210,1160,1450,970,1400,1140,1230,1440,1660,1130,1390,1410,1110,1060,1100,1340,1140,1340,980,1390,1190,1350,1390,1230,1280,1250,1360,1470,1540,1170,1500,1330,1330,1190,1280,1370,1460,1160,1490,1300,1240,1370,1330,1360,1780,1470,1300,1390,1420,1450,1520,1270,1180,1270,1440,1470,1500,1440,1710,1460,1390,1510,1510,1730,1630,1440,1690,1480,1340,1550,1410,1470,1380,1550,1280,1550,1500,1350,1280,1270,1430,1330,1190,1380,1790,1610,1240,1520,1120,1250,1040,1370,1140,1650,1840,1320,1860,1490,1680,1920,1190,1410,1180,1510,1490,1950,1700,1060,1630,1410,1230,1340,1640,1620,1610,1780,1320,1430,1510,1410,1660,1610,1320,1420,1360,1330,1300,1370,1590,1380,1580,1250,1460,1740,2250,1820,1670,1590,1710,1630,1770,1410,2100,1640,1670,1560,1820,1580,1560,1680,1520,1660,1570,1790,1560,1850,1670,2050,1660,1690,2110,1900,2280,1680,1770,2250,1910,2190,2070,2160,1810,1890,2130,2470,2150,2320,2420,2510,2390,2340,2260,2250,2250,2560,2090,1620,2340,2410,2270,2470,2360,2520,2380,2690,2590,2600,3010,2970,2480,2680,2910,2960,3150,3290,2380,2860,3130,2680,2980,3030,2900,3570,3340,2970,2910,3130,3180,3370,3590,3380,3720,3670,3480,3470,3770,3400,3060,3080,3090,3380,3040,3080,3410,3620,3320,2890,3570,3260,3100,3450,3490,3070,2640,3360,3260,3030,3250,3690,2950,2910,3540,3140,3090,3350,2960,2930,2940,3280,3080,2750,3370,3740,2550,2340,3290,2800,2910,3160,3200,3640,2910,2930,2830,3230,3190,2930,3090,2530,2760,2990,2700,3130,3140,3020,2790,2820,3400,3360,3100,3470,2560,3030,3340,3240,3540,3310,3300,3040,2870,2960,3140,2960,3130,2910,3140,2380,3080,3100,2910,2700,3020,2590,2790,2880,3390,3190,3130,3320,2480,2850,3070,3030,2750,3190,3130,2960,3060,2810,2810,2980,3130,3150,2990,2310,2690,3070,3670,3530,2890,2510,2890,3090,2930,2850,3260,3720,2460,2610,3280,2860,3240,3420,2920,2280,2840,3030,3370,2650,3200,3190,2590]],"types":{"y0":"line","y1":"line","x":"x"},"names":{"y0":"Joined","y1":"Left"},"colors":{"y0":"#4BD964","y1":"#FE3C30"}}
--------------------------------------------------------------------------------
/dist/data/2/overview.json:
--------------------------------------------------------------------------------
1 | {"columns":[["x",1523059200000,1523145600000,1523232000000,1523318400000,1523404800000,1523491200000,1523577600000,1523664000000,1523750400000,1523836800000,1523923200000,1524009600000,1524096000000,1524182400000,1524268800000,1524355200000,1524441600000,1524528000000,1524614400000,1524700800000,1524787200000,1524873600000,1524960000000,1525046400000,1525132800000,1525219200000,1525305600000,1525392000000,1525478400000,1525564800000,1525651200000,1525737600000,1525824000000,1525910400000,1525996800000,1526083200000,1526169600000,1526256000000,1526342400000,1526428800000,1526515200000,1526601600000,1526688000000,1526774400000,1526860800000,1526947200000,1527033600000,1527120000000,1527206400000,1527292800000,1527379200000,1527465600000,1527552000000,1527638400000,1527724800000,1527811200000,1527897600000,1527984000000,1528070400000,1528156800000,1528243200000,1528329600000,1528416000000,1528502400000,1528588800000,1528675200000,1528761600000,1528848000000,1528934400000,1529020800000,1529107200000,1529193600000,1529280000000,1529366400000,1529452800000,1529539200000,1529625600000,1529712000000,1529798400000,1529884800000,1529971200000,1530057600000,1530144000000,1530230400000,1530316800000,1530403200000,1530489600000,1530576000000,1530662400000,1530748800000,1530835200000,1530921600000,1531008000000,1531094400000,1531180800000,1531267200000,1531353600000,1531440000000,1531526400000,1531612800000,1531699200000,1531785600000,1531872000000,1531958400000,1532044800000,1532131200000,1532217600000,1532304000000,1532390400000,1532476800000,1532563200000,1532649600000,1532736000000,1532822400000,1532908800000,1532995200000,1533081600000,1533168000000,1533254400000,1533340800000,1533427200000,1533513600000,1533600000000,1533686400000,1533772800000,1533859200000,1533945600000,1534032000000,1534118400000,1534204800000,1534291200000,1534377600000,1534464000000,1534550400000,1534636800000,1534723200000,1534809600000,1534896000000,1534982400000,1535068800000,1535155200000,1535241600000,1535328000000,1535414400000,1535500800000,1535587200000,1535673600000,1535760000000,1535846400000,1535932800000,1536019200000,1536105600000,1536192000000,1536278400000,1536364800000,1536451200000,1536537600000,1536624000000,1536710400000,1536796800000,1536883200000,1536969600000,1537056000000,1537142400000,1537228800000,1537315200000,1537401600000,1537488000000,1537574400000,1537660800000,1537747200000,1537833600000,1537920000000,1538006400000,1538092800000,1538179200000,1538265600000,1538352000000,1538438400000,1538524800000,1538611200000,1538697600000,1538784000000,1538870400000,1538956800000,1539043200000,1539129600000,1539216000000,1539302400000,1539388800000,1539475200000,1539561600000,1539648000000,1539734400000,1539820800000,1539907200000,1539993600000,1540080000000,1540166400000,1540252800000,1540339200000,1540425600000,1540512000000,1540598400000,1540684800000,1540771200000,1540857600000,1540944000000,1541030400000,1541116800000,1541203200000,1541289600000,1541376000000,1541462400000,1541548800000,1541635200000,1541721600000,1541808000000,1541894400000,1541980800000,1542067200000,1542153600000,1542240000000,1542326400000,1542412800000,1542499200000,1542585600000,1542672000000,1542758400000,1542844800000,1542931200000,1543017600000,1543104000000,1543190400000,1543276800000,1543363200000,1543449600000,1543536000000,1543622400000,1543708800000,1543795200000,1543881600000,1543968000000,1544054400000,1544140800000,1544227200000,1544313600000,1544400000000,1544486400000,1544572800000,1544659200000,1544745600000,1544832000000,1544918400000,1545004800000,1545091200000,1545177600000,1545264000000,1545350400000,1545436800000,1545523200000,1545609600000,1545696000000,1545782400000,1545868800000,1545955200000,1546041600000,1546128000000,1546214400000,1546300800000,1546387200000,1546473600000,1546560000000,1546646400000,1546732800000,1546819200000,1546905600000,1546992000000,1547078400000,1547164800000,1547251200000,1547337600000,1547424000000,1547510400000,1547596800000,1547683200000,1547769600000,1547856000000,1547942400000,1548028800000,1548115200000,1548201600000,1548288000000,1548374400000,1548460800000,1548547200000,1548633600000,1548720000000,1548806400000,1548892800000,1548979200000,1549065600000,1549152000000,1549238400000,1549324800000,1549411200000,1549497600000,1549584000000,1549670400000,1549756800000,1549843200000,1549929600000,1550016000000,1550102400000,1550188800000,1550275200000,1550361600000,1550448000000,1550534400000,1550620800000,1550707200000,1550793600000,1550880000000,1550966400000,1551052800000,1551139200000,1551225600000,1551312000000,1551398400000,1551484800000,1551571200000,1551657600000,1551744000000,1551830400000,1551916800000,1552003200000,1552089600000,1552176000000,1552262400000,1552348800000,1552435200000,1552521600000,1552608000000,1552694400000,1552780800000,1552867200000,1552953600000,1553040000000,1553126400000,1553212800000,1553299200000,1553385600000,1553472000000,1553558400000,1553644800000,1553731200000,1553817600000,1553904000000,1553990400000,1554076800000,1554163200000,1554249600000,1554336000000,1554422400000,1554508800000],["y0",272400,311800,339600,335800,335800,328800,317600,299600,337200,366400,350200,349800,354400,348400,324200,329000,356200,356200,329000,352400,343800,308400,261400,364400,333600,380000,353600,345400,320200,355000,354400,365000,349200,353000,339200,320200,335800,381400,357000,355200,354800,332800,320600,329400,365800,363400,365000,361600,345200,300800,344200,370800,360200,362600,349400,357800,294800,349000,372200,368200,365600,365600,357000,320200,329800,383600,383600,382200,363000,361200,329200,351000,381400,364200,394600,372200,363000,335400,361800,379600,389000,382000,389000,370400,326000,363200,406400,392200,368400,398200,367200,326200,335600,386800,386000,378600,378800,387400,341600,349000,404600,379800,388600,393600,385200,345400,371600,419600,399800,422000,410800,410200,381200,380400,442600,457800,453000,459200,457200,411000,428600,465800,451000,459800,484600,461200,427000,421800,481800,466600,402400,477800,466600,467200,457200,517000,493000,482600,504400,505600,478800,491400,518800,520800,508800,522800,531400,492400,508400,557800,564200,528000,555200,537600,480400,520600,551000,566000,531000,531200,519400,499000,495000,553800,578000,553200,554800,532400,501800,540600,567600,567600,563000,542400,566600,486800,538400,621200,580800,574200,597200,584000,522200,589600,622800,623800,627800,595200,576000,366000,592200,655600,660000,640000,639600,638400,590800,675600,746600,708400,710400,722400,708600,632200,764400,840200,810200,667000,766800,766000,740400,850800,858400,857400,851800,851800,821000,757600,851400,883000,883600,879800,852800,804800,730600,805800,864000,844800,834800,838800,809200,722800,843800,894000,820400,819000,810000,793400,737600,818000,866800,830600,845000,819200,760000,728400,793200,830000,837600,811400,823400,752800,696400,770600,844800,823000,793400,812000,769400,723200,755600,764600,811200,826200,866800,833000,755000,770600,649800,740400,836800,833600,859000,796000,834800,858400,809000,853000,801400,763600,713600,799200,819200,818000,781800,809200,736600,689800,802400,828600,794200,813000,788400,755200,689200,777800,811200,766000,809400,776800,759000,684800,807400,830800,802800,786000,751800,745000,666400,773200,795200,743600,739200,714000,727600,654000,717000,751600,739600,757600,730600,705200,674400,730800,767000,751600,776600,712000,688000,637800,686000,748600,750200,765400,742400,701000,636800,720400,779000,765200,851200,793000,731400,651200,734800,825400,790800,763400,724200,723600,625800,714600,803600,742600,738000,745800,706600,613600,712000,767400,750800,821200,813400,757800,683800],["y1",12360,16240,14210,14040,15190,13570,14020,15600,16080,15800,16740,15680,16790,15520,17410,17660,17000,15080,17190,17020,16620,15200,13210,16970,16030,16090,16800,15280,15450,15990,17130,14970,16020,15780,15770,15720,16210,15820,16080,14860,14210,14980,16200,15430,15510,16750,16460,15130,15120,15580,18040,16380,15940,16590,15950,15480,14940,16520,16570,15910,15950,16280,17120,15720,16600,17580,16260,17270,15660,16500,16410,17140,16240,17330,16320,17490,17220,17030,19130,17440,17350,17010,19050,16150,16350,18280,17670,19690,17470,16320,16180,16290,15440,16600,17430,17800,18110,16870,17200,16700,18010,18110,17850,17600,17870,18100,17300,19960,18340,19650,19710,21300,18930,20090,20240,21150,21020,21940,22350,22160,20800,22390,21450,22970,20690,23410,21490,21690,20650,22440,21630,23420,22860,23490,24460,23610,23810,22840,23540,24800,23460,24140,25050,23910,23790,23190,23390,23160,23830,23680,25940,23420,23330,23630,23400,26230,22690,24700,22010,23050,22460,24620,24960,26180,24540,24240,24690,24140,25140,29410,25900,25880,24600,25380,25090,24930,28930,26570,25270,26560,25520,27150,25130,25600,28580,25800,25500,27870,26320,18930,30390,27640,27790,28380,29230,28160,28490,31290,31710,32150,29840,29860,30240,30750,33300,34750,33250,31920,36940,36930,33360,38500,33700,34630,36580,36130,34960,35210,37600,37100,34640,36840,36150,33850,32800,35440,37510,36770,35560,35460,36650,35370,36990,39810,39340,36350,35350,33160,34440,36720,35200,37240,36030,36330,34940,34840,39350,37370,34040,33510,35270,32940,33310,34730,35760,37300,35190,33420,32550,33450,34360,41660,42960,38970,37080,37150,36460,41330,34220,34980,34840,39150,38110,35380,38760,36080,33790,36150,35960,32570,33180,36000,36390,33950,35390,36680,36540,31270,34720,35030,37090,38120,32870,34800,35000,34370,35070,35430,36830,37380,35390,33170,37300,34710,36450,37500,37820,31590,34370,37430,36650,35300,35520,35830,35650,32070,38700,34460,34450,32720,34900,35680,33340,37500,35730,35270,37150,35010,35260,33690,40330,36410,35540,35600,35480,37740,35600,44060,34610,37160,37880,36800,37940,35140,36900,40490,37740,36330,37730,35330,35800,39580,37590,35770,36430,36720,36860,33580,36830,35830,36600,37840,39450,35390,35310]],"types":{"y0":"line","y1":"line","x":"x"},"names":{"y0":"Views","y1":"Shares"},"colors":{"y0":"#108BE3","y1":"#E8AF14"},"y_scaled":true}
--------------------------------------------------------------------------------
/src/Telecanvas.ts:
--------------------------------------------------------------------------------
1 | type Coordinate = [number, number]
2 | type MouseMoveListener = (x: number, y: number) => void
3 |
4 | export class Telecanvas {
5 | private widthProperty!: number
6 | private mouseMoveListeners: MouseMoveListener[] = []
7 | private mouseDownListeners: Array<(x: number, y: number) => void> = []
8 | private mouseUpListeners: Array<() => void> = []
9 | private resizeListeners: Array<() => void> = []
10 | private canvas: HTMLCanvasElement
11 | private context: CanvasRenderingContext2D
12 | private cachedDpr?: number
13 |
14 | constructor(parentElement: HTMLElement|null, public height: number, width?: number) {
15 | this.canvas = document.createElement('canvas')
16 | if (parentElement) {
17 | parentElement.appendChild(this.canvas)
18 | this.canvas.style.display = 'block'
19 | } else {
20 | document.body.appendChild(this.canvas)
21 | this.canvas.style.display = 'none'
22 | }
23 | this.context = this.canvas.getContext('2d')!
24 | if (!width) {
25 | window.addEventListener('resize', () => {
26 | if (this.width !== (width ? width : parentElement!.clientWidth)) {
27 | this.canvas.height = height * this.dpr
28 | this.canvas.style.height = `${height}px`
29 | this.width = width ? width : parentElement!.clientWidth
30 | this.resizeListeners.forEach(l => l())
31 | }
32 | })
33 | window.dispatchEvent(new Event('resize'))
34 | } else {
35 | this.width = width
36 | }
37 |
38 | const mousemove = (x: number, y: number) => {
39 | const rect = this.canvas.getBoundingClientRect()
40 | this.mouseMoveListeners.forEach(callback => callback(x - rect.left, y - rect.top))
41 | }
42 | const mousedown = (x: number, y: number) => {
43 | const rect = this.canvas.getBoundingClientRect()
44 | this.mouseDownListeners.forEach(callback => callback(x - rect.left, y - rect.top))
45 | }
46 | window.addEventListener('mousemove', (e) => mousemove(e.clientX, e.clientY))
47 | window.addEventListener('touchmove', (e) => mousemove(e.touches[0].clientX, e.touches[0].clientY))
48 | this.canvas.addEventListener('mousedown', (e) => mousedown(e.clientX, e.clientY))
49 | this.canvas.addEventListener('touchstart', (e) => mousedown(e.touches[0].clientX, e.touches[0].clientY))
50 | window.addEventListener('mouseup', () => this.mouseUpListeners.forEach(callback => callback()))
51 | window.addEventListener('touchend', () => this.mouseUpListeners.forEach(callback => callback()))
52 | }
53 |
54 | get width() {
55 | return this.widthProperty
56 | }
57 |
58 | set width(value: number) {
59 | this.cachedDpr = undefined
60 | this.widthProperty = value
61 | this.canvas.width = value * this.dpr
62 | this.canvas.style.width = `100%`
63 | this.context.scale(this.dpr, this.dpr)
64 | }
65 |
66 | get dpr() {
67 | return this.cachedDpr ? this.cachedDpr : window.devicePixelRatio || 1
68 | }
69 |
70 | set cursor(value: string) {
71 | this.canvas.style.cursor = value
72 | }
73 |
74 | public save() {
75 | this.context.save()
76 | }
77 |
78 | public setRoundedClippingRect(left: number, top: number, width: number, height: number, radius: number) {
79 | const c = this.context
80 | c.beginPath()
81 | c.moveTo(left + radius, top)
82 | c.lineTo(left + width - radius, top)
83 | c.quadraticCurveTo(left + width, top, left + width, top + radius)
84 | c.lineTo(left + width, top + height - radius)
85 | c.quadraticCurveTo(left + width, top + height, left + width - radius, top + height)
86 | c.lineTo(left + radius, top + height)
87 | c.quadraticCurveTo(left, top + height, left, top + height - radius)
88 | c.lineTo(left, top + radius)
89 | c.quadraticCurveTo(left, top, left + radius, top)
90 | c.closePath()
91 | c.clip()
92 | }
93 |
94 | public setClippingRect(left: number, top: number, width: number, height: number) {
95 | const c = this.context
96 | c.beginPath()
97 | c.rect(left, top, width, height)
98 | c.closePath()
99 | c.clip()
100 | }
101 |
102 | public restore() {
103 | this.context.restore()
104 | }
105 |
106 | public line(from: Coordinate, to: Coordinate, color: string, width = 1) {
107 | const c = this.context
108 | c.lineCap = 'butt'
109 | c.strokeStyle = color
110 | c.lineWidth = width
111 | c.beginPath()
112 | c.moveTo(from[0] + .5, from[1] + .5)
113 | c.lineTo(to[0] + .5, to[1] + .5)
114 | c.stroke()
115 | }
116 |
117 | public path(path: Array<[number, number]>, color: string, width = 1) {
118 | const c = this.context
119 | c.lineJoin = 'miter'
120 | c.miterLimit = 2
121 | c.strokeStyle = color
122 | c.lineWidth = width
123 | c.beginPath()
124 | c.moveTo(path[0][0], path[0][1])
125 | for (let n = 1; n < path.length; n++) {
126 | c.lineTo(path[n][0], path[n][1])
127 | }
128 | c.stroke()
129 | }
130 |
131 | public circle(point: [number, number], radius: number, stroke: string|null, fill: string|null, borderWidth: number = 1) {
132 | const c = this.context
133 | c.beginPath()
134 | c.arc(point[0], point[1], radius, 0, 2 * Math.PI)
135 | if (fill) {
136 | c.fillStyle = fill
137 | c.fill()
138 | }
139 | if (stroke) {
140 | c.strokeStyle = stroke
141 | c.lineWidth = borderWidth
142 | c.stroke()
143 | }
144 | }
145 |
146 | public text(text: string, to: Coordinate, color: string, fontFamily = 'sans-serif', size = 14, align: 'left'|'right'|'center'|'start'|'end' = 'left') {
147 | const c = this.context
148 | c.fillStyle = color
149 | c.font = `${size}px "${fontFamily}"`
150 | c.textAlign = align
151 | c.fillText(text, to[0], to[1])
152 | }
153 |
154 | public shape(path: Array<[number, number]>, color: string) {
155 | const c = this.context
156 | c.fillStyle = color
157 | c.beginPath()
158 | c.moveTo(path[0][0], path[0][1])
159 | for (let n = 1; n < path.length; n++) {
160 | c.lineTo(path[n][0], path[n][1])
161 | }
162 | c.closePath()
163 | c.fill()
164 | }
165 |
166 | public rect(left: number, top: number, width: number, height: number, fill?: string, stroke?: string, borderWidth?: number) {
167 | const c = this.context
168 | c.beginPath()
169 | if (fill) {
170 | c.fillStyle = fill
171 | c.fillRect(left, top, width, height)
172 | }
173 | if (stroke) {
174 | c.strokeStyle = stroke
175 | c.lineWidth = borderWidth!
176 | c.strokeRect(left, top, width, height)
177 | }
178 | }
179 |
180 | public roundedRect(left: number, top: number, width: number, height: number, radius: number, fill?: string, stroke?: string, borderWidth?: number) {
181 | const c = this.context
182 | c.beginPath()
183 | c.moveTo(left + radius, top)
184 | c.lineTo(left + width - radius, top)
185 | c.quadraticCurveTo(left + width, top, left + width, top + radius)
186 | c.lineTo(left + width, top + height - radius)
187 | c.quadraticCurveTo(left + width, top + height, left + width - radius, top + height)
188 | c.lineTo(left + radius, top + height)
189 | c.quadraticCurveTo(left, top + height, left, top + height - radius)
190 | c.lineTo(left, top + radius)
191 | c.quadraticCurveTo(left, top, left + radius, top)
192 | c.closePath()
193 | if (fill) {
194 | c.fillStyle = fill
195 | c.fill()
196 | }
197 | if (stroke) {
198 | c.strokeStyle = stroke
199 | c.lineWidth = borderWidth!
200 | c.stroke()
201 | }
202 | }
203 |
204 | public drawTelecanvas(telecanvas: Telecanvas, destX: number, destY: number) {
205 | this.context.resetTransform()
206 | this.context.drawImage(telecanvas.canvas, destX * this.dpr, destY * this.dpr)
207 | if (this.dpr > 1) {
208 | this.context.scale(this.dpr, this.dpr)
209 | }
210 | }
211 |
212 | public getOpacityValue(color: string) {
213 | return color.length === 9 ? parseInt(color.substr(7, 2), 16) / 255 : 1
214 | }
215 |
216 | public getColorString(baseColor: string, opacity: number) {
217 | const opacityPart = Math.round(this.getOpacityValue(baseColor) * opacity * 255).toString(16)
218 | return baseColor.substr(0, 7) + (opacityPart.length === 1 ? '0' + opacityPart : opacityPart)
219 | }
220 |
221 | public clear() {
222 | this.context.clearRect(0, 0, this.width, this.height)
223 | }
224 |
225 | public addMouseMoveListener(callback: (x: number, y: number) => void) {
226 | this.mouseMoveListeners.push(callback)
227 | }
228 |
229 | public addMouseDownListener(callback: (x: number, y: number) => void) {
230 | this.mouseDownListeners.push(callback)
231 | }
232 |
233 | public addMouseUpListener(callback: () => void) {
234 | this.mouseUpListeners.push(callback)
235 | }
236 |
237 | public addResizeListener(callback: () => void) {
238 | this.resizeListeners.push(callback)
239 | }
240 |
241 | }
242 |
--------------------------------------------------------------------------------
/src/Telemap/AbstractTelemap.ts:
--------------------------------------------------------------------------------
1 | import { Telechart } from '../Telechart'
2 | import { AbstractChartDrawer } from '../Drawer/AbstractChartDrawer'
3 | import { Telecolumn } from '../Telecolumn'
4 | import { Telecanvas } from '../Telecanvas'
5 | import { Telemation } from '../Telemation'
6 |
7 | export abstract class AbstractTelemap {
8 | protected config!: { rangeBackground: string, rangeFill: string, shadow: string }
9 | protected rangeProperty: { from: Telemation, to: Telemation }|null = null
10 | protected topPadding = 0
11 | protected bottomPadding = 0
12 | protected cacheTeelcanvas: Telecanvas
13 | protected telecanvasCached = false
14 | protected columns: Telecolumn[] = []
15 | protected drawers: AbstractChartDrawer[] = []
16 | private themeProperty: 'light'|'dark' = 'light'
17 |
18 | constructor(protected readonly telechart: Telechart, public height = 44) {
19 | this.theme = telechart.theme
20 | this.topPadding = this.telecanvas.height - height
21 | this.initHTML()
22 | this.cacheTeelcanvas = new Telecanvas(null, this.height - 2, this.telecanvas.width)
23 | this.telecanvas.addResizeListener(() => {
24 | this.cacheTeelcanvas.width = this.telecanvas.width
25 | this.telecanvasCached = false
26 | })
27 | }
28 |
29 | get telecanvas() {
30 | return this.telechart.telecanvas
31 | }
32 |
33 | get firstDrawer() {
34 | return this.drawers.length ? this.drawers[0] : undefined
35 | }
36 |
37 | public addColumn(column: Telecolumn) {
38 | this.columns.push(column)
39 | }
40 |
41 | public removeColumn(column: Telecolumn) {
42 | this.columns.splice(this.columns.indexOf(column), 1)
43 | this.drawers.forEach(d => d.removeColumn(column))
44 | }
45 |
46 | get theme() {
47 | return this.themeProperty
48 | }
49 |
50 | set theme(value) {
51 | this.themeProperty = value
52 | if (value === 'dark') {
53 | this.config = {
54 | ...this.config,
55 | rangeBackground: '#56626D',
56 | rangeFill: '#242f3e',
57 | shadow: '#30425999',
58 | }
59 | } else {
60 | this.config = {
61 | ...this.config,
62 | rangeBackground: '#C0D1E1',
63 | rangeFill: '#fff',
64 | shadow: '#E2EEF999',
65 | }
66 | }
67 | }
68 |
69 | set range(value: { from: number, to: number }|null) {
70 | const current = this.range
71 | this.rangeProperty = {
72 | from: Telemation.create(current ? current.from : 0, value!.from, current ? 50 : 0),
73 | to: Telemation.create(current ? current.to : 0, value!.to, current ? 50 : 0),
74 | }
75 | if (!this.firstDrawer) {
76 | return
77 | }
78 | this.columns.forEach((c, index) => {
79 | const from = this.firstDrawer!.borders.minX.to + (this.firstDrawer!.borders.maxX.to - this.firstDrawer!.borders.minX.to) * value!.from
80 | const to = this.firstDrawer!.borders.minX.to + (this.firstDrawer!.borders.maxX.to - this.firstDrawer!.borders.minX.to) * value!.to
81 | if (!index) {
82 | this.telechart.setRangeText(this.telechart.getDateString(from) + ' - ' + this.telechart.getDateString(to))
83 | }
84 | c.setCurrentRange(from, to)
85 | })
86 | this.telechart.teledisplay.recalcBorders(current ? 200 : 0)
87 | }
88 |
89 | get range(): { from: number, to: number }|null {
90 | return this.rangeProperty ? { from: this.rangeProperty!.from.value, to: this.rangeProperty!.to.value } : null
91 | }
92 |
93 | public draw() {
94 | const c = this.telecanvas
95 | const left = this.range!.from * this.telecanvas.width
96 | const width = (this.range!.to - this.range!.from) * this.telecanvas.width
97 |
98 | if (this.columns.reduce((r, col) => !col.opacity.finished || r, false) || !this.firstDrawer!.borders.maxY.finished) {
99 | this.telecanvasCached = false
100 | }
101 | if (!this.telecanvasCached) {
102 | this.cacheTeelcanvas.clear()
103 | this.drawColumns()
104 | this.cacheTeelcanvas.drawTelecanvas(this.telecanvas, 0, -this.topPadding - 1)
105 | this.telecanvasCached = true
106 | c.clear()
107 | }
108 | c.save()
109 | c.setRoundedClippingRect(0, this.topPadding + 1, c.width, this.height - 2, 6)
110 | c.drawTelecanvas(this.cacheTeelcanvas, 0, this.topPadding + 1)
111 |
112 | c.rect(0, this.topPadding + 1, left + 6, this.height - 2, this.config.shadow) // Shadow to left
113 | c.rect(left + width - 6, this.topPadding + 1, this.telecanvas.width - left - width + 6, this.height - 2, this.config.shadow) // Shadow to right
114 |
115 | c.restore()
116 |
117 | c.roundedRect(left, this.topPadding, 10, this.height, 6, this.config.rangeBackground) // Left gripper corners
118 | c.rect(left + 5, this.topPadding, 5, this.height, this.config.rangeBackground) // Left gripper rect
119 | c.roundedRect(left + 4, this.topPadding + 15, 2, 12, 2, this.config.rangeFill) // Left gripper strip
120 |
121 | c.roundedRect(left + width - 10, this.topPadding, 10, this.height, 6, this.config.rangeBackground) // Right gripper corners
122 | c.rect(left + width - 10, this.topPadding, 5, this.height, this.config.rangeBackground) // Right gripper rect
123 | c.roundedRect(left + width - 6, this.topPadding + 15, 2, 12, 2, this.config.rangeFill) // Right gripper strip
124 |
125 | c.line([left + 10 - 1, this.topPadding], [left + width - 10 + 1, this.topPadding], this.config.rangeBackground)
126 | c.line([left + 10 - 1, this.topPadding + this.height - 1], [left + width - 10 + 1, this.topPadding + this.height - 1], this.config.rangeBackground)
127 |
128 | if (!this.rangeProperty!.to.finished) {
129 | this.telechart.redraw()
130 | }
131 | }
132 |
133 | public recalcBorders(duration: number = 0) {
134 | this.drawers.forEach(d => d.recalcBorders(duration))
135 | this.telechart.redraw()
136 | }
137 |
138 | protected abstract drawColumns(): void
139 |
140 | protected initHTML() {
141 | let currentPos = { left: 0, top: 0 }
142 | let startRange: { from: number, to: number }|null = null
143 | let startPos: { left: number, top: number }|null = null
144 | let moveType: 'all'|'from'|'to'|null = null
145 | let yInArea = false
146 | const mousemove = (x: number, y: number) => {
147 | currentPos = { left: x, top: y }
148 | yInArea = y >= this.topPadding && y < this.topPadding + this.height
149 |
150 | if (!startPos || !startRange) {
151 | if (yInArea) {
152 | const left = this.range!.from * this.telecanvas.width
153 | const width = (this.range!.to - this.range!.from) * this.telecanvas.width
154 | if (x >= left - 5 && x <= left + 20) {
155 | moveType = 'from'
156 | this.telecanvas.cursor = 'ew-resize'
157 | } else if (x >= left + width - 15 && x < left + width + 5) {
158 | moveType = 'to'
159 | this.telecanvas.cursor = 'ew-resize'
160 | } else if (x >= left && x < left + width) {
161 | moveType = 'all'
162 | this.telecanvas.cursor = 'move'
163 | } else {
164 | moveType = null
165 | this.telecanvas.cursor = 'default'
166 | }
167 | } else {
168 | this.telecanvas.cursor = 'default'
169 | }
170 | return
171 | }
172 | this.columns.forEach(c => c.setCurrentX(null))
173 | const diff = (currentPos.left - startPos!.left) / this.telecanvas.width
174 | let newRangeFrom = startRange!.from
175 | let newRangeTo = startRange!.to
176 | if (moveType === 'all' || moveType === 'from') {
177 | newRangeFrom += diff
178 | }
179 | if (moveType === 'all' || moveType === 'to') {
180 | newRangeTo += diff
181 | }
182 | if (newRangeFrom < 0) {
183 | if (moveType === 'all' || moveType === 'to') {
184 | newRangeTo = newRangeTo - newRangeFrom
185 | }
186 | newRangeFrom = 0
187 | }
188 | if (newRangeTo > 1) {
189 | if (moveType === 'all' || moveType === 'from') {
190 | newRangeFrom = newRangeFrom - (newRangeTo - 1)
191 | }
192 | newRangeTo = 1
193 | }
194 | if (newRangeTo - newRangeFrom < 0.1) {
195 | if (moveType === 'to') {
196 | newRangeTo = newRangeFrom + 0.1
197 | } else {
198 | newRangeFrom = newRangeTo - 0.1
199 | }
200 | }
201 | this.range = { from: newRangeFrom, to: newRangeTo }
202 | }
203 | const mousedown = (x: number, y: number) => {
204 | if (moveType) {
205 | startPos = { ...currentPos }
206 | startRange = { ...this.range! }
207 | }
208 | }
209 | const mouseup = () => {
210 | moveType = null
211 | startPos = null
212 | startRange = null
213 | }
214 | this.telecanvas.addMouseMoveListener(mousemove)
215 | this.telecanvas.addMouseDownListener((x, y) => {
216 | mousemove(x, y)
217 | mousedown(x, y)
218 | })
219 | this.telecanvas.addMouseUpListener(mouseup)
220 | }
221 |
222 | }
223 |
--------------------------------------------------------------------------------
/src/Telechart.ts:
--------------------------------------------------------------------------------
1 | import { Telecolumn, ITelechartColumnData } from './Telecolumn'
2 | import { Telecanvas } from './Telecanvas'
3 | import { AbstractTeledisplay } from './Display/AbstractTeledisplay'
4 | import { Teletip } from './Teletip'
5 | import { AbstractTelemap } from './Telemap/AbstractTelemap'
6 | import { Telegend } from './Telegend'
7 | import { LineTeledisplay } from './Display/LineTeledisplay'
8 | import { TwoAxisTeledisplay } from './Display/TwoAxisTeledisplay'
9 | import { LineTelemap } from './Telemap/LineTelemap'
10 | import { TwoAxisTelemap } from './Telemap/TwoAxisTelemap'
11 | import { StackedTeledisplay } from './Display/StackedTeledisplay'
12 | import { StackedTelemap } from './Telemap/StackedTelemap'
13 | import { StackedPercentTeledisplay } from './Display/StackedPercentTeledisplay'
14 | import { StackedPercentTelemap } from './Telemap/StackedPercentTelemap'
15 |
16 | interface ITelechartData {
17 | columns: Array>
18 | types: { [key: string]: 'line'|'bar'|'x' }
19 | names: { [key: string]: string }
20 | colors: { [key: string]: string }
21 | y_scaled?: boolean
22 | stacked?: boolean
23 | percentage?: boolean
24 | }
25 | interface ITelechartOptions {
26 | data: ITelechartData
27 | height?: number
28 | title?: string
29 | showFps?: boolean
30 | allRange?: boolean
31 | }
32 |
33 | export class Telechart {
34 | public static init(el: HTMLElement|string, options: ITelechartOptions) {
35 | let element: HTMLElement|null
36 | if (typeof el === 'string' || el instanceof String) {
37 | element = document.getElementById(el as string)
38 | if (!element) {
39 | throw new Error(`Element #${el} not found`)
40 | }
41 | } else if (el instanceof HTMLElement) {
42 | element = el
43 | }
44 |
45 | return new Telechart(element!, options)
46 | }
47 |
48 | public telecanvas!: Telecanvas
49 | public teledisplay!: AbstractTeledisplay
50 | public teletip!: Teletip
51 | public telemap!: AbstractTelemap
52 | public telegend!: Telegend
53 | protected config!: {
54 | data: ITelechartData,
55 | height: number,
56 | title: string,
57 | showFps: boolean,
58 | allRange: boolean,
59 | }
60 | protected loaded = false
61 | protected columns: Telecolumn[] = []
62 | protected canvas!: HTMLCanvasElement
63 | protected needRedraw = false
64 | protected headingElement!: HTMLDivElement
65 | protected rangeElement?: HTMLDivElement
66 | private themeProperty: 'light'|'dark' = 'light'
67 |
68 | constructor(protected readonly element: HTMLElement, options: ITelechartOptions) {
69 | if (!element) {
70 | throw new Error('HTML element for Telechart is not found')
71 | }
72 | if (!(element instanceof HTMLElement)) {
73 | throw new Error('First argument of Telechart constructor must be an HTMLElement')
74 | }
75 | this.config = {
76 | data: options.data,
77 | height: options.height ? options.height : 360,
78 | title: options.title ? options.title : 'Untitled chart',
79 | showFps: options.showFps ? true : false,
80 | allRange: options.allRange ? true : false,
81 | }
82 | this.initHTML()
83 | this.updateData(options.data ? options.data : { columns: [], types: {}, names: {}, colors: {}, y_scaled: false })
84 | this.redraw()
85 | }
86 |
87 | get data() {
88 | return this.config.data
89 | }
90 |
91 | set data(value) {
92 | this.config.data = value
93 | this.updateData(value)
94 | }
95 |
96 | get theme() {
97 | return this.themeProperty
98 | }
99 |
100 | set theme(value) {
101 | this.themeProperty = value
102 | this.teletip.theme = value
103 | this.teledisplay.theme = value
104 | this.telemap.theme = value
105 | this.telegend.theme = value
106 | this.columns.forEach(c => c.theme = value)
107 | this.redraw()
108 | }
109 |
110 | public setRangeText(value: string) {
111 | if (!this.rangeElement) {
112 | this.rangeElement = this.headingElement.appendChild(document.createElement('div'))
113 | this.rangeElement.classList.add('telechart-heading-range')
114 | }
115 | this.rangeElement.innerText = value
116 | }
117 |
118 | public addColumn(data: ITelechartColumnData) {
119 | const column = new Telecolumn(this, data)
120 | this.columns.push(column)
121 | this.teledisplay.addColumn(column)
122 | this.telemap.addColumn(column)
123 | this.telegend.addColumn(column)
124 | }
125 |
126 | public removeColumn(id: string|number) {
127 | for (let n = this.columns.length - 1; n >= 0; n--) {
128 | const c = this.columns[n]
129 | if (c.id === id) {
130 | this.removeTelecolumn(c)
131 | return
132 | }
133 | }
134 | }
135 |
136 | public removeTelecolumn(column: Telecolumn) {
137 | if (this.teledisplay) {
138 | this.teledisplay.removeColumn(column)
139 | }
140 | if (this.telemap) {
141 | this.telemap.removeColumn(column)
142 | }
143 | this.telegend.removeColumn(column)
144 | this.columns.splice(this.columns.indexOf(column), 1)
145 | this.redraw()
146 | }
147 |
148 | public removeColumns() {
149 | for (let n = this.columns.length - 1; n >= 0; n--) {
150 | this.removeTelecolumn(this.columns[n])
151 | }
152 | }
153 |
154 | public redraw() {
155 | this.needRedraw = true
156 | }
157 |
158 | public updateData(data: ITelechartData) {
159 | let x: number[]
160 | let hasBar = false
161 | this.removeColumns()
162 |
163 | for (const key in data.types) {
164 | if (data.types[key] === 'bar') {
165 | hasBar = true
166 | break
167 | }
168 | }
169 |
170 | if (data.stacked || hasBar) {
171 | if (data.percentage) {
172 | this.telemap = new StackedPercentTelemap(this)
173 | this.teledisplay = new StackedPercentTeledisplay(this)
174 | } else {
175 | this.telemap = new StackedTelemap(this)
176 | this.teledisplay = new StackedTeledisplay(this)
177 | }
178 | } else if (data.y_scaled) {
179 | this.telemap = new TwoAxisTelemap(this)
180 | this.teledisplay = new TwoAxisTeledisplay(this)
181 | } else {
182 | this.telemap = new LineTelemap(this)
183 | this.teledisplay = new LineTeledisplay(this)
184 | }
185 | for (const col of data.columns) {
186 | const id = col[0] as string
187 | const row: number[] = []
188 | for (let n = 1; n < col.length; n++) {
189 | row.push(col[n] as number)
190 | }
191 | if (data.types[id] === 'x') {
192 | x = row
193 | continue
194 | }
195 | const values = row.reduce((result, val, i) => {
196 | if (x[i] === undefined) {
197 | throw new Error('Incorrect input data')
198 | }
199 | result.push({ x: x[i], y: val })
200 |
201 | return result
202 | }, [] as Array<{ x: number, y: number}>)
203 | this.addColumn({ id, name: data.names[id], color: data.colors[id], values })
204 | }
205 | this.telemap.range = this.config.allRange ? { from: 0, to: 1 } : { from: .8, to: 1 }
206 | this.loaded = true
207 | window.dispatchEvent(new Event('resize'))
208 | }
209 |
210 | public getDateString(timestamp: number, format: string = 'j F Y') {
211 | const date = new Date(timestamp)
212 | let result = ''
213 | for (const c of format.split('')) {
214 | let a = c
215 | if (c === 'j') {
216 | a = date.getDate().toString()
217 | } else if (c === 'F') {
218 | a = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'][date.getMonth()]
219 | } else if (c === 'Y') {
220 | a = date.getFullYear().toString()
221 | } else if (c === 'M') {
222 | a = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][date.getMonth()]
223 | } else if (c === 'D') {
224 | a = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][date.getDay()]
225 | }
226 | result += a
227 | }
228 | return result
229 | }
230 |
231 | public formatNumber(value: number): string {
232 | let result = ''
233 | value.toString(10).split('').reverse().forEach((n, i) => {
234 | if (i % 3 === 0) {
235 | result = ' ' + result
236 | }
237 | result = n + result
238 | })
239 | return result
240 | }
241 |
242 | protected initHTML() {
243 | this.element.classList.add('telechart')
244 | const heading = this.headingElement = this.element.appendChild(document.createElement('div'))
245 | heading.classList.add('telechart-heading')
246 | const title = heading.appendChild(document.createElement('div'))
247 | title.classList.add('telechart-heading-title')
248 | title.innerText = this.config.title
249 |
250 | this.telecanvas = new Telecanvas(this.element, this.config.height!)
251 | this.teletip = new Teletip(this, this.element)
252 | this.telegend = new Telegend(this, this.element)
253 |
254 | this.telecanvas.addResizeListener(() => this.redraw())
255 |
256 | let frames = 0
257 | let start = Date.now()
258 | let fps = 60
259 | const draw = () => {
260 | const needRedraw = this.needRedraw
261 | if (this.needRedraw) {
262 | this.draw()
263 | }
264 | frames++
265 | if (frames % 30 === 0) {
266 | fps = 1 / ((Date.now() - start) / 1000 / 30)
267 | start = Date.now()
268 | }
269 | if (this.config.showFps && (needRedraw || frames % 10 === 0)) {
270 | this.telecanvas.rect(2, 2, 30, 10, '#fff')
271 | this.telecanvas.text('fps ' + fps.toFixed(0), [3, 10], '#000', 'sans', 9)
272 | }
273 | window.requestAnimationFrame(draw)
274 | }
275 | window.requestAnimationFrame(draw)
276 | }
277 |
278 | protected draw() {
279 | if (!this.loaded) {
280 | return
281 | }
282 | this.needRedraw = false
283 | this.telecanvas.clear()
284 | this.telemap.draw()
285 | this.teledisplay.draw()
286 | this.teletip.draw()
287 | this.telegend.draw()
288 | }
289 |
290 | }
291 |
--------------------------------------------------------------------------------
/src/Drawer/AbstractChartDrawer.ts:
--------------------------------------------------------------------------------
1 | import { Telechart } from '../Telechart'
2 | import { Telecolumn } from '../Telecolumn'
3 | import { Telemation } from '../Telemation'
4 |
5 | export interface IBorders {
6 | maxX: Telemation,
7 | maxY: Telemation,
8 | minX: Telemation,
9 | minY: Telemation,
10 | }
11 |
12 | export interface IAbstractChartDrawerOptions {
13 | isRangeDisplay?: boolean
14 | isZeroStart?: boolean
15 | noGuides?: boolean
16 | noMilestones?: boolean
17 | topPadding?: number
18 | bottomPadding?: number
19 | }
20 |
21 | export abstract class AbstractChartDrawer {
22 | public isRangeDisplay = false
23 | public isZeroStart = false
24 | public topPadding: number = 0
25 | public bottomPadding: number = 0
26 | public borders!: IBorders
27 | public noGuides: boolean
28 | public noMilestones: boolean
29 | protected guidesCount = 6
30 | protected milestones: Array<{ x: number, title: string|null }> = []
31 | protected guides: Array<{ y: number, title: string, opacity: Telemation }> = []
32 | protected columns: Telecolumn[] = []
33 |
34 | constructor(protected readonly telechart: Telechart, options?: IAbstractChartDrawerOptions) {
35 | this.isRangeDisplay = options && options.isRangeDisplay ? true : false
36 | this.isZeroStart = options && options.isZeroStart ? true : false
37 | this.noGuides = options && options.noGuides ? true : false
38 | this.noMilestones = options && options.noMilestones ? true : false
39 | this.topPadding = options && options.topPadding ? options.topPadding : 0
40 | this.bottomPadding = options && options.bottomPadding ? options.bottomPadding : 0
41 | }
42 |
43 | public abstract drawColumns(): void
44 |
45 | public abstract drawColumn(column: Telecolumn): void
46 |
47 | public get telecanvas() {
48 | return this.telechart.telecanvas
49 | }
50 |
51 | public get bordersAnimationFinished() {
52 | return this.borders.maxX.finished && this.borders.maxY.finished
53 | }
54 |
55 | public getXValue(canvasX: number) {
56 | return Math.round((this.borders.maxX.value - this.borders.minX.value) * canvasX / this.telecanvas.width + this.borders.minX.value)
57 | }
58 |
59 | public getYValue(canvasY: number) {
60 | const tHeight = this.telecanvas.height - (this.bottomPadding + this.topPadding)
61 | return Math.round((this.topPadding - canvasY) * (this.borders.maxY.to - this.borders.minY.to) / tHeight + this.borders.maxY.to)
62 | }
63 |
64 | public getCanvasX(value: number, borders?: [number, number]) {
65 | const min = borders ? borders[0] : this.borders.minX.value
66 | const max = borders ? borders[1] : this.borders.maxX.value
67 | return (value - min) / (max - min) * this.telecanvas.width
68 | }
69 |
70 | public getCanvasY(value: number, borders?: [number, number]) {
71 | const min = borders ? borders[0] : this.borders.minY.value
72 | const max = borders ? borders[1] : this.borders.maxY.value
73 | const tHeight = this.telecanvas.height - (this.bottomPadding + this.topPadding)
74 | return tHeight - (value - min) / (max - min) * tHeight + this.topPadding
75 | }
76 |
77 | public addColumn(column: Telecolumn) {
78 | this.columns.push(column)
79 | this.recalcBorders(0)
80 | if (!this.noMilestones) {
81 | this.recalcMilestones()
82 | }
83 | }
84 |
85 | public removeColumn(column: Telecolumn) {
86 | this.columns.splice(this.columns.indexOf(column), 1)
87 | this.recalcBorders(0)
88 | if (!this.noMilestones) {
89 | this.recalcMilestones()
90 | }
91 | }
92 |
93 | public drawCurrentPoints() {
94 | this.columns.forEach(col => {
95 | if (col.current) {
96 | this.telecanvas.circle([this.getCanvasX(col.current.x), this.getCanvasY(col.current.y)], 4.5, col.color, col.config.background, 2)
97 | }
98 | })
99 | }
100 |
101 | public drawCurrentLine(color: string) {
102 | const c = this.telecanvas
103 | if (this.columns.length && this.columns[0].currentPoint) {
104 | c.line(
105 | [this.getCanvasX(this.columns[0].currentPoint.x), 0],
106 | [this.getCanvasX(this.columns[0].currentPoint.x), c.height - this.bottomPadding],
107 | color, 1,
108 | )
109 | }
110 | }
111 |
112 | public drawMilestones(textColor: string) {
113 | const c = this.telecanvas
114 | const dateWidth = 75
115 | const milestones = this.milestones.filter(m => {
116 | const x = this.getCanvasX(m.x)
117 | return x > -50 && x < c.width + 50
118 | })
119 | milestones.forEach(m => {
120 | const index = this.milestones.indexOf(m)
121 | const x = this.getCanvasX(m.x)
122 | if (!m.title) {
123 | m.title = this.telechart.getDateString(m.x, 'M j')
124 | }
125 | const roundToPowerOfTwo = (num: number) => {
126 | return Math.pow(2, Math.round(Math.log(num) / Math.log(2)))
127 | }
128 | const odd = roundToPowerOfTwo(Math.ceil(milestones.length / (c.width / dateWidth)))
129 | let opacity = 0
130 | if (index % odd === 0) {
131 | opacity = 1
132 | } else if (index % (odd / 2) === 0) {
133 | opacity = Math.min(1, c.width / (milestones.length / odd + milestones.length / odd / 2) / dateWidth)
134 | opacity = opacity * opacity * opacity * opacity
135 | }
136 | if (opacity < .15) {
137 | return
138 | }
139 | c.text(m.title!, [x, c.height - this.bottomPadding + 18], c.getColorString(textColor, opacity), undefined, 11, 'center')
140 | })
141 | }
142 |
143 | public drawGuides(lineColor: string|undefined, textColor?: string, textAlign: 'left'|'right' = 'left', labelFormatter?: (label: string) => string) {
144 | if (!lineColor && !textColor) {
145 | return
146 | }
147 | const c = this.telecanvas
148 | c.save()
149 | c.setClippingRect(0, 0, c.width, c.height - this.bottomPadding + 30)
150 | for (let n = this.guides.length - 1; n >= 0; n--) {
151 | const g = this.guides[n]
152 | const y = this.getCanvasY(g.y)
153 | if (g.opacity.finished && g.opacity.value === 0) {
154 | this.guides.splice(n, 1)
155 | }
156 | if (lineColor) {
157 | c.line([0, y], [c.width, y], c.getColorString(lineColor, g.opacity.value), 1)
158 | }
159 | if (textColor) {
160 | if (textAlign === 'left') {
161 | c.text(labelFormatter ? labelFormatter(g.title) : g.title, [0, y - 6], c.getColorString(textColor, g.opacity.value), undefined, 11)
162 | } else {
163 | c.text(labelFormatter ? labelFormatter(g.title) : g.title, [c.width, y - 6], c.getColorString(textColor, g.opacity.value), undefined, 11, 'right')
164 | }
165 | }
166 | }
167 | c.restore()
168 | }
169 |
170 | public recalcBorders(duration = 100) {
171 | if (!this.columns.filter(c => c.visible).length) {
172 | return
173 | }
174 | const oldMax = this.borders ? this.borders.maxY.to : 0
175 | const oldMin = this.borders ? this.borders.minY.to : 0
176 | this.borders = this.getNewBorders(duration)
177 | if (!this.noGuides && (oldMax !== this.borders.maxY.to || oldMin !== this.borders.minY.to)) {
178 | this.recalcGuides(duration)
179 | }
180 | }
181 |
182 | protected getNewBorders(duration?: number) {
183 | const result = {
184 | minX: Math.min(...this.columns.filter(c => c.visible).map(c => c.getMinX(this.isRangeDisplay))),
185 | maxX: Math.max(...this.columns.filter(c => c.visible).map(c => c.getMaxX(this.isRangeDisplay))),
186 | minY: this.isZeroStart ? 0 : Math.min(...this.columns.filter(c => c.visible).map(c => c.getMinY(this.isRangeDisplay))),
187 | maxY: Math.max(...this.columns.filter(c => c.visible).map(c => c.getMaxY(this.isRangeDisplay))),
188 | }
189 | return {
190 | minX: duration && this.borders ? Telemation.create(this.borders.minX.value, result.minX, 100) : Telemation.create(result.minX),
191 | maxX: duration && this.borders ? Telemation.create(this.borders.maxX.value, result.maxX, 100) : Telemation.create(result.maxX),
192 | minY: duration && this.borders ? Telemation.create(this.borders.minY.value, result.minY, duration) : Telemation.create(result.minY),
193 | maxY: duration && this.borders ? Telemation.create(this.borders.maxY.value, result.maxY, duration) : Telemation.create(result.maxY),
194 | }
195 | }
196 |
197 | protected getInDisplayColumnValues(column: Telecolumn, borders?: [number, number]) {
198 | const allVals = column.currentValues
199 | while (this.getCanvasX(allVals[0].x, borders) > 0) {
200 | const prevIndex = column.values.indexOf(allVals[0]) - 1
201 | if (prevIndex < 0) {
202 | break
203 | }
204 | allVals.unshift(column.values[prevIndex])
205 | }
206 | while (this.getCanvasX(allVals[allVals.length - 1].x, borders) < this.telecanvas.width) {
207 | const nextIndex = column.values.indexOf(allVals[allVals.length - 1]) + 1
208 | if (nextIndex >= column.values.length) {
209 | break
210 | }
211 | allVals.push(column.values[nextIndex])
212 | }
213 | return allVals
214 | }
215 |
216 | protected recalcGuides(duration: number = 0) {
217 | const c = this.telecanvas
218 | if (!duration) {
219 | this.guides = []
220 | } else {
221 | for (const g of this.guides) {
222 | g.opacity = Telemation.create(g.opacity.value, 0, duration)
223 | }
224 | }
225 | for (let n = 0; n < this.guidesCount; n++) {
226 | const y = this.getYValue(c.height - this.bottomPadding - (c.height - this.bottomPadding - this.topPadding) / this.guidesCount * n)
227 | let value = Math.round(y - y % Math.pow(10, y.toString().length - 2))
228 | let modifier = ''
229 | const diff = this.borders.maxY.to - this.borders.minY.to
230 | if (diff > 5000000) {
231 | value = Math.round(value / 1000000)
232 | modifier = 'M'
233 | } else if (diff > 5000) {
234 | value = Math.round(value / 1000)
235 | modifier = 'K'
236 | }
237 | this.guides.push({ y, title: `${value}${modifier}`, opacity: duration ? Telemation.create(0, 1, duration) : Telemation.create(1) })
238 | }
239 | while (this.guides.length > this.guidesCount * 3) {
240 | this.guides.shift()
241 | }
242 | }
243 |
244 | protected recalcMilestones() {
245 | this.milestones = []
246 | for (let x = this.borders.minX.to; x < this.borders.maxX.to; x += 60 * 60 * 24 * 1000) {
247 | const value = { x, title: null }
248 | this.milestones.push(value)
249 | }
250 | }
251 |
252 | }
253 |
--------------------------------------------------------------------------------
/dist/data/5/overview.json:
--------------------------------------------------------------------------------
1 | {"columns":[["x",1523059200000,1523145600000,1523232000000,1523318400000,1523404800000,1523491200000,1523577600000,1523664000000,1523750400000,1523836800000,1523923200000,1524009600000,1524096000000,1524182400000,1524268800000,1524355200000,1524441600000,1524528000000,1524614400000,1524700800000,1524787200000,1524873600000,1524960000000,1525046400000,1525132800000,1525219200000,1525305600000,1525392000000,1525478400000,1525564800000,1525651200000,1525737600000,1525824000000,1525910400000,1525996800000,1526083200000,1526169600000,1526256000000,1526342400000,1526428800000,1526515200000,1526601600000,1526688000000,1526774400000,1526860800000,1526947200000,1527033600000,1527120000000,1527206400000,1527292800000,1527379200000,1527465600000,1527552000000,1527638400000,1527724800000,1527811200000,1527897600000,1527984000000,1528070400000,1528156800000,1528243200000,1528329600000,1528416000000,1528502400000,1528588800000,1528675200000,1528761600000,1528848000000,1528934400000,1529020800000,1529107200000,1529193600000,1529280000000,1529366400000,1529452800000,1529539200000,1529625600000,1529712000000,1529798400000,1529884800000,1529971200000,1530057600000,1530144000000,1530230400000,1530316800000,1530403200000,1530489600000,1530576000000,1530662400000,1530748800000,1530835200000,1530921600000,1531008000000,1531094400000,1531180800000,1531267200000,1531353600000,1531440000000,1531526400000,1531612800000,1531699200000,1531785600000,1531872000000,1531958400000,1532044800000,1532131200000,1532217600000,1532304000000,1532390400000,1532476800000,1532563200000,1532649600000,1532736000000,1532822400000,1532908800000,1532995200000,1533081600000,1533168000000,1533254400000,1533340800000,1533427200000,1533513600000,1533600000000,1533686400000,1533772800000,1533859200000,1533945600000,1534032000000,1534118400000,1534204800000,1534291200000,1534377600000,1534464000000,1534550400000,1534636800000,1534723200000,1534809600000,1534896000000,1534982400000,1535068800000,1535155200000,1535241600000,1535328000000,1535414400000,1535500800000,1535587200000,1535673600000,1535760000000,1535846400000,1535932800000,1536019200000,1536105600000,1536192000000,1536278400000,1536364800000,1536451200000,1536537600000,1536624000000,1536710400000,1536796800000,1536883200000,1536969600000,1537056000000,1537142400000,1537228800000,1537315200000,1537401600000,1537488000000,1537574400000,1537660800000,1537747200000,1537833600000,1537920000000,1538006400000,1538092800000,1538179200000,1538265600000,1538352000000,1538438400000,1538524800000,1538611200000,1538697600000,1538784000000,1538870400000,1538956800000,1539043200000,1539129600000,1539216000000,1539302400000,1539388800000,1539475200000,1539561600000,1539648000000,1539734400000,1539820800000,1539907200000,1539993600000,1540080000000,1540166400000,1540252800000,1540339200000,1540425600000,1540512000000,1540598400000,1540684800000,1540771200000,1540857600000,1540944000000,1541030400000,1541116800000,1541203200000,1541289600000,1541376000000,1541462400000,1541548800000,1541635200000,1541721600000,1541808000000,1541894400000,1541980800000,1542067200000,1542153600000,1542240000000,1542326400000,1542412800000,1542499200000,1542585600000,1542672000000,1542758400000,1542844800000,1542931200000,1543017600000,1543104000000,1543190400000,1543276800000,1543363200000,1543449600000,1543536000000,1543622400000,1543708800000,1543795200000,1543881600000,1543968000000,1544054400000,1544140800000,1544227200000,1544313600000,1544400000000,1544486400000,1544572800000,1544659200000,1544745600000,1544832000000,1544918400000,1545004800000,1545091200000,1545177600000,1545264000000,1545350400000,1545436800000,1545523200000,1545609600000,1545696000000,1545782400000,1545868800000,1545955200000,1546041600000,1546128000000,1546214400000,1546300800000,1546387200000,1546473600000,1546560000000,1546646400000,1546732800000,1546819200000,1546905600000,1546992000000,1547078400000,1547164800000,1547251200000,1547337600000,1547424000000,1547510400000,1547596800000,1547683200000,1547769600000,1547856000000,1547942400000,1548028800000,1548115200000,1548201600000,1548288000000,1548374400000,1548460800000,1548547200000,1548633600000,1548720000000,1548806400000,1548892800000,1548979200000,1549065600000,1549152000000,1549238400000,1549324800000,1549411200000,1549497600000,1549584000000,1549670400000,1549756800000,1549843200000,1549929600000,1550016000000,1550102400000,1550188800000,1550275200000,1550361600000,1550448000000,1550534400000,1550620800000,1550707200000,1550793600000,1550880000000,1550966400000,1551052800000,1551139200000,1551225600000,1551312000000,1551398400000,1551484800000,1551571200000,1551657600000,1551744000000,1551830400000,1551916800000,1552003200000,1552089600000,1552176000000,1552262400000,1552348800000,1552435200000,1552521600000,1552608000000,1552694400000,1552780800000,1552867200000,1552953600000,1553040000000,1553126400000,1553212800000,1553299200000,1553385600000,1553472000000,1553558400000,1553644800000,1553731200000,1553817600000,1553904000000,1553990400000,1554076800000,1554163200000,1554249600000,1554336000000,1554422400000,1554508800000],["y0",34310,38260,47440,42460,43740,43770,41720,35440,39770,42420,45930,42840,42080,41300,33430,34690,44450,41780,33570,40180,38560,33220,27930,44050,35100,47290,46580,43240,34810,39960,45820,43680,44660,46050,43560,32970,42450,47550,50150,45430,44740,41950,30010,38770,45030,50130,42960,43090,39330,35630,41110,46810,48720,49340,45190,38450,31440,37730,42390,48980,49870,43060,44800,32470,38350,46770,49570,49110,50510,43630,37390,42040,49600,49120,44440,48430,47780,39650,37610,47430,49810,47090,47960,42390,31880,38090,43410,47620,48660,49410,48980,33870,39340,52190,48170,48830,49110,44620,29840,34750,52870,44890,48690,50820,41630,32840,33220,45130,48770,40130,42330,39850,30770,30490,42370,44410,42050,45240,37590,28220,28460,43830,35120,37970,38080,33960,31170,33140,35170,31390,23890,35030,29560,27300,29170,41540,38970,40210,40290,42360,33160,37040,45390,43470,45240,48290,45280,39430,37240,46040,53750,52340,56740,48730,32760,35940,57580,48800,44720,47330,40000,37190,44400,53920,48080,42060,45650,41430,34950,35300,50860,44030,46780,43890,38240,29930,36670,43530,46970,47220,45550,38840,34260,39740,41650,45770,47930,44510,42120,20810,35470,41790,45670,44380,42660,40320,32480,40190,47830,47030,47340,42530,42240,37300,38980,49190,45440,37440,34270,46220,33960,44960,45250,43860,44340,44010,41790,34410,43200,46130,48550,43810,45360,50150,35320,39170,48970,48150,47340,48960,39830,32340,37610,49160,45110,41230,44360,44180,33100,37630,47340,46860,47800,43470,39480,36760,38750,46680,42040,41890,43630,39920,30640,37680,42650,42410,39520,38680,33620,26190,31120,31710,24600,29640,35580,33250,29090,31260,20900,25900,39520,38410,38970,37370,32060,41190,42710,42410,44490,42680,33690,38400,42230,44920,41980,42120,40250,35550,37400,48750,44870,45750,44020,41510,30420,37770,48420,42870,47080,47870,41520,33120,39320,52990,44150,49360,42200,42290,29470,41270,47010,42710,44330,39960,40600,30710,33290,44720,43690,42740,40440,40440,32720,37030,42310,42630,38830,39250,36590,26960,29320,41210,40850,40130,40860,38760,29040,33270,44720,44170,43990,42110,40370,30110,30340,46630,42680,41700,41820,43800,31090,33950,46700,43480,44790,41260,40460,28270,32880,42010,43890,45990,42250,39450,28870],["y1",13730,13690,15220,13820,13080,13870,13300,11290,14240,15260,15150,14600,13690,14460,12750,13510,15220,15070,12730,15170,14140,12650,11480,13980,14500,15550,15590,15470,14040,14770,16590,14470,14840,14910,14490,13380,14410,14170,14800,15700,15180,14010,13020,14750,14950,14350,14710,15120,14070,12520,14680,15510,14200,15610,15180,14540,11940,15190,16180,15670,13830,14800,14560,12850,13800,14890,16190,15610,15230,14770,13940,15450,15530,16340,16000,16880,15530,13800,14410,15520,16630,14890,14660,15540,14100,15960,15950,16010,16150,15500,13800,14030,14520,16270,16110,15870,15270,15810,13670,15600,16290,15610,16060,16400,16340,13810,14920,16820,16950,17530,17490,17050,14650,15670,19000,18680,18240,18210,17680,16420,16190,16760,16580,18300,20560,18760,16440,17800,18270,21800,16760,18260,18150,18100,18210,20350,20730,22270,21910,19380,17800,20190,19540,19730,19530,19810,21450,17920,19850,21320,22400,22700,22810,20180,19140,21540,21730,21580,22800,23640,19150,22070,22740,20730,23820,21880,22700,22450,21120,21180,24150,20920,23890,21320,22110,20860,21190,22710,22170,23680,23590,23760,23170,22360,24520,23830,24690,26700,22220,14530,22920,26310,24840,24910,27490,24910,23330,28350,29540,29300,28910,30530,27710,26870,31170,34050,32040,28070,31970,32860,30500,35250,34900,35680,34820,36470,36600,31880,37310,38540,37510,36470,37070,33790,32550,34480,35660,34840,35070,34430,33800,29450,32910,37250,34730,33970,33660,32470,29670,32120,35610,33620,35090,32780,30180,26990,32680,35540,33250,33070,31350,31500,29800,29620,32630,32060,31030,31850,31040,29000,31410,30880,34180,31390,31410,33940,30190,29970,27620,28530,31660,35190,34050,33360,33250,32930,33570,32310,31930,32520,31000,34450,35120,33320,32760,32310,32110,30030,32290,32180,34510,34630,33840,32850,29680,32390,35360,32350,33910,32170,31140,25910,31100,33070,31630,32140,32980,31910,26510,28700,32450,30350,30620,28170,27090,24020,26210,30630,30010,29060,28280,27480,25640,27380,31170,30140,29880,27080,27190,26540,26100,28950,28390,29580,28430,27180,26900,27890,30370,29010,37710,31070,28200,24050,29250,30280,30940,30400,29590,27840,25070,28680,30740,28600,30670,30550,28430,26900,27170,29890,30590,33270,31990,30770,27010],["y2",10200,11610,11210,11800,11010,10980,12360,9040,11290,10530,10530,9160,8920,10140,8700,8320,9860,9330,7450,9840,8710,6850,6500,8840,7640,8690,7730,7990,8020,7160,9640,7810,9740,8010,10200,7060,6570,8240,8260,8390,9060,7860,8050,6180,8160,8020,9000,8300,7980,6450,6700,7870,7820,7330,8520,8010,6940,7800,8480,8430,7360,7010,7310,6680,5940,7100,6890,8810,6600,7580,5680,6710,8530,9210,6170,6940,7760,6120,5890,9590,6340,6450,8990,7720,7650,6330,8120,7200,7620,8010,5930,8830,7360,8020,6730,7360,7870,8170,6520,6500,6820,9860,7160,7960,7270,6420,5610,7340,7070,6480,7090,6960,6440,5830,7230,8080,6980,7660,9220,5980,4930,6880,6920,6910,7140,6030,5800,7240,8090,5640,5530,6520,6230,6210,6200,8850,8430,9310,8930,8140,7330,7770,7820,7380,8020,7310,6790,6980,6910,8800,7250,9200,8440,8230,6710,7710,8430,7780,7290,9210,8000,8170,7140,8060,7360,6840,7850,6650,6150,7120,8510,9020,9750,9200,9320,7500,6820,8560,9350,9020,8150,8610,6740,8500,8330,7170,8790,7090,6870,4910,7700,8490,9190,10100,7720,7850,8530,7970,9480,8170,9900,9190,8690,10060,10280,10930,9470,9840,11210,11240,7870,10100,11280,10970,11100,10590,10920,8850,9130,11280,10410,10530,10560,10150,11230,8580,9660,10010,10990,10560,7710,7710,9290,10680,9030,8690,9440,8860,7170,9130,10090,9080,9240,9090,8760,8070,8520,9110,9240,9110,9500,9080,7810,9090,10110,9700,10770,9580,8390,8100,7840,9530,9590,8820,9140,9580,9610,8950,7980,8180,9920,9730,9940,8990,9600,9830,9680,9840,8840,9030,9090,10470,9820,10730,9900,10470,11100,7790,10320,10060,11450,10110,10020,10170,10540,11910,11290,11040,9940,10240,9850,9610,9920,10440,10880,10290,9930,10560,10560,9590,11160,10660,10540,9800,9490,9350,9440,10260,11180,9980,9590,9240,8560,9170,9290,9370,9420,10210,9640,8780,11220,10440,9800,10500,10420,9840,8990,9410,10860,10710,13840,13700,10680,8830,11480,12140,11130,13350,11750,9780,9150,9820,11100,10890,11930,10630,10490,8880,11000,11480,12160,10660,11210,10410,9850],["y3",2000,2540,3540,3380,3190,3530,3190,2160,2520,3770,3360,3300,3130,2810,1710,2210,3490,3370,2270,3070,2870,1750,1430,2340,2210,3470,3380,3470,2150,2210,3540,3450,3280,3360,2890,2130,2250,3940,3480,3380,3470,2920,1920,1950,3600,3440,3450,3540,2940,2070,2050,3430,3610,3290,3320,2770,1880,2280,3690,3360,3490,3060,3120,2080,2220,3390,3290,3580,3330,3160,2160,2140,3290,3010,3540,3280,3060,2350,2490,3260,3430,3160,3860,2730,1890,2300,3050,2940,3150,3380,2840,1870,1940,3020,3050,3310,2960,2760,1730,2330,3610,3390,2790,2930,2840,1750,1910,2990,3190,2620,2940,2190,1580,1490,2430,2490,2350,2270,2030,1240,1510,2550,2100,1900,2290,1770,1450,1560,1790,1670,1110,2060,1530,1600,1620,2470,2760,2390,2260,2200,1690,1590,2630,2580,2500,2780,2280,1810,1970,2880,2970,2830,3030,2910,2150,2150,3090,2950,2850,3120,2540,1830,2290,3110,3210,2950,2670,2940,1800,1820,3130,3180,3690,3030,2940,1780,2080,3120,3470,3220,3240,3140,2080,2510,3300,3260,3390,3490,2970,1780,2260,3610,3280,3540,3620,3020,2110,2360,3120,3420,3440,3430,3050,2630,2670,4080,3320,2980,2400,2920,2240,2010,3290,3880,3480,3180,3750,2200,3050,3160,3590,2890,3580,3510,1790,2610,3930,3540,3660,3280,2900,2100,2580,3660,4100,3340,3590,3050,2390,2360,3880,3870,3910,3230,2690,1990,2280,3710,3540,3350,3150,2870,2290,2280,3230,3520,2990,2590,2390,1890,2170,1950,1360,2060,2650,2430,1920,1820,1400,1540,2900,3080,3560,2360,2710,3960,3900,3660,4000,3550,2930,3770,4240,4490,4760,4160,3410,2350,3210,3420,3980,4010,4000,4150,2390,3060,3830,4060,3700,3510,3530,2380,2430,3640,4550,3700,3310,3870,2130,2480,3650,3820,4180,3500,3380,1970,2640,3970,3800,3830,3400,3110,1820,2370,3860,3650,3650,3620,3270,2100,2440,3520,3290,3470,3210,3210,2020,2360,3910,3700,3650,3200,3250,2220,2420,4010,3870,3620,3620,3010,2410,2530,3820,3630,3870,3510,3190,1880,2460,3500,3750,3880,4140,3320,2260],["y4",5480,5930,10490,9460,11790,9530,9690,5500,5810,8090,9510,8830,8350,8490,5130,5550,9110,9850,5800,8930,8280,4540,4350,6630,4490,9810,9130,8680,5040,5120,9100,9520,8670,10550,8860,5140,5050,9510,10390,10290,10130,9700,4150,5270,9790,9670,9120,10030,9790,5250,5530,9280,9610,9870,9580,9410,4700,6340,10490,10390,10850,9680,8600,4920,5050,10960,10680,10500,10070,8270,5410,5730,10780,10250,10470,9690,9640,5080,5630,10050,11060,8290,9540,8070,5380,5310,9710,9750,10760,9870,9080,5030,6720,9830,10500,9190,9550,9580,6040,6360,10720,9090,10170,9570,9750,4810,5280,9420,9310,8830,9050,8400,4480,3990,7880,8890,8320,8770,7420,5210,3960,7940,7750,8310,8070,6670,4590,4500,6150,5190,3850,5940,6310,4300,4370,9240,7760,7810,7700,7790,4380,4990,8640,9060,8870,9760,8780,6250,6250,10460,10520,10970,10430,9440,5390,5270,10630,10740,10160,10030,9180,4620,5290,9080,11090,9930,10520,9910,5120,5360,9810,9170,9120,10310,8460,4200,4390,9770,9800,10000,9530,9130,4830,4820,9390,8900,8820,9390,8480,3240,4990,9510,9060,8840,9480,8970,4800,5620,9750,10350,9890,9510,9170,5790,6960,10760,9780,8790,6010,8560,5550,5710,9910,9130,9630,10250,9720,4930,6080,9760,10140,8950,10930,9040,5390,6260,9570,10320,9450,10200,8570,5630,5230,10030,10220,9690,10240,9500,5680,5970,9350,9710,9090,9760,8630,4730,5930,9900,10220,9480,8960,7940,5080,4910,9060,8490,10270,9200,7350,4800,5420,4580,3820,4200,6850,7120,5040,4870,4070,3590,7720,7710,7330,5230,5980,8450,10610,9030,9480,8870,5010,5210,10050,9270,9770,9290,9480,5280,4770,9320,10050,9310,9650,8280,4880,5350,10050,9730,9880,10130,9120,5140,5840,9820,9870,9770,8920,9010,4810,5480,10440,9540,9450,9540,9390,5380,5460,10590,9370,10240,9790,9370,5140,5630,9530,9240,9440,9760,8500,4900,4850,9890,8650,9450,9820,8880,5050,5000,9100,9690,9630,9870,8570,4840,5130,9910,9760,9930,10210,9010,4990,5580,10040,10630,10260,10610,8240,5080,4530,10140,9920,9670,10590,10600,4970],["y5",4770,4760,4910,5490,5560,5270,4900,4520,5420,5750,5640,5290,5090,5670,4290,4160,4990,5170,4380,5370,5840,4710,3600,4560,4640,5000,4660,4800,3900,6400,4150,5100,5190,5950,4670,3940,4070,4490,4750,4760,4910,4730,3780,3760,4860,4730,4960,4330,5320,4700,4390,5570,5470,4330,4250,4070,3500,3790,5020,4630,5070,3930,4360,3470,3730,4130,4910,4670,4100,4240,3660,3360,4430,4090,3860,4180,4420,3540,4120,4180,4330,4000,4450,3460,3090,3600,3720,4190,3890,3900,4340,3150,3210,3940,4150,4310,4300,3600,3380,2970,3320,3520,3570,4010,3400,3210,3130,3670,3740,3790,2910,3230,2280,3030,2770,3310,3640,3050,3090,2810,2880,3470,3120,3270,3140,2460,2950,2690,3000,2950,2430,3210,3500,2230,2620,3030,3010,3150,3110,3170,3680,3020,3380,2600,3180,3240,3690,3150,3200,2860,3320,3290,3200,3240,2760,3100,3660,3180,4120,3110,4100,2950,2360,3590,3320,3410,3220,3200,2510,2800,3490,3050,2830,3100,3000,3030,2800,3670,2890,3320,2640,2660,2410,2720,3370,3230,3070,2920,3010,2240,2510,2970,2750,2560,2700,2630,2660,2700,2890,3030,2430,3300,3700,2830,3010,2990,2850,2850,3290,2400,2890,3000,2640,2900,2970,2980,2430,2450,2960,2990,2940,2950,2900,2670,2300,2610,2670,2760,2440,2960,2740,2290,2820,2330,2690,2420,2780,2110,2180,2040,2740,2960,3230,2880,2680,2180,2380,2560,2890,2540,2660,2450,2440,2450,2590,2930,2960,3030,2380,2220,2390,2520,2650,2490,2590,2450,2200,2340,2150,2520,2140,2100,2240,2150,2770,2740,2240,2080,2480,2090,2230,2180,2390,2390,2670,2920,1960,1910,2420,2180,2860,2800,2460,2700,2360,2320,2750,2520,2690,2580,2270,2370,2190,2440,2120,2360,2110,2170,2200,2370,2110,2280,2410,2640,2240,2380,2090,2620,2570,2510,2320,2390,1970,2190,2340,2340,2310,2290,2450,1960,2140,1930,2400,1980,2290,2160,1840,1700,2110,2540,2390,2150,1800,1990,2130,2040,1910,1740,2290,2030,1820,2090,2200,2340,2010,2200,2030,2340,1630,2010,1910,1980,1970,1640,1660]],"types":{"y0":"area","y1":"area","y2":"area","y3":"area","y4":"area","y5":"area","x":"x"},"names":{"y0":"Apples","y1":"Oranges","y2":"Lemons","y3":"Apricots","y4":"Kiwi","y5":"Mango"},"colors":{"y0":"#3497ED","y1":"#2373DB","y2":"#9ED448","y3":"#5FB641","y4":"#F5BD25","y5":"#F79E39"},"percentage":true,"stacked":true}
--------------------------------------------------------------------------------
/dist/data/3/overview.json:
--------------------------------------------------------------------------------
1 | {"columns":[["x",1523059200000,1523145600000,1523232000000,1523318400000,1523404800000,1523491200000,1523577600000,1523664000000,1523750400000,1523836800000,1523923200000,1524009600000,1524096000000,1524182400000,1524268800000,1524355200000,1524441600000,1524528000000,1524614400000,1524700800000,1524787200000,1524873600000,1524960000000,1525046400000,1525132800000,1525219200000,1525305600000,1525392000000,1525478400000,1525564800000,1525651200000,1525737600000,1525824000000,1525910400000,1525996800000,1526083200000,1526169600000,1526256000000,1526342400000,1526428800000,1526515200000,1526601600000,1526688000000,1526774400000,1526860800000,1526947200000,1527033600000,1527120000000,1527206400000,1527292800000,1527379200000,1527465600000,1527552000000,1527638400000,1527724800000,1527811200000,1527897600000,1527984000000,1528070400000,1528156800000,1528243200000,1528329600000,1528416000000,1528502400000,1528588800000,1528675200000,1528761600000,1528848000000,1528934400000,1529020800000,1529107200000,1529193600000,1529280000000,1529366400000,1529452800000,1529539200000,1529625600000,1529712000000,1529798400000,1529884800000,1529971200000,1530057600000,1530144000000,1530230400000,1530316800000,1530403200000,1530489600000,1530576000000,1530662400000,1530748800000,1530835200000,1530921600000,1531008000000,1531094400000,1531180800000,1531267200000,1531353600000,1531440000000,1531526400000,1531612800000,1531699200000,1531785600000,1531872000000,1531958400000,1532044800000,1532131200000,1532217600000,1532304000000,1532390400000,1532476800000,1532563200000,1532649600000,1532736000000,1532822400000,1532908800000,1532995200000,1533081600000,1533168000000,1533254400000,1533340800000,1533427200000,1533513600000,1533600000000,1533686400000,1533772800000,1533859200000,1533945600000,1534032000000,1534118400000,1534204800000,1534291200000,1534377600000,1534464000000,1534550400000,1534636800000,1534723200000,1534809600000,1534896000000,1534982400000,1535068800000,1535155200000,1535241600000,1535328000000,1535414400000,1535500800000,1535587200000,1535673600000,1535760000000,1535846400000,1535932800000,1536019200000,1536105600000,1536192000000,1536278400000,1536364800000,1536451200000,1536537600000,1536624000000,1536710400000,1536796800000,1536883200000,1536969600000,1537056000000,1537142400000,1537228800000,1537315200000,1537401600000,1537488000000,1537574400000,1537660800000,1537747200000,1537833600000,1537920000000,1538006400000,1538092800000,1538179200000,1538265600000,1538352000000,1538438400000,1538524800000,1538611200000,1538697600000,1538784000000,1538870400000,1538956800000,1539043200000,1539129600000,1539216000000,1539302400000,1539388800000,1539475200000,1539561600000,1539648000000,1539734400000,1539820800000,1539907200000,1539993600000,1540080000000,1540166400000,1540252800000,1540339200000,1540425600000,1540512000000,1540598400000,1540684800000,1540771200000,1540857600000,1540944000000,1541030400000,1541116800000,1541203200000,1541289600000,1541376000000,1541462400000,1541548800000,1541635200000,1541721600000,1541808000000,1541894400000,1541980800000,1542067200000,1542153600000,1542240000000,1542326400000,1542412800000,1542499200000,1542585600000,1542672000000,1542758400000,1542844800000,1542931200000,1543017600000,1543104000000,1543190400000,1543276800000,1543363200000,1543449600000,1543536000000,1543622400000,1543708800000,1543795200000,1543881600000,1543968000000,1544054400000,1544140800000,1544227200000,1544313600000,1544400000000,1544486400000,1544572800000,1544659200000,1544745600000,1544832000000,1544918400000,1545004800000,1545091200000,1545177600000,1545264000000,1545350400000,1545436800000,1545523200000,1545609600000,1545696000000,1545782400000,1545868800000,1545955200000,1546041600000,1546128000000,1546214400000,1546300800000,1546387200000,1546473600000,1546560000000,1546646400000,1546732800000,1546819200000,1546905600000,1546992000000,1547078400000,1547164800000,1547251200000,1547337600000,1547424000000,1547510400000,1547596800000,1547683200000,1547769600000,1547856000000,1547942400000,1548028800000,1548115200000,1548201600000,1548288000000,1548374400000,1548460800000,1548547200000,1548633600000,1548720000000,1548806400000,1548892800000,1548979200000,1549065600000,1549152000000,1549238400000,1549324800000,1549411200000,1549497600000,1549584000000,1549670400000,1549756800000,1549843200000,1549929600000,1550016000000,1550102400000,1550188800000,1550275200000,1550361600000,1550448000000,1550534400000,1550620800000,1550707200000,1550793600000,1550880000000,1550966400000,1551052800000,1551139200000,1551225600000,1551312000000,1551398400000,1551484800000,1551571200000,1551657600000,1551744000000,1551830400000,1551916800000,1552003200000,1552089600000,1552176000000,1552262400000,1552348800000,1552435200000,1552521600000,1552608000000,1552694400000,1552780800000,1552867200000,1552953600000,1553040000000,1553126400000,1553212800000,1553299200000,1553385600000,1553472000000,1553558400000,1553644800000,1553731200000,1553817600000,1553904000000,1553990400000,1554076800000,1554163200000,1554249600000,1554336000000,1554422400000,1554508800000],["y0",12360,16240,14210,14040,15190,13570,14020,15600,16080,15800,16740,15680,16790,15520,17410,17660,17000,15080,17190,17020,16620,15200,13210,16970,16030,16090,16800,15280,15450,15990,17130,14970,16020,15780,15770,15720,16210,15820,16080,14860,14210,14980,16200,15430,15510,16750,16460,15130,15120,15580,18040,16380,15940,16590,15950,15480,14940,16520,16570,15910,15950,16280,17120,15720,16600,17580,16260,17270,15660,16500,16410,17140,16240,17330,16320,17490,17220,17030,19130,17440,17350,17010,19050,16150,16350,18280,17670,19690,17470,16320,16180,16290,15440,16600,17430,17800,18110,16870,17200,16700,18010,18110,17850,17600,17870,18100,17300,19960,18340,19650,19710,21300,18930,20090,20240,21150,21020,21940,22350,22160,20800,22390,21450,22970,20690,23410,21490,21690,20650,22440,21630,23420,22860,23490,24460,23610,23810,22840,23540,24800,23460,24140,25050,23910,23790,23190,23390,23160,23830,23680,25940,23420,23330,23630,23400,26230,22690,24700,22010,23050,22460,24620,24960,26180,24540,24240,24690,24140,25140,29410,25900,25880,24600,25380,25090,24930,28930,26570,25270,26560,25520,27150,25130,25600,28580,25800,25500,27870,26320,18930,30390,27640,27790,28380,29230,28160,28490,31290,31710,32150,29840,29860,30240,30750,33300,34750,33250,31920,36940,36930,33360,38500,33700,34630,36580,36130,34960,35210,37600,37100,34640,36840,36150,33850,32800,35440,37510,36770,35560,35460,36650,35370,36990,39810,39340,36350,35350,33160,34440,36720,35200,37240,36030,36330,34940,34840,39350,37370,34040,33510,35270,32940,33310,34730,35760,37300,35190,33420,32550,33450,34360,41660,42960,38970,37080,37150,36460,41330,34220,34980,34840,39150,38110,35380,38760,36080,33790,36150,35960,32570,33180,36000,36390,33950,35390,36680,36540,31270,34720,35030,37090,38120,32870,34800,35000,34370,35070,35430,36830,37380,35390,33170,37300,34710,36450,37500,37820,31590,34370,37430,36650,35300,35520,35830,35650,32070,38700,34460,34450,32720,34900,35680,33340,37500,35730,35270,37150,35010,35260,33690,40330,36410,35540,35600,35480,37740,35600,44060,34610,37160,37880,36800,37940,35140,36900,40490,37740,36330,37730,35330,35800,39580,37590,35770,36430,36720,36860,33580,36830,35830,36600,37840,39450,35390,35310],["y1",9850,8210,10800,10490,11600,11160,11920,10210,8010,12010,12270,11720,12790,12330,10970,10150,11180,12150,9320,11460,12290,10400,7790,12150,8920,11330,11450,11550,10900,9800,11770,12130,11070,11850,11670,11260,10110,10790,10940,11200,12710,11660,9980,9120,11410,12830,11380,13290,12080,11020,9770,11700,11980,13020,12200,12320,9780,10660,10900,11940,12490,11300,12220,10410,10270,12310,12580,12170,12590,13110,10510,8960,12310,13270,13860,13460,12980,10030,10480,11550,12540,11630,13280,12670,9230,9510,11770,12160,12510,12130,12220,9630,8880,11210,10570,11600,12920,11260,11260,9570,11440,11850,12090,12640,12330,12180,9550,12990,12830,13600,14390,13380,11200,9350,13120,14140,15400,14090,14010,12900,10810,13690,13380,13910,13970,14260,12480,11110,12830,12910,8660,11560,13010,11910,11520,13260,15130,13850,14270,13940,13170,12080,15420,15530,16720,16800,16950,15980,13840,16930,17870,17780,17860,18180,16790,13320,18470,19150,18290,20630,19410,16410,15320,18460,18970,18930,20580,20850,17600,17750,22190,19970,21820,22900,21350,17600,16250,21290,20670,21300,22480,21530,17690,18860,21140,21100,22620,21730,21500,14230,17470,22730,22990,22790,23880,23070,21310,20790,23750,26840,25400,27300,25810,23570,21880,27560,29980,29890,22490,27400,25220,23230,28400,29720,31360,29380,31590,27210,23950,28940,29740,32280,32270,32520,27280,22010,30900,31550,32050,31800,32050,28210,23880,31450,29530,30470,32430,31660,27030,24270,31230,31630,31470,33030,32890,23600,24670,30340,31460,31610,31910,30550,26730,25180,29610,32710,33670,35040,35140,27820,23700,24670,16390,18390,29090,28130,25560,23590,21840,16420,24260,27670,29570,25730,22280,29060,29430,28930,29790,31130,25750,22390,29480,31690,30350,31150,31420,26440,22340,28380,29510,31160,30110,31910,25370,23090,30500,30550,29850,29560,30570,24870,23180,28910,29270,29670,31770,30990,26920,24520,30170,30620,30320,28920,30310,25300,22950,28800,30250,31800,30740,31250,27140,24710,30040,30210,32370,30260,31210,25190,24120,29280,30080,31050,31120,29810,25580,22500,28520,30260,35910,31510,31150,25450,23190,29760,31150,30540,30290,31860,26750,25020,30190,30700,30360,31060,30420,27340,22040,29990,30980,32710,32880,33190,30180],["y2",13730,13690,15220,13820,13080,13870,13300,11290,14240,15260,15150,14600,13690,14460,12750,13510,15220,15070,12730,15170,14140,12650,11480,13980,14500,15550,15590,15470,14040,14770,16590,14470,14840,14910,14490,13380,14410,14170,14800,15700,15180,14010,13020,14750,14950,14350,14710,15120,14070,12520,14680,15510,14200,15610,15180,14540,11940,15190,16180,15670,13830,14800,14560,12850,13800,14890,16190,15610,15230,14770,13940,15450,15530,16340,16000,16880,15530,13800,14410,15520,16630,14890,14660,15540,14100,15960,15950,16010,16150,15500,13800,14030,14520,16270,16110,15870,15270,15810,13670,15600,16290,15610,16060,16400,16340,13810,14920,16820,16950,17530,17490,17050,14650,15670,19000,18680,18240,18210,17680,16420,16190,16760,16580,18300,20560,18760,16440,17800,18270,21800,16760,18260,18150,18100,18210,20350,20730,22270,21910,19380,17800,20190,19540,19730,19530,19810,21450,17920,19850,21320,22400,22700,22810,20180,19140,21540,21730,21580,22800,23640,19150,22070,22740,20730,23820,21880,22700,22450,21120,21180,24150,20920,23890,21320,22110,20860,21190,22710,22170,23680,23590,23760,23170,22360,24520,23830,24690,26700,22220,14530,22920,26310,24840,24910,27490,24910,23330,28350,29540,29300,28910,30530,27710,26870,31170,34050,32040,28070,31970,32860,30500,35250,34900,35680,34820,36470,36600,31880,37310,38540,37510,36470,37070,33790,32550,34480,35660,34840,35070,34430,33800,29450,32910,37250,34730,33970,33660,32470,29670,32120,35610,33620,35090,32780,30180,26990,32680,35540,33250,33070,31350,31500,29800,29620,32630,32060,31030,31850,31040,29000,31410,30880,34180,31390,31410,33940,30190,29970,27620,28530,31660,35190,34050,33360,33250,32930,33570,32310,31930,32520,31000,34450,35120,33320,32760,32310,32110,30030,32290,32180,34510,34630,33840,32850,29680,32390,35360,32350,33910,32170,31140,25910,31100,33070,31630,32140,32980,31910,26510,28700,32450,30350,30620,28170,27090,24020,26210,30630,30010,29060,28280,27480,25640,27380,31170,30140,29880,27080,27190,26540,26100,28950,28390,29580,28430,27180,26900,27890,30370,29010,37710,31070,28200,24050,29250,30280,30940,30400,29590,27840,25070,28680,30740,28600,30670,30550,28430,26900,27170,29890,30590,33270,31990,30770,27010],["y3",930,890,900,980,1120,1250,1220,1030,960,1390,1300,1200,1030,880,1820,1680,1190,1320,1790,1610,1210,1170,1300,1080,1320,1200,970,760,1230,1250,1040,1020,1300,1290,970,900,1050,1040,980,1070,1410,1080,1000,1100,1070,1010,940,1160,1110,990,1070,830,940,1070,1160,1040,1020,1120,1210,3030,2530,1660,1170,1240,1180,1000,1170,720,1010,1300,1020,1180,1080,960,1050,880,950,970,1360,1020,1280,1140,1150,1100,1100,1260,1280,1540,1360,1250,1060,1330,930,1060,940,1190,1320,1180,1050,1210,1370,1330,950,1270,1130,1300,1170,1530,1110,1380,1240,1390,1150,1230,1340,1160,1140,1380,1690,1460,1240,1610,1320,1360,1320,1460,1450,1330,1080,1720,1600,1250,1570,1530,1610,1860,1450,1560,1690,1560,1730,1600,2170,1540,1940,1430,1410,1840,1790,1850,1620,1520,2190,1870,1550,2080,1560,1720,2040,1810,1890,2000,1900,2270,2060,1890,1930,1590,2030,1890,1810,1620,1690,1310,1700,1530,1970,2080,1620,1510,1990,1720,1750,1870,1740,1620,1840,1980,1910,1790,2080,1820,1530,2140,2440,2130,2430,2180,2080,2190,2090,1910,2440,1940,2680,3310,2510,2200,3020,2550,2450,2800,2450,2780,3020,2680,2210,2550,3160,2870,2690,3140,2820,2850,2160,2540,3050,2720,2540,3000,2630,2660,2780,2350,2510,2980,2650,2770,2220,3000,2950,2450,2610,2270,2200,2200,2920,2600,2470,2180,2480,2400,2450,2970,2830,2740,2680,2750,2200,2720,2270,3100,3510,3400,2920,2240,2330,2660,3400,3240,2940,3300,3760,3270,3460,3340,2820,2300,2830,2690,2760,2570,2420,2730,2480,3000,3260,2920,2750,2660,3130,3480,2530,3140,2200,2970,2900,2510,2500,2660,2970,2810,3200,2640,2790,3360,2690,2750,2810,3090,3080,2490,2810,2570,2630,2370,3320,2610,2300,2670,2470,2680,3270,3580,3000,2670,2540,2740,2940,2800,3590,3000,3130,3030,2460,2400,2610,3240,4010,2880,2930,2890,3240,2600,3530,2850,3580,3480,3210,3150,2730,3240,2720,3210,3090,3310,2670,2750,2540,2600,2930,3400,3050,3480,2930],["y4",2090,2070,2080,2490,2580,2210,2670,2940,2280,2520,2840,2480,3150,2590,2630,2490,3220,2390,2430,2490,2490,1520,1680,2680,2240,2630,2440,2340,2430,2710,2670,2420,2210,2750,3630,2450,2650,2330,2120,2310,2280,2500,2310,2410,2210,2210,2550,2690,2190,2030,1940,1790,3250,3370,2580,2330,2190,2270,2460,2310,2030,3070,2440,1820,2260,1580,2070,2230,2890,2430,1540,2450,2590,2200,2470,2790,2430,1960,2370,2470,2880,2960,2140,2420,1570,2530,2430,2850,2290,2380,2450,3150,3240,2100,2210,2580,2780,2880,2220,2290,2560,2550,3230,3760,4940,2460,2890,3120,3950,3170,2850,3480,2160,2770,3070,4080,2860,2950,2550,3890,3760,5150,7520,5950,4400,3150,2820,3390,3740,3140,3480,2480,2980,4740,3230,3370,3970,3730,3910,3890,2250,3340,5110,4360,3940,3030,3130,3470,3470,4230,3190,2950,5310,4600,3540,3170,3780,3210,4020,5060,4180,3710,4540,4070,3530,4100,3950,3810,4960,4750,4030,3760,4790,6930,5160,4060,4490,4500,4410,4950,4850,4380,4500,3270,3620,4910,4160,4520,5990,3080,5560,4510,4190,4390,4380,4260,4240,4260,4650,4630,3880,5130,4430,5030,5610,4420,4200,4300,5710,6660,4860,5620,4330,4120,10220,12330,7070,6430,6420,5510,4970,5390,5910,5440,4760,6080,4730,6690,6130,6050,4920,5310,5860,6880,6510,4860,6470,4960,4820,6520,5230,4350,5110,6100,4660,5110,4780,3790,5480,3560,4670,4530,5010,4590,4350,5670,3950,5150,4430,3630,4390,4090,3730,3380,6720,7270,5950,5350,4280,4400,6240,6950,5740,4400,5100,5880,4670,4710,6370,5630,4960,5780,6110,6070,5160,5280,4890,4560,5700,5030,4770,5370,6800,7150,3830,12010,4190,4320,4520,5850,5830,5670,4670,4980,4330,5050,5820,4610,5920,5160,4690,3980,4380,4450,3670,3440,4870,4330,4510,3880,4830,4850,4290,4400,5830,3760,4940,4670,5020,3920,4480,5410,5410,3750,5490,4150,3990,3910,4460,4240,3770,5000,4520,5000,4070,5080,4710,4440,5540,5280,5960,5260,4480,5540,6320,6150,5610,4900,4300,5010,5440,4450,5570,5840,4530],["y5",2520,2490,3090,2800,2820,3140,2780,2780,2770,2770,2960,2660,3010,2590,2670,2800,2630,2860,2590,2930,3020,2520,1990,2740,2540,2950,2920,3190,2610,2710,2900,3340,3240,2920,2870,2610,2600,2660,3110,3080,3260,2790,3140,2510,2940,2700,2780,3010,3010,2440,2750,3250,3500,3190,3150,2720,2550,2580,3060,2820,2640,2980,2720,2440,2270,3010,3150,3160,2830,2710,2420,2870,3130,2860,2840,2940,2780,2630,2770,2690,3100,3050,3020,2830,2270,2630,2550,3260,3120,2500,2720,2360,2170,3180,3410,2830,3250,2890,2680,2500,3730,3290,2790,2660,3160,2780,2490,3480,2990,2980,3110,3550,2900,2560,2920,3210,3410,3340,3190,3370,3430,3370,3380,3570,3360,3280,2920,3100,3250,3620,2640,2920,3370,2890,3210,3700,3880,3340,3630,3810,3960,4240,3680,3690,3540,3900,4130,3230,3430,4060,4240,3920,3950,4300,3340,3290,3670,3410,3640,4180,3560,3160,3060,3920,3980,4390,3810,3960,3590,4130,4310,3970,3870,4080,4170,3850,3750,3930,3880,3770,3970,3810,3910,3960,4180,4420,4390,4460,4420,2620,4500,4300,4470,4590,4580,4470,4120,4610,4730,5040,4970,5170,4990,4210,4870,5340,5170,4530,5560,5230,4300,5140,5630,5780,5400,5200,5310,5130,5480,5260,5780,5750,5350,5460,4670,4900,6280,6380,6580,6710,7110,5210,5230,5790,5720,5340,5510,5090,4550,5150,5370,5460,5550,5600,5510,5140,4960,5160,5180,5260,5340,5030,4750,5150,5030,5220,4620,5250,5000,4650,4080,4320,4360,4160,5420,5690,4580,4600,3750,4000,4990,5070,5510,5480,5260,5840,5330,5930,5640,5150,5560,4640,6140,5560,5880,6310,5370,5160,4920,5550,5730,5410,5180,5820,4790,5990,4960,5490,5540,5500,5140,5000,4960,5650,5440,5360,5790,5360,4690,5370,5490,5280,5510,5840,5720,4590,4760,5380,5220,5310,5300,5400,4540,4900,5140,5360,5540,5310,5480,4690,4800,5320,5900,5450,5250,4900,4410,4760,5150,5110,5890,5900,5460,4770,5100,5700,5560,5510,5700,5080,4880,4950,5880,5840,5470,5450,5320,4490,4090,5870,5420,6160,6240,5640,4530],["y6",120,60,90,70,50,60,110,150,100,60,70,50,60,80,130,80,90,130,170,80,160,100,90,100,90,40,90,100,80,100,110,100,80,120,180,160,110,50,60,50,20,110,130,120,50,40,110,110,70,140,150,70,50,110,30,70,130,110,140,60,60,80,170,110,140,60,40,140,60,160,150,90,70,150,130,100,80,110,100,30,80,80,130,130,150,130,160,70,70,70,80,200,80,80,80,50,70,80,70,90,50,70,120,140,110,170,180,90,70,80,100,150,220,170,90,120,140,90,190,190,100,110,80,180,150,140,150,220,170,120,160,130,170,150,190,200,120,100,130,210,190,100,100,180,130,80,90,230,130,100,120,120,110,100,140,140,50,100,100,100,150,140,110,120,80,100,70,150,120,100,100,100,130,110,110,190,170,210,100,90,130,210,180,90,160,90,70,120,190,140,100,100,100,160,160,200,190,190,100,90,140,180,120,170,130,60,50,160,130,170,280,160,130,140,170,110,240,220,150,110,150,80,180,150,70,190,80,150,220,210,160,170,90,120,50,180,180,130,220,100,150,200,110,280,180,150,190,140,60,120,100,110,180,100,140,120,200,180,220,170,160,70,140,150,210,120,200,80,330,90,100,140,60,100,160,50,80,120,80,120,170,80,80,110,80,70,210,140,190,60,100,120,60,170,240,200,70,80,80,120,160,90,120,100,130,180,110,130,240,130,90,80,150,150,240,250,140,80,130,170,120,120,170,110,80,170,150,130,190,210,180,120,50,100,180,210,170,150,120,110,170,160,220,140,150,160,130,120,60,230,170,270,120,160,200,160,150,180,210,200,150,110,120,160,210]],"types":{"y0":"bar","y1":"bar","y2":"bar","y3":"bar","y4":"bar","y5":"bar","y6":"bar","x":"x"},"names":{"y0":"Apples","y1":"Oranges","y2":"Lemons","y3":"Apricots","y4":"Kiwi","y5":"Mango","y6":"Pears"},"colors":{"y0":"#3497ED","y1":"#2373DB","y2":"#9ED448","y3":"#5FB641","y4":"#F5BD25","y5":"#F79E39","y6":"#E65850"},"stacked":true}
--------------------------------------------------------------------------------