diff --git a/packages/g-plugin-annotation/src/AnnotationPlugin.ts b/packages/g-plugin-annotation/src/AnnotationPlugin.ts index 21df3f635..98eb8b54a 100644 --- a/packages/g-plugin-annotation/src/AnnotationPlugin.ts +++ b/packages/g-plugin-annotation/src/AnnotationPlugin.ts @@ -103,7 +103,7 @@ export class AnnotationPlugin implements RenderingPlugin { default: break; } - + activeDrawer?.setCanvas(this.canvas); const onStart = (toolstate: any) => { this.emmiter.emit('draw:start', toolstate); this.renderDrawer(toolstate); @@ -174,23 +174,23 @@ export class AnnotationPlugin implements RenderingPlugin { const handleMouseDown = (e: FederatedPointerEvent) => { if (e.button === 0) { - this.drawer?.onMouseDown(this.canvas.viewport2Canvas(e.viewport)); + this.drawer?.onMouseDown(e); } }; const handleMouseMove = (e: FederatedPointerEvent) => { - this.drawer?.onMouseMove(this.canvas.viewport2Canvas(e.viewport)); + this.drawer?.onMouseMove(e); }; const handleMouseUp = (e: FederatedPointerEvent) => { if (e.button === 0) { - this.drawer?.onMouseUp(this.canvas.viewport2Canvas(e.viewport)); + this.drawer?.onMouseUp(e); } }; const handleMouseDbClick = (e: FederatedPointerEvent) => { if (e.button === 0) { - this.drawer?.onMouseDbClick(this.canvas.viewport2Canvas(e.viewport)); + this.drawer?.onMouseDbClick(e); } }; diff --git a/packages/g-plugin-annotation/src/drawers/circle.ts b/packages/g-plugin-annotation/src/drawers/circle.ts index 1c7c18ab6..e520b5bad 100644 --- a/packages/g-plugin-annotation/src/drawers/circle.ts +++ b/packages/g-plugin-annotation/src/drawers/circle.ts @@ -14,7 +14,7 @@ export class CircleDrawer extends BaseDrawer { }; } onMouseDown(e: FederatedEvent) { - this.path = [{ x: e.x, y: e.y }]; + this.path = [{ x: e.canvas.x, y: e.canvas.y }]; this.id = uuidv4(); } diff --git a/packages/g-plugin-annotation/src/drawers/polygon.ts b/packages/g-plugin-annotation/src/drawers/polygon.ts index d9a62d746..c5a883c2e 100644 --- a/packages/g-plugin-annotation/src/drawers/polygon.ts +++ b/packages/g-plugin-annotation/src/drawers/polygon.ts @@ -1,6 +1,6 @@ import { DrawerTool } from '../constants/enum'; import { BaseDrawer } from '../interface/drawer'; -import { isNearPoint } from '../utils/drawer'; +import { isInvalidRect } from '../utils/drawer'; import uuidv4 from '../utils/uuidv4'; export class PolygonDrawer extends BaseDrawer { @@ -15,7 +15,7 @@ export class PolygonDrawer extends BaseDrawer { } onMouseDown(e) { - const point = { x: e.x, y: e.y }; + const point = { x: e.canvas.x, y: e.canvas.y }; if (!this.isDrawing) { this.isDrawing = true; this.id = uuidv4(); @@ -23,7 +23,7 @@ export class PolygonDrawer extends BaseDrawer { this.emit('draw:start', this.state); } else { const startPoint = this.path[0]; - if (isNearPoint(point, startPoint, 10)) { + if (isInvalidRect(point, startPoint, 10)) { this.closePath(); } else { this.path.push(point); @@ -34,7 +34,7 @@ export class PolygonDrawer extends BaseDrawer { onMouseMove(e) { if (!this.isDrawing) return; - this.path[this.path.length - 1] = { x: e.x, y: e.y }; + this.path[this.path.length - 1] = { x: e.canvas.x, y: e.canvas.y }; this.emit('draw:move', this.state); } diff --git a/packages/g-plugin-annotation/src/drawers/polyline.ts b/packages/g-plugin-annotation/src/drawers/polyline.ts index 6e8bb87a8..4d0b70d23 100644 --- a/packages/g-plugin-annotation/src/drawers/polyline.ts +++ b/packages/g-plugin-annotation/src/drawers/polyline.ts @@ -1,6 +1,6 @@ import { DrawerTool } from '../constants/enum'; import { BaseDrawer } from '../interface/drawer'; -import { isNearPoint } from '../utils/drawer'; +import { isInvalidRect } from '../utils/drawer'; import uuidv4 from '../utils/uuidv4'; export class PolylineDrawer extends BaseDrawer { @@ -16,7 +16,7 @@ export class PolylineDrawer extends BaseDrawer { } onMouseDown(e) { - const currentPoint = { x: e.x, y: e.y }; + const currentPoint = { x: e.canvas.x, y: e.canvas.y }; if (!this.isDrawing) { this.isDrawing = true; this.id = uuidv4(); @@ -25,7 +25,7 @@ export class PolylineDrawer extends BaseDrawer { } else { const lastPoint = this.path[this.path.length - 2]; - if (isNearPoint(lastPoint, currentPoint, 10)) { + if (isInvalidRect(lastPoint, currentPoint, 10)) { this.closePath(); return; } @@ -37,7 +37,7 @@ export class PolylineDrawer extends BaseDrawer { onMouseMove(e) { if (!this.isDrawing) return; - this.path[this.path.length - 1] = { x: e.x, y: e.y }; + this.path[this.path.length - 1] = { x: e.canvas.x, y: e.canvas.y }; this.emit('draw:modify', this.state); } diff --git a/packages/g-plugin-annotation/src/drawers/rect.ts b/packages/g-plugin-annotation/src/drawers/rect.ts index e9e56eeb4..40a3a3af9 100644 --- a/packages/g-plugin-annotation/src/drawers/rect.ts +++ b/packages/g-plugin-annotation/src/drawers/rect.ts @@ -1,26 +1,35 @@ import { DrawerTool } from '../constants/enum'; import type { Point } from '../interface/drawer'; import { BaseDrawer } from '../interface/drawer'; -import { isNearPoint } from '../utils/drawer'; +import { isInvalidRect } from '../utils/drawer'; import uuidv4 from '../utils/uuidv4'; +const sortBboxPoint = (points: Point[]) => { + const [tl, tr, bl, br] = points.concat().sort((a, b) => b.y - a.y); + const t = [bl, br].sort((a, b) => a.x - b.x); + const b = [tl, tr].sort((a, b) => b.x - a.x); + return t.concat(b); +}; export class RectDrawer extends BaseDrawer { - private start: Point | undefined; - private end: Point | undefined; + private start: { canvas: Point; viewport: Point } | undefined; + private end: { canvas: Point; viewport: Point } | undefined; type = DrawerTool.Rect; get state() { if (!this.start || !this.end) return null; + + const tr = { + canvas: this.canvas.viewport2Canvas({ x: this.end.viewport.x, y: this.start.viewport.y }), + viewport: { x: this.end.viewport.x, y: this.start.viewport.y }, + }; + const bl = { + canvas: this.canvas.viewport2Canvas({ x: this.start.viewport.x, y: this.end.viewport.y }), + viewport: { x: this.start.viewport.x, y: this.end.viewport.y }, + }; + return { type: this.type, - path: [ - this.start, - { x: this.end.x, y: this.start.y }, - this.end, - { x: this.start.x, y: this.end.y }, - ], - width: this.end.x - this.start.x, - height: this.end.y - this.start.y, + path: sortBboxPoint([this.start.canvas, tr.canvas, this.end.canvas, bl.canvas]), id: this.id, isDrawing: this.isDrawing, }; @@ -28,24 +37,25 @@ export class RectDrawer extends BaseDrawer { onMouseDown(e) { if (this.start) { - this.reset(); + this.onMouseUp(e); + return; } this.isDrawing = true; - this.start = { x: e.x, y: e.y }; - this.end = { x: e.x, y: e.y }; + this.start = { canvas: Object.assign({}, e.canvas), viewport: Object.assign({}, e.viewport) }; + this.end = { canvas: e.canvas, viewport: e.viewport }; this.id = uuidv4(); this.emit('draw:start', this.state); } onMouseMove(e) { if (!this.isDrawing) return; - this.end = { x: e.x, y: e.y }; + this.end = { canvas: e.canvas, viewport: e.viewport }; this.emit('draw:modify', this.state); } onMouseUp(e) { if (!this.isDrawing) return; - if (isNearPoint(this.start, this.end, 2)) { + if (isInvalidRect(this.start.viewport, this.end.viewport, 2)) { this.emit('draw:cancel', this.state); this.reset(); return; diff --git a/packages/g-plugin-annotation/src/interface/drawer.ts b/packages/g-plugin-annotation/src/interface/drawer.ts index 48a1f9e96..cbda6e409 100644 --- a/packages/g-plugin-annotation/src/interface/drawer.ts +++ b/packages/g-plugin-annotation/src/interface/drawer.ts @@ -1,3 +1,4 @@ +import type { Canvas } from '@antv/g'; import EventEmitter from 'eventemitter3'; import type { DrawerTool } from '../constants/enum'; @@ -35,6 +36,8 @@ export abstract class BaseDrawer extends EventEmitter { isActive: boolean = true; /** 绘制路径 */ path: Point[] = []; + /** 画布 */ + canvas: Canvas; constructor(drawerOptions: DrawerOption) { super(); @@ -47,6 +50,10 @@ export abstract class BaseDrawer extends EventEmitter { abstract onMouseDbClick(e): void; abstract onKeyDown(e: KeyboardEvent): void; + setCanvas(canvas: Canvas) { + this.canvas = canvas; + } + reset() { this.id = undefined; this.isDrawing = false; diff --git a/packages/g-plugin-annotation/src/rendering/rect-render.ts b/packages/g-plugin-annotation/src/rendering/rect-render.ts index 631aa21b9..6ff82cf7b 100644 --- a/packages/g-plugin-annotation/src/rendering/rect-render.ts +++ b/packages/g-plugin-annotation/src/rendering/rect-render.ts @@ -1,15 +1,37 @@ +import type { PointLike } from '@antv/g'; import { Rect } from '@antv/g'; -import { DEFAULT_STYLE, DASH_LINE_STYLE } from '../constants/style'; import type { AnnotationPlugin } from '../AnnotationPlugin'; +import { DASH_LINE_STYLE, DEFAULT_STYLE } from '../constants/style'; import type { DrawerState } from '../interface/drawer'; +function getWidthFromBbox(path: PointLike[]) { + const [tl, tr, br, bl] = path; + const dy = tr.y - tl.y; + const dx = tr.x - tl.x; + return Math.sqrt(dy * dy + dx * dx); +} + +function getHeightFromBbox(path: PointLike[]) { + const [tl, tr, br, bl] = path; + const dy = br.y - tr.y; + const dx = br.x - tr.x; + return Math.sqrt(dy * dy + dx * dx); +} +function getRotationFromBbox(path: PointLike[]) { + const [tl, tr, br, bl] = path; + const dy = tr.y - tl.y; + const dx = tr.x - tl.x; + return (Math.atan(dy / dx) * 180) / Math.PI; +} + export const renderRect = (context: AnnotationPlugin, anno: DrawerState) => { const { path } = anno; const left = path[0].x; const top = path[0].y; - const height = path[2].y - path[0].y; - const width = path[2].x - path[0].x; const style = anno.isDrawing ? DASH_LINE_STYLE : DEFAULT_STYLE; + const width = getWidthFromBbox(path); + const height = getHeightFromBbox(path); + const rect = new Rect({ style: { x: left, @@ -21,13 +43,15 @@ export const renderRect = (context: AnnotationPlugin, anno: DrawerState) => { className: anno.id, id: anno.id, }); + const rotation = getRotationFromBbox(path); + rect.rotate(rotation); - rect.addEventListener('mousedown', (e) => { + rect.addEventListener('mousedown', () => { context.freezeDrawer(); context.setActiveAnnotation(anno.id); }); - rect.addEventListener('mouseup', (e) => { + rect.addEventListener('mouseup', () => { context.unfreezeDrawer(); }); diff --git a/packages/g-plugin-annotation/src/utils/drawer.ts b/packages/g-plugin-annotation/src/utils/drawer.ts index 6da79d181..8df0d27ab 100644 --- a/packages/g-plugin-annotation/src/utils/drawer.ts +++ b/packages/g-plugin-annotation/src/utils/drawer.ts @@ -1,5 +1,5 @@ import type { PointLike } from '@antv/g'; -export function isNearPoint(p: PointLike, q: PointLike, threshold: number) { - return Math.abs(p.x - q.x) < threshold && Math.abs(p.y - q.y) < threshold; +export function isInvalidRect(p: PointLike, q: PointLike, threshold: number) { + return Math.abs(p.x - q.x) < threshold || Math.abs(p.y - q.y) < threshold; }