Browse Source

Merge branch 'bar-titles' into 'main'

Bar Annotations

See merge request chartwerk/bar-pod!3
merge-requests/4/merge
Alexander Velikiy 2 years ago
parent
commit
e31ada2e2c
  1. 29
      demo.html
  2. 3
      dist/index.d.ts
  3. 2
      dist/index.js
  4. 5
      dist/types.d.ts
  5. 6375
      package-lock.json
  6. 4
      package.json
  7. 49
      src/index.ts
  8. 8
      src/types.ts

29
demo.html

@ -13,7 +13,7 @@
var pod = new ChartwerkBarPod( var pod = new ChartwerkBarPod(
document.getElementById('chart'), document.getElementById('chart'),
[ [
{ target: 'test11', datapoints: getData(), matchedKey: 'm-1', color: 'red' }, { target: 'test11', datapoints: getData(), matchedKey: 'm-1', color: 'red' },
{ target: 'test12', datapoints: [[100, 10], [200, 20], [300, 10]], matchedKey: 'm-1', color: 'green' }, { target: 'test12', datapoints: [[100, 10], [200, 20], [300, 10]], matchedKey: 'm-1', color: 'green' },
{ target: 'test21', datapoints: [[130, 10], [230, 26], [330, 15]], matchedKey: 'm-2', color: 'yellow'}, { target: 'test21', datapoints: [[130, 10], [230, 26], [330, 15]], matchedKey: 'm-2', color: 'yellow'},
{ target: 'test22', datapoints: [[130, 10], [230, 27], [330, 10]], matchedKey: 'm-2', color: 'blue' }, { target: 'test22', datapoints: [[130, 10], [230, 27], [330, 10]], matchedKey: 'm-2', color: 'blue' },
@ -29,7 +29,11 @@
maxBarWidth: 20, maxBarWidth: 20,
zoomEvents: { zoomEvents: {
scroll: { zoom: { isActive: false }, pan: { isActive: false } }, scroll: { zoom: { isActive: false }, pan: { isActive: false } },
} },
annotations: [
{ key: 'm-1', color: 'red' },
{ key: 'm-2', color: 'green' }
]
} }
); );
console.time('render'); console.time('render');
@ -39,23 +43,14 @@
function getData() { function getData() {
return [ return [
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
[100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10], [100, 15], [110, 20], [300, 10],
]; ];
} }
</script> </script>
</body> </body>
</html> </html>
<style>
.overlay {
fill: black;
}
</style>

3
dist/index.d.ts vendored

@ -2,12 +2,12 @@ import { ChartwerkPod, TickOrientation, TimeFormat, AxisFormat } from '@chartwer
import { BarTimeSerie, BarOptions, RowValues } from './types'; import { BarTimeSerie, BarOptions, RowValues } from './types';
import * as d3 from 'd3'; import * as d3 from 'd3';
export declare class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> { export declare class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
metricsContainer: any;
barYScale: null | d3.ScaleLinear<number, number>; barYScale: null | d3.ScaleLinear<number, number>;
constructor(el: HTMLElement, _series?: BarTimeSerie[], _options?: BarOptions); constructor(el: HTMLElement, _series?: BarTimeSerie[], _options?: BarOptions);
protected renderMetrics(): void; protected renderMetrics(): void;
setBarPodScales(): void; setBarPodScales(): void;
renderSerie(data: any): void; renderSerie(data: any): void;
getTrianglePath(x: number, y: number, length: number): string;
getBarOpacity(rowValues: RowValues): number; getBarOpacity(rowValues: RowValues): number;
mergeMacthedSeriesAndSort(matchedSeries: any[]): any; mergeMacthedSeriesAndSort(matchedSeries: any[]): any;
get seriesUniqKeys(): string[]; get seriesUniqKeys(): string[];
@ -77,6 +77,7 @@ export declare const VueChartwerkBarChartObject: {
panning(range: any): void; panning(range: any): void;
contextMenu(evt: any): void; contextMenu(evt: any): void;
sharedCrosshairMove(event: any): void; sharedCrosshairMove(event: any): void;
renderStart(): void;
renderEnd(): void; renderEnd(): void;
}; };
}[]; }[];

2
dist/index.js vendored

File diff suppressed because one or more lines are too long

5
dist/types.d.ts vendored

