Skip to content

feat: 股票图增强 #2579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
May 24, 2021
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions __tests__/unit/adaptor/geometries/schema-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { schema, SchemaGeometryOptions, P, Params } from '../../../../src';
import { Y_FIELD } from '../../../../src/plots/stock/constant';
import { getStockData } from '../../../../src/plots/stock/utils';
import { createDiv } from '../../../utils/dom';

describe('adaptor - schema', () => {
function adaptor(params: Params<SchemaGeometryOptions>): Params<SchemaGeometryOptions> {
const { chart, options } = params;
const { data } = options;

chart.data(data);

// 直接使用 geometry 进行测试
schema({
chart,
options: {
...options,
schema: {
shape: 'candle',
},
},
});
return params;
}

function getPlot() {
const plot = new P(
createDiv(),
{
width: 400,
height: 300,
data: getStockData(
[
{
ts_code: '000001.SH',
trade_date: '2020-03-13',
close: 2887.4265,
open: 2804.2322,
high: 2910.8812,
low: 2799.9841,
vol: 366450436,
amount: 393019665.2,
},
{
ts_code: '000001.SH',
trade_date: '2020-03-12',
close: 2923.4856,
open: 2936.0163,
high: 2944.4651,
low: 2906.2838,
vol: 307778457,
amount: 328209202.4,
},
{
ts_code: '000001.SH',
trade_date: '2020-03-11',
close: 2968.5174,
open: 3001.7616,
high: 3010.0286,
low: 2968.5174,
vol: 352470970,
amount: 378766619,
},
],
['open', 'close', 'high', 'low']
),
appendPadding: 10,
xField: 'trade_date',
yField: Y_FIELD,
mapping: {},
},
adaptor
);

plot.render();
return plot;
}

it('default', () => {
const plot = getPlot();
expect(plot.chart.geometries[0].elements.length).toBe(3);

plot.destroy();
});
});
43 changes: 43 additions & 0 deletions __tests__/unit/plots/stock/color-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Stock } from '../../../../src';
import { createDiv, removeDom } from '../../../utils/dom';
import { kdata as data } from '../../../data/stock';
import { DEFAULT_OPTIONS } from '../../../../src/plots/stock/constant';

describe('Stock', () => {
const div = createDiv('x*y');
const plot = new Stock(div, {
width: 400,
height: 500,
data,
xField: 'date',
yField: ['start', 'end', 'max', 'min'],
});

it('color', () => {
plot.render();

// 图形元素个数
expect(plot.chart.geometries[0].elements.length).toBe(data.length);
expect(plot.chart.geometries[0].elements[0].shape.attr('fill')).toBe(DEFAULT_OPTIONS.risingFill);
// datum.start < datum.end 上涨
expect(plot.chart.geometries[0].elements[data.length - 2].shape.attr('fill')).toBe(DEFAULT_OPTIONS.fallingFill);
});

it('change color', () => {
plot.update({
// 绿涨红跌
fallingFill: '#ef5350',
risingFill: '#26a69a',
});
// 图形元素个数
expect(plot.chart.geometries[0].elements.length).toBe(data.length);
expect(plot.chart.geometries[0].elements[0].shape.attr('fill')).toBe(DEFAULT_OPTIONS.fallingFill);
// datum.start < datum.end 上涨
expect(plot.chart.geometries[0].elements[data.length - 2].shape.attr('fill')).toBe(DEFAULT_OPTIONS.risingFill);
});

afterAll(() => {
removeDom(div);
plot.destroy();
});
});
29 changes: 29 additions & 0 deletions __tests__/unit/plots/stock/style-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Stock } from '../../../../src';
import { createDiv } from '../../../utils/dom';
import { kdata } from '../../../data/stock';

