diff --git a/common/changes/@visactor/vrender-components/feat-polygon-sector-crosshair_2024-12-23-12-33.json b/common/changes/@visactor/vrender-components/feat-polygon-sector-crosshair_2024-12-23-12-33.json new file mode 100644 index 000000000..11ea174bb --- /dev/null +++ b/common/changes/@visactor/vrender-components/feat-polygon-sector-crosshair_2024-12-23-12-33.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-components", + "comment": "feat: support polygon sector crosshair for non-smooth angle axis", + "type": "none" + } + ], + "packageName": "@visactor/vrender-components" +} \ No newline at end of file diff --git a/packages/vrender-components/__tests__/browser/examples/crosshair-polygon-sector.ts b/packages/vrender-components/__tests__/browser/examples/crosshair-polygon-sector.ts new file mode 100644 index 000000000..ceac08290 --- /dev/null +++ b/packages/vrender-components/__tests__/browser/examples/crosshair-polygon-sector.ts @@ -0,0 +1,27 @@ +import '@visactor/vrender'; +import render from '../../util/render'; +import { PolygonSectorCrosshair, SectorCrosshair } from '../../../src'; + +export function run() { + const startAngle = 1.3 * Math.PI; + const endAngle = 1.7 * Math.PI; + const crosshair = new PolygonSectorCrosshair({ + center: { + x: 250, + y: 250 + }, + radius: 100, + innerRadius: 30, + startAngle, + endAngle + }); + + const stage = render([crosshair], 'main'); + + stage.addEventListener('pointermove', e => { + crosshair.setLocation({ + x: e.viewX, + y: e.viewY + }); + }); +} diff --git a/packages/vrender-components/__tests__/browser/main.ts b/packages/vrender-components/__tests__/browser/main.ts index 595d01510..a22968776 100644 --- a/packages/vrender-components/__tests__/browser/main.ts +++ b/packages/vrender-components/__tests__/browser/main.ts @@ -154,6 +154,10 @@ const specs = [ path: 'crosshair-sector', name: '扇形 crosshair' }, + { + path: 'crosshair-polygon-sector', + name: '矩形扇形 crosshair' + }, { path: 'crosshair-polygon', name: '多边形 crosshair' diff --git a/packages/vrender-components/src/crosshair/index.ts b/packages/vrender-components/src/crosshair/index.ts index e957e76f9..7360b7764 100644 --- a/packages/vrender-components/src/crosshair/index.ts +++ b/packages/vrender-components/src/crosshair/index.ts @@ -2,13 +2,15 @@ * @description crosshair 组件 * 1. line 直线 * 2. rect 矩形 - * 3. sector rect 在极坐标系下的 + * 3. sector rect 在极坐标系下的角度轴,smooth === true 时 * 4. circle 用于极坐标系下弧度轴,smooth === true 时 * 5. polygon 用于极坐标系下弧度轴,smooth === false 时 + * 6. polygon-sector 用于极坐标系下的角度轴,smooth === false 时 */ export * from './line'; export * from './rect'; export * from './circle'; export * from './sector'; export * from './polygon'; +export * from './polygon-sector'; export * from './type'; diff --git a/packages/vrender-components/src/crosshair/polygon-sector.ts b/packages/vrender-components/src/crosshair/polygon-sector.ts new file mode 100644 index 000000000..5aad7e924 --- /dev/null +++ b/packages/vrender-components/src/crosshair/polygon-sector.ts @@ -0,0 +1,61 @@ +/** + * @description sector 类型 crosshair,用于极坐标系下 + */ +import type { IGroup } from '@visactor/vrender-core'; +import { merge, getAngleByPoint, radianToDegree, polarToCartesian } from '@visactor/vutils'; +import type { PointLocationCfg } from '../core/type'; +import { POLAR_END_ANGLE, POLAR_START_ANGLE } from '../constant'; +import { CrosshairBase } from './base'; +import type { PolygonSectorCrosshairAttrs } from './type'; +import type { ComponentOptions } from '../interface'; +import { loadPolygonSectorCrosshairComponent } from './register'; +import { getPolygonPath } from '../axis'; + +loadPolygonSectorCrosshairComponent(); +export class PolygonSectorCrosshair extends CrosshairBase { + static defaultAttributes = { + polygonSectorStyle: { + fill: '#b2bacf', + opacity: 0.2 + } + }; + + constructor(attributes: PolygonSectorCrosshairAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, PolygonSectorCrosshair.defaultAttributes, attributes)); + } + + protected renderCrosshair(container: IGroup) { + const { center, radius, innerRadius = 0, polygonSectorStyle } = this.attribute as PolygonSectorCrosshairAttrs; + const { startAngle, endAngle } = this.attribute; + const points = []; + points.push(polarToCartesian(center, innerRadius, startAngle)); + points.push(polarToCartesian(center, radius * Math.cos((endAngle - startAngle) / 2), startAngle)); + points.push(polarToCartesian(center, radius, (startAngle + endAngle) / 2)); + points.push(polarToCartesian(center, radius * Math.cos((endAngle - startAngle) / 2), endAngle)); + points.push(polarToCartesian(center, innerRadius, endAngle)); + + const polygon = container.createOrUpdateChild( + 'crosshair-polygon-sector', + { + path: getPolygonPath(points, true), + ...polygonSectorStyle + }, + 'path' + ); + return polygon; + } + + setLocation(point: PointLocationCfg) { + const { + center, + startAngle = POLAR_START_ANGLE, + endAngle = POLAR_END_ANGLE + } = this.attribute as PolygonSectorCrosshairAttrs; + const sectorAngle = endAngle - startAngle; + const pointAngle = radianToDegree(getAngleByPoint(center, point)); + this.setAttributes({ + startAngle: pointAngle - sectorAngle / 2, + endAngle: pointAngle + sectorAngle / 2 + }); + } +} diff --git a/packages/vrender-components/src/crosshair/register.ts b/packages/vrender-components/src/crosshair/register.ts index dbc834fbf..cd928e7d9 100644 --- a/packages/vrender-components/src/crosshair/register.ts +++ b/packages/vrender-components/src/crosshair/register.ts @@ -25,3 +25,8 @@ export function loadSectorCrosshairComponent() { registerGroup(); registerArc(); } + +export function loadPolygonSectorCrosshairComponent() { + registerGroup(); + registerPath(); +} diff --git a/packages/vrender-components/src/crosshair/type.ts b/packages/vrender-components/src/crosshair/type.ts index f5ee93fc1..8156661b0 100644 --- a/packages/vrender-components/src/crosshair/type.ts +++ b/packages/vrender-components/src/crosshair/type.ts @@ -1,8 +1,13 @@ -import type { IGroupGraphicAttribute, ILineGraphicAttribute, IRectGraphicAttribute } from '@visactor/vrender-core'; +import type { + IGroupGraphicAttribute, + ILineGraphicAttribute, + IPolygonGraphicAttribute, + IRectGraphicAttribute +} from '@visactor/vrender-core'; import type { Point } from '../core/type'; export interface BaseCrosshairAttrs extends IGroupGraphicAttribute { - type?: 'line' | 'rect' | 'circle' | 'polygon' | 'sector'; + type?: 'line' | 'rect' | 'circle' | 'polygon' | 'sector' | 'polygon-sector'; } export interface PolarCrosshairAttrs extends BaseCrosshairAttrs { @@ -83,3 +88,15 @@ export interface PolygonCrosshairAttrs extends PolarCrosshairAttrs { /** 多边形样式 */ lineStyle?: Partial; } + +export interface PolygonSectorCrosshairAttrs extends PolarCrosshairAttrs { + type?: 'polygon-sector'; + /** + * 内半径 + */ + innerRadius?: number; + /** + * 样式配置 + */ + polygonSectorStyle?: Partial; +}