Skip to content

Commit

Permalink
feat: getSnapshot支持饼图 (#1380)
Browse files Browse the repository at this point in the history
  • Loading branch information
ACERY1 authored Mar 7, 2022
1 parent 254262a commit c3a0a04
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 11 deletions.
1 change: 1 addition & 0 deletions packages/f2/src/chart/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ class Chart extends Component implements IChart, InteractionMixin {
getGeometrys() {
const { children } = this;
const geometrys: Component[] = [];
// @ts-ignore
Children.toArray(children).forEach((element) => {
if (!element) return false;
const { component } = element;
Expand Down
46 changes: 38 additions & 8 deletions packages/f2/src/components/geometry/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -433,14 +433,15 @@ class Geometry<T extends GeometryProps = GeometryProps> extends Component<T> {
return this.getAttr('y').scale;
}

_getSnap(scale, invertPointX) {
if (scale.isCategory) {
return scale.invert(invertPointX);
_getXSnap(invertPointX) {
const xScale = this.getXScale();
if (xScale.isCategory) {
return xScale.invert(invertPointX);
}

// linear 类型
const invertValue = scale.invert(invertPointX);
const values = scale.values;
const invertValue = xScale.invert(invertPointX);
const values = xScale.values;
const len = values.length;
// 如果只有1个点直接返回第1个点
if (len === 1) {
Expand All @@ -466,6 +467,24 @@ class Geometry<T extends GeometryProps = GeometryProps> extends Component<T> {
return null;
}

_getYSnapRecords(invertPointY, records) {
const yScale = this.getYScale();
const { field: yField } = yScale;
const yValue = yScale.invert(invertPointY);
// category
if (yScale.isCategory) {
return records.filter((record) => record[FIELD_ORIGIN][yField] === yValue);
}
// linear
return records.filter((record) => {
const rangeY = record[yField];
if (rangeY[0] <= yValue && rangeY[1] >= yValue) {
return true;
}
return false;
});
}

// 把 records 拍平
flatRecords() {
const { records } = this;
Expand All @@ -476,7 +495,7 @@ class Geometry<T extends GeometryProps = GeometryProps> extends Component<T> {

getSnapRecords(point) {
const { props } = this;
const { coord } = props;
const { coord, adjust } = props;
const invertPoint = coord.invertPoint(point);
const xScale = this.getXScale();
const yScale = this.getYScale();
Expand All @@ -486,14 +505,24 @@ class Geometry<T extends GeometryProps = GeometryProps> extends Component<T> {
return [];
}

const records = this.flatRecords();

// 处理饼图
if (adjust === 'stack' && coord.isPolar && coord.transposed) {
// 弧度在半径范围内
if (invertPoint.x >= 0 && invertPoint.x <= 1) {
const snapRecords = this._getYSnapRecords(invertPoint.y, records);
return snapRecords;
}
}

const rst = [];
const value = this._getSnap(xScale, invertPoint.x);
const value = this._getXSnap(invertPoint.x);
if (!value) {
return rst;
}
const { field: xField } = xScale;
const { field: yField } = yScale;
const records = this.flatRecords();
for (let i = 0, len = records.length; i < len; i++) {
const record = {
...records[i],
Expand All @@ -507,6 +536,7 @@ class Geometry<T extends GeometryProps = GeometryProps> extends Component<T> {
rst.push(record);
}
}

return rst;
}

Expand Down
38 changes: 38 additions & 0 deletions packages/f2/src/coord/polar.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Base from './base';
import { Range, Option } from './types';
import { Vector2, Matrix } from '@antv/f2-graphic';

interface PolarOption extends Option {
radius: number; // 内半径比例
Expand Down Expand Up @@ -64,6 +65,43 @@ class Polar extends Base {
y: center.y + Math.sin(angle) * radius,
};
}

invertPoint(point) {
const { center, transposed, x: rangeX, y: rangeY } = this;
const x = { start: rangeX[0], end: rangeX[1] }
const y = { start: rangeY[0], end: rangeY[1] }
const xDim = transposed ? 'y' : 'x';
const yDim = transposed ? 'x' : 'y';

const m = [1, 0, 0, 1, 0, 0];
Matrix.rotate(m, m, x.start);

let startV = [1, 0];
Vector2.transformMat2d(startV, startV, m);
startV = [startV[0], startV[1]];

const pointV = [point.x - center.x, point.y - center.y];
if (Vector2.zero(pointV)) {
return {
x: 0,
y: 0
};
}

let theta = Vector2.angleTo(startV, pointV, x.end < x.start);
if (Math.abs(theta - Math.PI * 2) < 0.001) {
theta = 0;
}
const l = Vector2.length(pointV);
let percentX = theta / (x.end - x.start);
percentX = x.end - x.start > 0 ? percentX : -percentX;
const percentY = (l - y.start) / (y.end - y.start);
const rst = {};
rst[xDim] = percentX;
rst[yDim] = percentY;
return rst;
}

}

export default Polar;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
94 changes: 91 additions & 3 deletions packages/f2/test/components/interval/example/pie.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,61 @@
import { jsx } from '../../../../src';
import { Polar, Rect } from '../../../../src/coord';
import { Canvas, Chart } from '../../../../src';
import { Interval, Legend } from '../../../../src/components';
import { createContext, delay } from '../../../util';
import { isArray } from '@antv/util';
import { Canvas, Chart, Component } from '../../../../src';
import { Interval } from '../../../../src/components';
import { createContext, delay, gestureSimulator } from '../../../util';

// @ts-ignore
class Test extends Component {
constructor(props) {
super(props);
this.state = {
record: null,
};
}
didMount() {
super.didMount();
this._initEvent();
}

_handleEvent = (ev) => {
const { chart } = this.props;
const point = ev.points[0];
const pieData = chart.getSnapRecords(point);
if (isArray(pieData) && pieData.length > 0) {
this.setState({ record: pieData[0] });
}
};

_initEvent() {
const { context } = this;
const { canvas } = context;
canvas.on('click', this._handleEvent);
}

render() {
if (!this.state.record) {
return null;
}
const { record } = this.state;
const { coord } = this.props;
const { x, y } = coord?.center;
const { radius } = coord;

const { xMax, xMin } = record;
return (
<text
attrs={{
text: record.origin.name,
x: x + radius * Math.cos(xMin + (xMax - xMin) / 2),
y: y + radius * Math.sin(xMin + (xMax - xMin) / 2),
fill: '#000',
fontSize: '22px',
}}
/>
);
}
}

const data = [
{
Expand Down Expand Up @@ -70,4 +123,39 @@ describe('饼图', () => {
await delay(1000);
expect(context).toMatchImageSnapshot();
});

it('饼图-交互式label', async () => {
const context = createContext('饼图-交互式label');
const chartRef = { current: null };
const { type, props } = (
<Canvas context={context} pixelRatio={1}>
<Chart
ref={chartRef}
data={data}
coord={{
type: Polar,
transposed: true,
}}
>
<Interval
x="a"
y="percent"
adjust="stack"
color={{
field: 'name',
range: ['#1890FF', '#13C2C2', '#2FC25B', '#FACC14', '#F04864', '#8543E0'],
}}
/>
<Test />
</Chart>
</Canvas>
);

const canvas = new Canvas(props);
canvas.render();

await gestureSimulator(context.canvas, 'click', { x: 205, y: 76 });
await delay(1000);
expect(context).toMatchImageSnapshot();
});
});

0 comments on commit c3a0a04

Please sign in to comment.