describe('Stock', () => {
it('set style', () => {
const k = new Stock(createDiv('x*y'), {
width: 400,
height: 500,
data: kdata,
xField: 'date',
yField: ['start', 'end', 'max', 'min'],
style: {
stroke: 'red',
lineWidth: 2,
},
});

k.render();

const geometry = k.chart.geometries[0];

// 图形元素个数
expect(k.chart.geometries[0].elements[0].shape.attr('stroke')).toBe('red');
expect(k.chart.geometries[0].elements[0].shape.attr('lineWidth')).toBe(2);

k.destroy();
});
});
153 changes: 82 additions & 71 deletions __tests__/unit/plots/stock/tooltip-spec.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,49 @@
import { Stock } from '../../../../src';
import { createDiv } from '../../../utils/dom';
import { createDiv, removeDom } from '../../../utils/dom';
import { kdata } from '../../../data/stock';

// import { DEFAULT_TOOLTIP_OPTIONS } from '../../../../src/plots/stock/constant';
// import { pick } from '../../../../src/utils';

describe('Stock tooltip', () => {
it('tooltip: default options', () => {
const k = new Stock(createDiv('default tooltip'), {
width: 400,
height: 500,
data: kdata,
xField: 'date',
yField: ['start', 'end', 'max', 'min'],
});
const div = createDiv('default tooltip');
const k = new Stock(div, {
width: 400,
height: 500,
data: kdata,
xField: 'date',
yField: ['start', 'end', 'max', 'min'],
});

k.render();
k.render();
it('tooltip: default options', () => {
// @ts-ignore
expect(k.chart.options.tooltip.shared).toBe(true);
// @ts-ignore
expect(k.chart.options.tooltip.showCrosshairs).toBe(true);
// @ts-ignore
expect(k.chart.options.tooltip.showTitle).toBe(false);
// @ts-ignore
expect(k.chart.options.tooltip.showMarkers).toBe(false);
});

// @ts-ignore
// expect(pick(k.chart.options.tooltip, Object.keys(DEFAULT_TOOLTIP_OPTIONS))).toEqual(DEFAULT_TOOLTIP_OPTIONS);
it('tooltip: default show fields of yField', () => {
const geometry = k.chart.geometries[0];
const elements = geometry.elements;
const bbox = elements[0].getBBox();

k.destroy();
// 正常渲染某个元素tooltip
k.chart.showTooltip({ x: bbox.minX + bbox.width / 2, y: bbox.y + bbox.height / 2 });

expect(div.querySelectorAll('.g2-tooltip-list-item').length).toBe(k.options.yField.length);

// 设置hide
k.chart.hideTooltip();
});

it('tooltip: options', () => {
const k = new Stock(createDiv('tooltip: options'), {
width: 400,
height: 500,
data: kdata,
xField: 'date',
yField: ['start', 'end', 'max', 'min'],
it('tooltip: showTitle', () => {
k.update({
tooltip: {
showTitle: true,
title: 'hello world',
},
});

k.render();

// @ts-ignore
expect(k.chart.options.tooltip.showTitle).toBe(true);
// @ts-ignore
Expand All @@ -58,17 +56,10 @@ describe('Stock tooltip', () => {
// @ts-ignore
expect(k.chart.options.tooltip).toBe(false);
expect(k.chart.getComponents().find((co) => co.type === 'tooltip')).toBe(undefined);

k.destroy();
});

it('tooltip: custom itemTpl', () => {
const k = new Stock(createDiv('custom itemTpl'), {
width: 400,
height: 500,
data: kdata,
xField: 'date',
yField: ['start', 'end', 'max', 'min'],
k.update({
tooltip: {
itemTpl:
'<li class="g2-tooltip-list-item custom-item-tpl" data-index={index} style="margin-bottom:4px;">' +
Expand All @@ -79,68 +70,86 @@ describe('Stock tooltip', () => {
},
});

k.render();

const geometry = k.chart.geometries[0];
const elements = geometry.elements;
const bbox = elements[elements.length - 1].getBBox();

// 渲染自定义itemTpl
k.chart.showTooltip({ x: bbox.maxX, y: bbox.maxY });
k.chart.showTooltip({ x: bbox.minX + bbox.width / 2, y: bbox.y + bbox.height / 2 });
expect(document.getElementsByClassName('custom-item-tpl')[0].innerHTML).not.toBeNull();

k.destroy();
// 设置hide
k.chart.hideTooltip();
});

it('tooltip: change the configuration && operation', () => {
const k = new Stock(createDiv('change the configuration && operation'), {
width: 400,
height: 500,
data: kdata,
xField: 'date',
yField: ['start', 'end', 'max', 'min'],
it('tooltip: fields', () => {
k.update({
tooltip: {
fields: ['start', 'end', 'max', 'min', 'volumn'],
},
});

k.render();
const geometry = k.chart.geometries[0];
const elements = geometry.elements;
const bbox = elements[0].getBBox();

// 正常渲染某个元素tooltip
k.chart.showTooltip({ x: bbox.minX + bbox.width / 2, y: bbox.y + bbox.height / 2 });

expect(div.querySelectorAll('.g2-tooltip-list-item').length).toBe(5);

// 设置hide
k.chart.hideTooltip();
});

// fixme https://github.com/antvis/G2/issues/3435
it.skip('tooltip: fields & formatter', () => {
k.update({
tooltip: {
fields: ['start', 'end', 'max', 'min', 'volumn'],
formatter: () => ({ name: 'x', value: 'a' }),
},
});

const geometry = k.chart.geometries[0];
const elements = geometry.elements;
const bbox = elements[elements.length - 1].getBBox();

// 正常渲染某个元素tooltip
k.chart.showTooltip({ x: bbox.maxX, y: bbox.maxY });
expect(document.getElementsByClassName('g2-tooltip-list-item')[0].innerHTML).not.toBeNull();
k.chart.showTooltip({ x: bbox.minX + bbox.width / 2, y: bbox.y + bbox.height / 2 });
expect(div.getElementsByClassName('g2-tooltip-list-item').length).toBe(5);

// 设置hide
k.chart.hideTooltip();
});

it('tooltip: fields & customContent', () => {
k.update({
...k.options,
tooltip: false,
tooltip: {
fields: ['start', 'end', 'max'],
customContent: (text, items) =>
`<div>${items.map((item, idx) => `<div class="custom-tooltip-item-content">${idx}</div>`)}<div>`,
},
});
// @ts-ignore
expect(k.chart.options.tooltip).toBe(false);
expect(k.chart.getComponents().find((co) => co.type === 'tooltip')).toBe(undefined);

k.destroy();
const elements = k.chart.geometries[0].elements;
const bbox = elements[elements.length - 1].getBBox();

// 正常渲染某个元素tooltip
k.chart.showTooltip({ x: bbox.minX + bbox.width / 2, y: bbox.y + bbox.height / 2 });
expect(div.getElementsByClassName('custom-tooltip-item-content').length).toBe(3);

// 设置hide
k.chart.hideTooltip();
});

it('tooltip: custom crosshairs', () => {
const k = new Stock(createDiv('custom crosshairs'), {
width: 400,
height: 500,
data: kdata,
xField: 'date',
yField: ['start', 'end', 'max', 'min'],
it('tooltip: custom crosshairs', () => {
k.update({
tooltip: {
crosshairs: {
type: 'xy',
follow: true,
text: (
type, // 对应当前 crosshairs 的类型,值为 'x' 或者 'y'
defaultContent, // 对应当前 crosshairs 默认的文本内容
items, // 对应当前 tooltip 内容框中的数据
currentPoint // 对应当前坐标点
) => {
console.log(type, defaultContent, items, currentPoint);
text: () => {
return {
content: 'custom text',
};
Expand All @@ -149,12 +158,14 @@ describe('Stock tooltip', () => {
},
});

k.render();

// @ts-ignore
expect(k.chart.options.tooltip.crosshairs.text()).not.toBeUndefined();
// @ts-ignore
expect(k.chart.options.tooltip.crosshairs.text().content).toBe('custom text');
});

afterAll(() => {
k.destroy();
removeDom(div);
});
});
Loading