UNPKG

@antv/f2

Version:

Charts for mobile visualization.

112 lines (89 loc) 2.88 kB
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;