diff --git a/packages/shared/examples/_previews/dual-axis-chart-dark.png b/packages/shared/examples/_previews/dual-axis-chart-dark.png new file mode 100644 index 000000000..220afee22 Binary files /dev/null and b/packages/shared/examples/_previews/dual-axis-chart-dark.png differ diff --git a/packages/shared/examples/_previews/dual-axis-chart.png b/packages/shared/examples/_previews/dual-axis-chart.png new file mode 100644 index 000000000..9a567ec57 Binary files /dev/null and b/packages/shared/examples/_previews/dual-axis-chart.png differ diff --git a/packages/shared/examples/dual-axis-chart/data.ts b/packages/shared/examples/dual-axis-chart/data.ts new file mode 100644 index 000000000..c2c097b98 --- /dev/null +++ b/packages/shared/examples/dual-axis-chart/data.ts @@ -0,0 +1,15 @@ +export type XYDataRecord = { + x: number; + y: number | undefined; + y1?: number; + y2?: number; +} + +export function generateXYDataRecords (n = 10): XYDataRecord[] { + return Array(n).fill(0).map((_, i) => ({ + x: i, + y: 5 + 5 * Math.random(), + y1: 1 + 3 * Math.random(), + y2: 2 * Math.random(), + })) +} diff --git a/packages/shared/examples/dual-axis-chart/dual-axis-chart.component.html b/packages/shared/examples/dual-axis-chart/dual-axis-chart.component.html new file mode 100644 index 000000000..feafb7de2 --- /dev/null +++ b/packages/shared/examples/dual-axis-chart/dual-axis-chart.component.html @@ -0,0 +1,35 @@ + + + + + + + + + \ No newline at end of file diff --git a/packages/shared/examples/dual-axis-chart/dual-axis-chart.component.ts b/packages/shared/examples/dual-axis-chart/dual-axis-chart.component.ts new file mode 100644 index 000000000..363bdc59e --- /dev/null +++ b/packages/shared/examples/dual-axis-chart/dual-axis-chart.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core' +import { XYDataRecord, generateXYDataRecords } from './data' + +@Component({ + selector: 'dual-axis-chart', + templateUrl: './dual-axis-chart.component.html', +}) +export class DualAxisChartComponent { + data = generateXYDataRecords(150) + + margin = { left: 100, right: 100, top: 40, bottom: 60 } + style = { position: 'absolute', top: 0, left: 0, width: '100%', height: '40vh' } + + chartX = (d: XYDataRecord): number => d.x + chartAY = (d: XYDataRecord, i: number): number => i * (d.y || 0) + chartBY = (d: XYDataRecord): number => 20 + 10 * (d.y2 || 0) + xTicks = (x: number): string => `${x}ms` + chartAYTicks = (y: number): string => `${y}bps` + chartBYTicks = (y: number): string => `${y}db` +} diff --git a/packages/shared/examples/dual-axis-chart/dual-axis-chart.module.ts b/packages/shared/examples/dual-axis-chart/dual-axis-chart.module.ts new file mode 100644 index 000000000..d89c64190 --- /dev/null +++ b/packages/shared/examples/dual-axis-chart/dual-axis-chart.module.ts @@ -0,0 +1,11 @@ +import { NgModule } from '@angular/core' +import { VisXYContainerModule, VisAxisModule, VisLineModule, VisAreaModule } from '@unovis/angular' + +import { DualAxisChartComponent } from './dual-axis-chart.component' + +@NgModule({ + imports: [VisXYContainerModule, VisAreaModule, VisAxisModule, VisLineModule], + declarations: [DualAxisChartComponent], + exports: [DualAxisChartComponent], +}) +export class DualAxisChartModule { } diff --git a/packages/shared/examples/dual-axis-chart/dual-axis-chart.svelte b/packages/shared/examples/dual-axis-chart/dual-axis-chart.svelte new file mode 100644 index 000000000..c9addae6b --- /dev/null +++ b/packages/shared/examples/dual-axis-chart/dual-axis-chart.svelte @@ -0,0 +1,65 @@ + + +
+ + + + + + + + + +
+ + diff --git a/packages/shared/examples/dual-axis-chart/dual-axis-chart.ts b/packages/shared/examples/dual-axis-chart/dual-axis-chart.ts new file mode 100644 index 000000000..4fe95c7c9 --- /dev/null +++ b/packages/shared/examples/dual-axis-chart/dual-axis-chart.ts @@ -0,0 +1,59 @@ +import { XYContainer, Area, Line, Axis } from '@unovis/ts' +import { XYDataRecord, generateXYDataRecords } from './data' +import './styles.css' + +const container = document.getElementById('vis-container') +const chartAContainer = document.createElement('div') +container.appendChild(chartAContainer) + +const chartBContainer = document.createElement('div') +chartBContainer.className = 'chartContainer' +container.appendChild(chartBContainer) + +const margin = { left: 100, right: 100, top: 40, bottom: 60 } + +// Area +const area = new Area({ + x: (d: XYDataRecord) => d.x, + y: (d: XYDataRecord, i: number) => i * (d.y || 0), + opacity: 0.9, + color: '#FF6B7E', +}) + +const line = new Line({ + x: (d: XYDataRecord) => d.x, + y: (d: XYDataRecord, i: number) => 20 + 10 * (d.y2 || 0), +}) + +// Container +const chartA = new XYContainer(chartAContainer, { + height: '40vh', + width: '100%', + position: 'absolute', + components: [area], + margin: margin, + autoMargin: false, + xAxis: new Axis({ label: 'Time' }), + yAxis: new Axis({ + label: 'Traffic', + tickFormat: (y: number) => `${y}bps`, + tickTextWidth: 60, + tickTextColor: '#FF6B7E', + labelColor: '#FF6B7E', + }), +}, generateXYDataRecords(150)) + +const chartB = new XYContainer(chartBContainer, { + components: [line], + yDomain: [0, 150], + margin: margin, + autoMargin: false, + yAxis: new Axis({ + position: 'right', + tickFormat: (y: number) => `${y}db`, + gridLine: false, + tickTextColor: '#4D8CFD', + labelColor: '#4D8CFD', + label: 'Signal Strength', + }), +}, generateXYDataRecords(150)) diff --git a/packages/shared/examples/dual-axis-chart/dual-axis-chart.tsx b/packages/shared/examples/dual-axis-chart/dual-axis-chart.tsx new file mode 100644 index 000000000..ac9127c96 --- /dev/null +++ b/packages/shared/examples/dual-axis-chart/dual-axis-chart.tsx @@ -0,0 +1,47 @@ +import React from 'react' +import { VisXYContainer, VisArea, VisLine, VisAxis } from '@unovis/react' + +import { XYDataRecord, generateXYDataRecords } from './data' + +export default function component (): JSX.Element { + const margin = { left: 100, right: 100, top: 40, bottom: 60 } + const style: React.CSSProperties = { position: 'absolute', top: 0, left: 0, width: '100%', height: '40vh' } + return (<> + + x={d => d.x} y={(d: XYDataRecord, i: number) => i * (d.y || 0)} opacity={0.9} color='#FF6B7E' /> + `${x}ms`} label='Time' /> + `${y}bps`} + tickTextWidth={60} + tickTextColor='#FF6B7E' + labelColor='#FF6B7E' + label='Traffic' + /> + + + x={d => d.x} y={d => 20 + 10 * (d.y2 || 0)} /> + `${y}db`} + gridLine={false} + tickTextColor='#4D8CFD' + labelColor='#4D8CFD' + label='Signal Strength' + /> + + + ) +} diff --git a/packages/shared/examples/dual-axis-chart/dual-axis-chart.vue b/packages/shared/examples/dual-axis-chart/dual-axis-chart.vue new file mode 100644 index 000000000..e41bb0eac --- /dev/null +++ b/packages/shared/examples/dual-axis-chart/dual-axis-chart.vue @@ -0,0 +1,51 @@ + + + diff --git a/packages/shared/examples/dual-axis-chart/index.tsx b/packages/shared/examples/dual-axis-chart/index.tsx new file mode 100644 index 000000000..6d190cb06 --- /dev/null +++ b/packages/shared/examples/dual-axis-chart/index.tsx @@ -0,0 +1,32 @@ +/* eslint-disable import/no-unresolved, import/no-webpack-loader-syntax, @typescript-eslint/no-var-requires */ +import React from 'react' +import type { Example } from '../types' + +const pathname = 'dual-axis-chart' +const example: Example = { + component: () => { + // eslint-disable-next-line @typescript-eslint/naming-convention + const Component = require(`./${pathname}.tsx`).default + return + }, + pathname, + title: 'Dual Axis Chart', + description:
+ Randomly Generated Data +
*This example shows how to create dual axis chart by overlapping two charts
+
, + codeReact: require(`!!raw-loader!./${pathname}.tsx`).default, + codeTs: require(`!!raw-loader!./${pathname}.ts`).default, + codeAngular: { + html: require(`!!raw-loader!./${pathname}.component.html`).default, + component: require(`!!raw-loader!./${pathname}.component.ts`).default, + module: require(`!!raw-loader!./${pathname}.module.ts`).default, + }, + codeSvelte: require(`!!raw-loader!./${pathname}.svelte`).default, + codeVue: require(`!!raw-loader!./${pathname}.vue`).default, + data: require('!!raw-loader!./data').default, + preview: require(`../_previews/${pathname}.png`).default, + previewDark: require(`../_previews/${pathname}-dark.png`).default, +} + +export default example diff --git a/packages/shared/examples/dual-axis-chart/styles.css b/packages/shared/examples/dual-axis-chart/styles.css new file mode 100644 index 000000000..e7dd4b020 --- /dev/null +++ b/packages/shared/examples/dual-axis-chart/styles.css @@ -0,0 +1,7 @@ +.chartContainer { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 40vh; +} diff --git a/packages/shared/examples/examples-list.tsx b/packages/shared/examples/examples-list.tsx index 3c1a21a79..cf380f3a1 100644 --- a/packages/shared/examples/examples-list.tsx +++ b/packages/shared/examples/examples-list.tsx @@ -75,6 +75,13 @@ export const examples: ExampleCollection[] = [ require('./sunburst-nested-donut').default, ], }, + { + title: 'Composite Charts', + description: '', + examples: [ + require('./dual-axis-chart').default, + ], + }, { title: 'Auxiliary Components', description: 'Annotations, Brushes, Tooltips and more', diff --git a/packages/svelte/src-demo/svelte-gallery.svelte b/packages/svelte/src-demo/svelte-gallery.svelte index bfba47781..f15683a2e 100644 --- a/packages/svelte/src-demo/svelte-gallery.svelte +++ b/packages/svelte/src-demo/svelte-gallery.svelte @@ -1,5 +1,6 @@