Skip to content

Commit

Permalink
feat(api): use api and spec together
Browse files Browse the repository at this point in the history
  • Loading branch information
pearmini committed May 23, 2023
1 parent af6e892 commit 8d0f065
Show file tree
Hide file tree
Showing 4 changed files with 351 additions and 35 deletions.
205 changes: 205 additions & 0 deletions __tests__/unit/api/options.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import { Chart } from '../../../src';
import { Point } from '../../../src/api/mark/mark';

describe('chart api and options', () => {
it('chart.options({...}) should create node instance from spec.', () => {
const chart = new Chart({});

chart.options({
type: 'interval',
data: [
{ genre: 'Sports', sold: 275 },
{ genre: 'Strategy', sold: 115 },
{ genre: 'Action', sold: 120 },
{ genre: 'Shooter', sold: 350 },
{ genre: 'Other', sold: 150 },
],
encode: {
x: 'genre',
y: 'sold',
},
});

expect(chart.getNodeByType('view')).toBeDefined();
expect(chart.getNodeByType('interval')).toBeDefined();
});

it('chart.options({...}) should bubble view options', () => {
const chart = new Chart({});

chart.options({
type: 'interval',
width: 100,
height: 100,
padding: 10,
paddingLeft: 10,
paddingRight: 10,
paddingBottom: 10,
paddingTop: 10,
inset: 10,
insetLeft: 10,
insetRight: 10,
insetTop: 10,
insetBottom: 10,
margin: 10,
marginLeft: 10,
marginRight: 10,
marginTop: 10,
marginBottom: 10,
autoFit: 10,
theme: 10,
});

expect(chart.options()).toEqual({
type: 'view',
width: 100,
height: 100,
padding: 10,
paddingLeft: 10,
paddingRight: 10,
paddingBottom: 10,
paddingTop: 10,
inset: 10,
insetLeft: 10,
insetRight: 10,
insetTop: 10,
insetBottom: 10,
margin: 10,
marginLeft: 10,
marginRight: 10,
marginTop: 10,
marginBottom: 10,
autoFit: 10,
theme: 10,
children: [{ type: 'interval' }],
});
});

it('chart.options({...}) should create nested node tree from spec.', () => {
const chart = new Chart({});
const options = {
type: 'spaceFlex',
flex: [1, 2],
children: [
{
type: 'spaceLayer',
children: [
{
type: 'view',
children: [
{ type: 'interval', data: [2, 3, 4] },
{ type: 'point' },
],
},
],
},
{ type: 'interval', data: [1, 2, 3] },
],
};

chart.options(options);

expect(chart.options()).toEqual(options);
expect(chart.getNodeByType('point')).toBeInstanceOf(Point);
});

it('chart.options({...}) should update node with same height and index.', () => {
const chart = new Chart({});

chart.options({
type: 'view',
children: [{ type: 'interval' }],
});

chart.options({
children: [{ data: [1, 2, 3] }],
});

expect(chart.getNodeByType('interval').value.data).toEqual([1, 2, 3]);
});

it('chart.options({...}) should update nested node tree.', () => {
const chart = new Chart({});

chart.options({
type: 'spaceFlex',
flex: [1, 2],
children: [
{
type: 'spaceLayer',
children: [
{
type: 'view',
children: [
{ type: 'interval', data: [2, 3, 4] },
{ type: 'point' },
],
},
],
},
{ type: 'interval', data: [1, 2, 3] },
],
});

chart.options({
flex: [2, 3, 4],
children: [
{ children: [{ children: [{}, { data: [1, 2, 3] }] }] },
{ data: [2, 3, 4], scale: { x: { nice: true } } },
],
});

expect(chart.options()).toEqual({
type: 'spaceFlex',
flex: [2, 3, 4],
children: [
{
type: 'spaceLayer',
children: [
{
type: 'view',
children: [
{ type: 'interval', data: [2, 3, 4] },
{ type: 'point', data: [1, 2, 3] },
],
},
],
},
{ type: 'interval', data: [2, 3, 4], scale: { x: { nice: true } } },
],
});
});

it('chart.options({...}) should transform node.', () => {
const chart = new Chart({});

chart.options({
type: 'view',
children: [
{ type: 'interval', scale: { x: { nice: true } }, data: [1, 2, 3] },
],
});

chart.options({
type: 'view',
children: [{ type: 'line', data: [4, 5, 6] }],
});

const line = chart.getNodeByType('line');
expect(line.type).toBe('line');
expect(line.value).toEqual({ data: [4, 5, 6] });
});

it('chart.options({...}) should update node tree specified by API.', () => {
const chart = new Chart({});

const interval = chart.interval().data([1, 2, 3]);

chart.options({
type: 'view',
children: [{ data: [2, 3, 4] }],
});

expect(interval.data()).toEqual([2, 3, 4]);
});
});
28 changes: 13 additions & 15 deletions src/api/chart.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IRenderer, RendererPlugin, Canvas as GCanvas } from '@antv/g';
import { Renderer as CanvasRenderer } from '@antv/g-canvas';
import { Plugin as DragAndDropPlugin } from '@antv/g-plugin-dragndrop';
import { debounce, deepMix } from '@antv/util';
import { debounce } from '@antv/util';
import EventEmitter from '@antv/event-emitter';
import { G2Context, render, destroy } from '../runtime';
import { ViewComposition } from '../spec';
Expand All @@ -27,6 +27,8 @@ import {
removeContainer,
sizeOf,
optionsOf,
updateRoot,
VIEW_KEYS,
} from './utils';

