@antv/f2
Version:
Charts for mobile visualization.
112 lines (89 loc) • 2.88 kB
text/typescript
import Base from './base';
import { Range, Option } from './types';
import { mat2d, vec2 } from 'gl-matrix';
import { vec2Zero, vec2AngleTo } from '../util/vector';
interface PolarOption extends Option {
radius: number; // 内半径比例
innerRadius: number; // 半径 0~1 默认为1
}
class Polar extends Base {
type = 'polar';
isPolar = true;
startAngle: number;
endAngle: number;
radius: number; // 半径
innnerRadius: number; // 内半径
option: PolarOption;
update(option: PolarOption) {
super.update(option);
if (!this.option) {
this.option = option;
}
const { radius: radiusRatio = 1, innerRadius: innerRadiusRatio = 0 } = this.option;
const { width, height, startAngle = -Math.PI / 2, endAngle = (Math.PI * 3) / 2 } = this;
// 半径取宽高的最小值
const radius = radiusRatio * (Math.min(width, height) / 2);
// 极坐标下 x 表示弧度, y 代表 半径
const x: Range = [startAngle, endAngle];
const y: Range = [innerRadiusRatio * radius, radius];
this.x = x;
this.y = y;
this.startAngle = startAngle;
this.endAngle = endAngle;
this.radius = radius;
this.innnerRadius = innerRadiusRatio * radius;
return this;
}
isCyclic() {
const { startAngle, endAngle } = this;
if (endAngle - startAngle < Math.PI * 2) {
return false;
}
return true;
}
convertPoint(point) {
const { center, transposed, x, y } = this;
const xDim = transposed ? 'y' : 'x';
const yDim = transposed ? 'x' : 'y';
const [xStart, xEnd] = x;
const [yStart, yEnd] = y;
const angle = xStart + (xEnd - xStart) * point[xDim];
const radius = yStart + (yEnd - yStart) * point[yDim];
return {
x: center.x + Math.cos(angle) * radius,
y: center.y + Math.sin(angle) * radius,
};
}
invertPoint(point) {
const { center, transposed, x, y } = this;
const xDim = transposed ? 'y' : 'x';
const yDim = transposed ? 'x' : 'y';
const [xStart, xEnd] = x;
const [yStart, yEnd] = y;
const m = ([1, 0, 0, 1, 0, 0] as unknown) as mat2d;
mat2d.rotate(m, m, xStart);
let startV = ([1, 0] as unknown) as vec2;
vec2.transformMat2d(startV, startV, m);
startV = [startV[0], startV[1]];
const pointV = ([point.x - center.x, point.y - center.y] as unknown) as vec2;
if (vec2Zero(pointV)) {
return {
x: 0,
y: 0,
};
}
let theta = vec2AngleTo(startV, pointV, xEnd < xStart);
if (Math.abs(theta - Math.PI * 2) < 0.001) {
theta = 0;
}
const l = vec2.length(pointV);
let percentX = theta / (xEnd - xStart);
percentX = xEnd - xStart > 0 ? percentX : -percentX;
const percentY = (l - yStart) / (yEnd - yStart);
const rst = {};
rst[xDim] = percentX;
rst[yDim] = percentY;
return rst;
}
}
export default Polar;