UNPKG

@antv/f2

Version:

Charts for mobile visualization.

203 lines (175 loc) 4.72 kB
import { Range, Point, Option } from './types'; import { isArray, mix } from '@antv/util'; function transposedRect({ xMin, xMax, yMin, yMax }) { return { xMin: yMin, xMax: yMax, yMin: xMin, yMax: xMax }; } function convertRect({ x, y, size, y0 }: RectPoint) { let xMin: number; let xMax: number; if (isArray(x)) { xMin = x[0]; xMax = x[1]; } else { xMin = x - size / 2; xMax = x + size / 2; } let yMin: number; let yMax: number; if (isArray(y)) { if (y[0] === y[1]) { yMin = y[0]; yMax = y[1]; } else { yMin = Math.min(y[0], y[1]); yMax = Math.max(y[0], y[1]); } } else { yMin = Math.min(y0, y); yMax = Math.max(y0, y); } return { xMin, xMax, yMin, yMax, }; } // 绘制矩形的关键点 interface RectPoint { x: number | [number, number]; y: number | [number, number]; y0?: number; size?: number; } interface Rect { xMin: number; xMax: number; yMin: number; yMax: number; } /** * 直角坐标系 * convert相关的方法,涉及将标准坐标系映射到实际坐标系内 * transform相关的方法,是仅将某一种关键点转换成另一种关键点 (比如将x/y/size/y0转换成yMin/yMax/..) */ class Base { left = 0; top = 0; width = 0; height = 0; right: number; bottom: number; type: string; // 用来特殊标识是否是极坐标 isPolar: boolean; // x y 调换 transposed = false; // 中心点的坐标 center: Point; // x,y 的值域,在极坐标中对应的就是弧度和半径 x: Range = [0, 1]; y: Range = [0, 1]; constructor(option: Option) { this.update(option); } update(option: Option) { mix(this, option); const { left, top, width, height } = this; this.right = left + width; this.bottom = top + height; this.center = { x: left + width / 2, y: top + height / 2, }; return this; } // 是循环, 比如极坐标是以 2π 循环的 isCyclic() { return false; } _zoomVal(val, func) { return isArray(val) ? val.map((v) => func(v)) : func(val); } /** * 把归一后的值映射到对应的定义域 * @param point */ convert(point) { const { transposed, x, y } = this; const xDim = transposed ? 'y' : 'x'; const yDim = transposed ? 'x' : 'y'; const pointX = point[xDim]; const pointY = point[yDim]; // 超出边界不绘制 if (pointX < 0 || pointX > 1 || pointY < 0 || pointY > 1) { return { x: NaN, y: NaN, }; } return { x: this._zoomVal(point[xDim], (v) => x[0] + (x[1] - x[0]) * v), y: this._zoomVal(point[yDim], (v) => y[0] + (y[1] - y[0]) * v), }; } /** * convert 的反处理,把定义域的值,反处理到归一的值 */ invert(point) { const { transposed, x, y } = this; const xDim = transposed ? 'y' : 'x'; const yDim = transposed ? 'x' : 'y'; return { [xDim]: this._zoomVal(point.x, (v) => (v - x[0]) / (x[1] - x[0])), [yDim]: this._zoomVal(point.y, (v) => (v - y[0]) / (y[1] - y[0])), }; } /** * 把归一化的值映射到 canvas 的坐标点 * @param point * @returns */ convertPoint(point) { return this.convert(point); } /** * 把canvas坐标的点位映射回归一的值 */ invertPoint(point) { return this.invert(point); } // 将标准坐标系下的矩形绘制关键点映射成实际绘制的坐标点 convertRect(rectPoint: RectPoint): Rect { const { x: xRange, y: yRange, transposed } = this; const [xStart, xEnd] = xRange; const [yStart, yEnd] = yRange; const rect = convertRect(rectPoint); const { xMin, xMax, yMin, yMax } = transposed ? transposedRect(rect) : rect; const x0 = xStart + (xEnd - xStart) * xMin; const x1 = xStart + (xEnd - xStart) * xMax; const y0 = yStart + (yEnd - yStart) * yMin; const y1 = yStart + (yEnd - yStart) * yMax; return { xMin: Math.min(x0, x1), xMax: Math.max(x0, x1), yMin: Math.min(y0, y1), yMax: Math.max(y0, y1), }; } // 将已经映射好的矩形绘制关键点转换成实际绘制的坐标点 transformToRect(rectPoint: RectPoint): Rect { const { x, y, y0, size } = rectPoint; const coordOrigin = this.convertPoint({ x: 0, y: y0 }); const { transposed } = this; const _rectPoint = { size, x: transposed ? y : x, y: transposed ? x : y, y0: transposed ? coordOrigin.x : coordOrigin.y, }; const rect = convertRect(_rectPoint); const { xMin, xMax, yMin, yMax } = transposed ? transposedRect(rect) : rect; return { xMin, xMax, yMin, yMax }; } } export default Base;