@ -12,6 +12,10 @@ export declare type BarOptionsParams = {
minBarWidth: number; minBarWidth: number;
matching: boolean; matching: boolean;
opacityFormatter: (data: RowValues) => number; opacityFormatter: (data: RowValues) => number;
annotations: {
key: string;
color: string;
}[];
}; };
export declare type BarOptions = Options & Partial<BarOptionsParams>; export declare type BarOptions = Options & Partial<BarOptionsParams>;
export declare type RowValues = { export declare type RowValues = {
@ -19,4 +23,5 @@ export declare type RowValues = {
values: number[]; values: number[];
additionalValues: (null | number)[]; additionalValues: (null | number)[];
colors: string[]; colors: string[];
serieTarget: string[];
}; };

6375
package-lock.json generated

File diff suppressed because it is too large Load Diff

4
package.json

@ -1,6 +1,6 @@
{ {
"name": "@chartwerk/bar-pod", "name": "@chartwerk/bar-pod",
"version": "0.2.5", "version": "0.2.6",
"description": "Chartwerk bar pod", "description": "Chartwerk bar pod",
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
@ -15,7 +15,7 @@
"author": "CorpGlory", "author": "CorpGlory",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@chartwerk/core": "gitlab:chartwerk/core#23b38f67809f64f021ea40998f8033c9a5100b31" "@chartwerk/core": "0.3.10"
}, },
"devDependencies": { "devDependencies": {
"@types/d3": "^5.7.2", "@types/d3": "^5.7.2",

49
src/index.ts

@ -13,7 +13,6 @@ const DEFAULT_BAR_OPTIONS: BarOptions = {
} }
export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> { export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
metricsContainer: any;
barYScale: null | d3.ScaleLinear<number, number> = null; barYScale: null | d3.ScaleLinear<number, number> = null;
constructor(el: HTMLElement, _series: BarTimeSerie[] = [], _options: BarOptions = {}) { constructor(el: HTMLElement, _series: BarTimeSerie[] = [], _options: BarOptions = {}) {
@ -29,16 +28,6 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
this.setBarPodScales(); this.setBarPodScales();
// container for clip path
const clipContatiner = this.chartContainer
.append('g')
.attr('clip-path', `url(#${this.rectClipId})`)
.attr('class', 'metrics-container');
// container for panning
this.metricsContainer = clipContatiner
.append('g')
.attr('class', ' metrics-rect');
if(this.options.matching === false || this.seriesUniqKeys.length === 0) { if(this.options.matching === false || this.seriesUniqKeys.length === 0) {
const zippedData = this.getZippedDataForRender(this.visibleSeries); const zippedData = this.getZippedDataForRender(this.visibleSeries);
this.renderSerie(zippedData); this.renderSerie(zippedData);
@ -58,11 +47,10 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
} }
renderSerie(data: any): void { renderSerie(data: any): void {
this.metricsContainer.selectAll(`.rects-container`) this.metricContainer.selectAll(`.rects-container`)
.data(data) .data(data)
.enter().append('g') .enter().append('g')
.attr('class', 'rects-container') .attr('class', 'rects-container')
.attr('clip-path', `url(#${this.rectClipId})`)
.each((d: RowValues, i: number, nodes: any) => { .each((d: RowValues, i: number, nodes: any) => {
const container = d3.select(nodes[i]); const container = d3.select(nodes[i]);
container.selectAll('rect') container.selectAll('rect')
@ -79,9 +67,37 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
.attr('width', this.barWidth) .attr('width', this.barWidth)
.attr('height', (val: number) => this.getBarHeight(val)) .attr('height', (val: number) => this.getBarHeight(val))
.on('contextmenu', this.contextMenu.bind(this)); .on('contextmenu', this.contextMenu.bind(this));
// render bar annotations, its all hardcoded
if(_.isEmpty(this.options.annotations)) {
return;
}
// find all series for single matchedKey
const series = _.filter(this.series, serie => _.includes(d.serieTarget, serie.target));
const matchedKeys = _.map(series, serie => serie.matchedKey); // here matchedKeys should be equal
const key = matchedKeys[0];
const lastRect = _.last(container.selectAll('rect')?.nodes());
const annotation = _.find(this.options.annotations, a => a.key === key);
if(!lastRect || !key || !annotation) {
return;
}
const rectSelection = d3.select(lastRect);
// render triangle
container.append('path')
.attr('d', () => {
const x = Math.ceil(_.toNumber(rectSelection.attr('x')));
const y = Math.max(Math.ceil(_.toNumber(rectSelection.attr('y'))) - this.barWidth, 0);
return this.getTrianglePath(x, y, this.barWidth);
})
.attr('fill', annotation.color);
}); });
}
// TODO: render bar labels getTrianglePath(x: number, y: number, length: number): string {
// (x, y) - top left corner
return `M ${x - 2} ${y - 2} L ${x + length + 2} ${y - 2} L ${x + length / 2 } ${y + length - 2} z`;
} }
getBarOpacity(rowValues: RowValues): number { getBarOpacity(rowValues: RowValues): number {
@ -139,8 +155,9 @@ export class ChartwerkBarPod extends ChartwerkPod<BarTimeSerie, BarOptions> {
const zippedAdditionalValuesColumn = _.zip(...additionalValuesColumns); const zippedAdditionalValuesColumn = _.zip(...additionalValuesColumns);
const zippedValuesColumn = _.zip(...valuesColumns); const zippedValuesColumn = _.zip(...valuesColumns);
const colors = _.map(series, serie => this.getBarColor(serie)); const colors = _.map(series, serie => this.getBarColor(serie));
const zippedData = _.zip(keysColumn, zippedValuesColumn, zippedAdditionalValuesColumn); const tagrets = _.map(series, serie => serie.target);
const data = _.map(zippedData, row => { return { key: row[0], values: row[1], additionalValues: row[2], colors } }); const zippedData = _.zip(keysColumn, zippedValuesColumn, zippedAdditionalValuesColumn, tagrets);
const data = _.map(zippedData, row => { return { key: row[0], values: row[1], additionalValues: row[2], colors, serieTarget: tagrets } });
return data; return data;
} }

8
src/types.ts

@ -13,11 +13,17 @@ export type BarOptionsParams = {
minBarWidth: number; // in px minBarWidth: number; // in px
matching: boolean; matching: boolean;
opacityFormatter: (data: RowValues) => number; opacityFormatter: (data: RowValues) => number;
annotations: {
key: string, // matchedKey from series
// TODO: add enum with "triangle" option
color: string,
}[];
} }
export type BarOptions = Options & Partial<BarOptionsParams>; export type BarOptions = Options & Partial<BarOptionsParams>;
export type RowValues = { export type RowValues = {
key: number, key: number,
values: number[], values: number[],
additionalValues: (null | number)[], // values in datapoints third column additionalValues: (null | number)[], // values in datapoints third column
colors: string[] colors: string[],
serieTarget: string[],
} }

Loading…
Cancel
Save