export const G2_CHART_KEY = 'G2_CHART_KEY';
Expand Down Expand Up @@ -84,7 +86,6 @@ export class Chart extends View<ChartOptions> {
private _container: HTMLElement;
private _context: G2Context;
private _emitter: EventEmitter;
private _options: G2ViewTree;
private _width: number;
private _height: number;
private _renderer: IRenderer;
Expand Down Expand Up @@ -161,20 +162,11 @@ export class Chart extends View<ChartOptions> {
* @returns {Chart|G2ViewTree}
*/
options(options?: G2ViewTree): Chart | G2ViewTree {
if (arguments.length === 0) {
return this._options || optionsOf(this);
}
this._options = deepMix(this._options || optionsOf(this), options);
if (arguments.length === 0) return optionsOf(this);
updateRoot(this, options);
return this;
}

// @todo Remove it when implement updateRoot.
changeData(data: any): Promise<Chart> {
// Update options data.
this.options({ data });
return super.changeData(data);
}

getContainer(): HTMLElement {
return this._container;
}
Expand Down Expand Up @@ -206,7 +198,7 @@ export class Chart extends View<ChartOptions> {
clear() {
const options = this.options();
this.emit(ChartEvent.BEFORE_CLEAR);
this._options = {};
this._reset();
destroy(options, this._context, false);
this.emit(ChartEvent.AFTER_CLEAR);
}
Expand All @@ -215,7 +207,7 @@ export class Chart extends View<ChartOptions> {
const options = this.options();
this.emit(ChartEvent.BEFORE_DESTROY);
this._unbindAutoFit();
this._options = {};
this._reset();
destroy(options, this._context, true);
removeContainer(this._container);
this.emit(ChartEvent.AFTER_DESTROY);
Expand Down Expand Up @@ -252,6 +244,12 @@ export class Chart extends View<ChartOptions> {
return finished;
}

private _reset() {
this.type = 'view';
this.value = {};
this.children = [];
}

private _onResize = debounce(() => {
this.forceFit();
}, 300);
Expand Down
8 changes: 8 additions & 0 deletions src/api/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ export class Node<
return nodes;
}

getNodeByType(type: string): Node {
let node;
bfs(this, (current: Node) => {
if (type === current.type) node = current;
});
return node;
}

/**
* Apply specified callback to the node value.
*/
Expand Down
Loading

0 comments on commit 8d0f065

Please sign in to comment.