Skip to content

Commit

Permalink
feat: add legendColorKey property to series options (#239)
Browse files Browse the repository at this point in the history
  • Loading branch information
artemmufazalov authored Jan 30, 2025
1 parent 8ccbc6b commit 87f590b
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 6 deletions.
39 changes: 39 additions & 0 deletions demo/examples/legend.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ <h1>Legend</h1>
<div id="chart7" class="container"></div>
</div>

<h2>Charts with semi-transparent colors</h2>
<div>To prevent transparent colors in legend and tooltip,
you can set <b>'lineColor'</b> to them with <b>legendColorKey</b> serie option</div>
<div class="grid">
<div id="chart8" class="container"></div>
</div>

<script>
const y1 = new Yagr(chart1, {
title: {text: 'On top'},
Expand Down Expand Up @@ -198,6 +205,38 @@ <h1>Legend</h1>
position: 'top',
},
});

const timeline = Array(50).fill(0.2).map((v, i) => v * i)
const data1 = timeline.map(x => Math.sin(x))
const data2 = timeline.map(x => Math.cos(x))

const y8 = new Yagr(chart8, {
timeline: timeline,
series: [
{
name: "sin(x)",
data: data1,
color: 'rgba(126, 178, 109, 0.1)',
lineColor: 'rgba(126, 178, 109)',
type: 'area',
legendColorKey: 'lineColor'
},
{
name: "cos(x)",
data: data2,
color: 'rgba(110, 208, 224, 0.1)',
lineColor: 'rgba(110, 208, 224)',
type: 'area',
legendColorKey: 'lineColor'
},
],
scales: {
y: {min: -1.5, max: 1.5},
},
legend: {
show: true,
},
});
</script>
</body>
</html>
4 changes: 3 additions & 1 deletion docs/en/api/series.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ Series type adds extra features to [uPlot series](https://github.com/leeoniya/up

- `series.width?: number` - line width (line type charts)

- `series.lineColor? string` - line color (area type charts)
- `series.lineColor?: string` - line color (area type charts)

- `series.legendColorKey?: 'color' | 'lineColor'` - determines which color field to use for serie in legend and tooltip

- `series.lineWidth?: number` - line width over area (area type charts)

Expand Down
20 changes: 20 additions & 0 deletions src/YagrCore/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,26 @@ class Yagr<TConfig extends MinimalValidConfig = MinimalValidConfig> {
return this.uplot.series[this.state.y2uIdx[id]];
}

getSerieLegendColor(serie: Series) {
const {legendColorKey, color, lineColor} = serie;

let serieColor = color;

switch (legendColorKey) {
case 'lineColor': {
if (lineColor) {
serieColor = lineColor;
}
break;
}
case 'color': {
serieColor = color;
}
}

return serieColor;
}

dispose() {
this.resizeOb && this.resizeOb.unobserve(this.root);
this.unsubscribe();
Expand Down
2 changes: 1 addition & 1 deletion src/YagrCore/plugins/legend/legend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ export default class LegendPlugin {
private createIconLineElement(serie: Series) {
const iconLineElement = html('span', {
class: `yagr-legend__icon yagr-legend__icon_${serie.type}`,
style: {'background-color': serie.color},
style: {'background-color': this.yagr.getSerieLegendColor(serie)},
});

return iconLineElement;
Expand Down
2 changes: 1 addition & 1 deletion src/YagrCore/plugins/tooltip/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ class YagrTooltip {
value: displayValue,
y: yValue,
displayY: realY,
color: serie.color,
color: this.yagr.getSerieLegendColor(serie),
seriesIdx,
rowIdx: section.rows.length ? section.rows[section.rows.length - 1].rowIdx + 1 : 0,
};
Expand Down
9 changes: 9 additions & 0 deletions src/YagrCore/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,15 @@ export interface CommonSeriesOptions {
* Use at your own risk
**/
postProcess?: (data: (number | null)[], idx: number, y: Yagr) => (number | null)[];

/**
* Determines what data value should be used to get a color for legend and tooltip.
* - `lineColor` indicates that lineColor property should be used
* - `color` indicates that color property should be used
*
* @default 'color'
*/
legendColorKey?: 'color' | 'lineColor';
}

export interface LineSeriesOptions extends CommonSeriesOptions {
Expand Down
52 changes: 50 additions & 2 deletions tests/plugins/legend.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Series } from 'uplot';
import {MinimalValidConfig} from '../../src';
import {Series} from 'uplot';
import {AreaSeriesOptions, ExtendedSeriesOptions, MinimalValidConfig} from '../../src';
import Yagr from '../../src/YagrCore';
import {DEFAULT_X_SERIE_NAME} from '../../src/YagrCore/defaults';
import {hasOneVisibleLine} from '../../src/YagrCore/plugins/legend/legend';
Expand Down Expand Up @@ -69,6 +69,54 @@ describe('legend', () => {
});
});

describe('color', () => {
afterEach(() => {
el.innerHTML = '';
});

const serie: ExtendedSeriesOptions & AreaSeriesOptions = {
type: 'area',
data: [1, 2, 3, 4],
id: '1',
color: 'rgba(255, 0, 0, 0.1)',
lineColor: 'rgb(255, 0, 0)',
};

const colorTestConfig: MinimalValidConfig = {
series: [serie],
timeline: [1, 2, 3, 4],
legend: {
show: true,
position: 'top',
},
};

it('should use color for legend if there is no legendColorKey', () => {
const y = new Yagr(el, {
...colorTestConfig,
});

expect(y.root.querySelector('.yagr-legend')).toBeTruthy();

const legendIcon = y.root.querySelector('.yagr-legend .yagr-legend__icon') as HTMLSpanElement;

expect(legendIcon.style.background).toBe('rgba(255, 0, 0, 0.1)');
});

it('should use lineColor for legend if legendColorKey is lineColor', () => {
const y = new Yagr(el, {
...colorTestConfig,
series: [{...colorTestConfig.series[0], legendColorKey: 'lineColor'}],
});

expect(y.root.querySelector('.yagr-legend')).toBeTruthy();

const legendIcon = y.root.querySelector('.yagr-legend .yagr-legend__icon') as HTMLSpanElement;

expect(legendIcon.style.background).toBe('rgb(255, 0, 0)');
});
});

describe('basic interaction', () => {
it('should toggle series on click', async () => {
const y = new Yagr(el, {
Expand Down
44 changes: 43 additions & 1 deletion tests/plugins/tooltip.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {MinimalValidConfig, TooltipHandler} from '../../src';
import {AreaSeriesOptions, ExtendedSeriesOptions, MinimalValidConfig, TooltipHandler} from '../../src';
import Yagr from '../../src/YagrCore';

const gen = (cfg: MinimalValidConfig) => {
Expand Down Expand Up @@ -49,6 +49,48 @@ describe('tooltip', () => {
});
});

describe('color', () => {
const serie: ExtendedSeriesOptions & AreaSeriesOptions = {
type: 'area',
data: [1, 2, 3, 4],
id: '1',
color: 'rgba(255, 0, 0, 0.1)',
lineColor: 'rgb(255, 0, 0)',
};

const colorTestConfig: MinimalValidConfig = {
series: [serie],
timeline: [1, 2, 3, 4],
};

it('should use color for tooltip if there is no legendColorKey', () => {
const yagr = gen({...colorTestConfig});

yagr.uplot.setCursor({left: 10, top: 10});

const tooltipElem = window.document.querySelector(`#${yagr.id}_tooltip`) as HTMLElement;

const legendIcon = tooltipElem.querySelector('.yagr-tooltip__mark') as HTMLSpanElement;

expect(legendIcon.style.background).toBe('rgba(255, 0, 0, 0.1)');
});

it('should use lineColor for tooltip if legendColorKey is lineColor', () => {
const yagr = gen({
...colorTestConfig,
series: [{...colorTestConfig.series[0], legendColorKey: 'lineColor'}],
});

yagr.uplot.setCursor({left: 10, top: 10});

const tooltipElem = window.document.querySelector(`#${yagr.id}_tooltip`) as HTMLElement;

const legendIcon = tooltipElem.querySelector('.yagr-tooltip__mark') as HTMLSpanElement;

expect(legendIcon.style.background).toBe('rgb(255, 0, 0)');
});
});

describe('perScale', () => {
const y = gen({
timeline: [1, 2, 3, 4],
Expand Down

0 comments on commit 87f590b

Please sign in to comment.