From 5f0783e41aa7872f52ea498e478cdd9579348e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B4=96=E5=B4=96=E5=B4=96?= Date: Fri, 13 Dec 2019 19:51:59 +0800 Subject: [PATCH] feat: add induction area option for Anchor --- packages/x6/src/handler/anchor/handler.ts | 71 +++++++++-------------- packages/x6/src/handler/anchor/option.ts | 5 +- packages/x6/src/option/preset.ts | 1 + 3 files changed, 33 insertions(+), 44 deletions(-) diff --git a/packages/x6/src/handler/anchor/handler.ts b/packages/x6/src/handler/anchor/handler.ts index 2aed2b73505..25643de56f4 100644 --- a/packages/x6/src/handler/anchor/handler.ts +++ b/packages/x6/src/handler/anchor/handler.ts @@ -10,12 +10,13 @@ import { DomEvent, MouseEventEx, Disposable } from '../../common' import { getAnchorOptions, createAnchorHighlightShape } from './option' export class AnchorHandler extends BaseHandler { + inductionSize: number currentState: State | null currentPoint: Point | null currentArea: Rectangle | null currentAnchor: Anchor | null - protected icons: Shape[] | null + protected knobs: Shape[] | null protected points: Point[] | null protected anchors: Anchor[] | null protected highlight: Shape | null @@ -25,6 +26,9 @@ export class AnchorHandler extends BaseHandler { constructor(graph: Graph) { super(graph) + + this.inductionSize = graph.options.anchor.inductionSize + this.resetHandler = () => { if ( this.currentState != null && @@ -57,7 +61,7 @@ export class AnchorHandler extends BaseHandler { if ( this.currentState != null && this.anchors != null && - this.icons != null && + this.knobs != null && this.points != null ) { const state = this.graph.view.getState(this.currentState.cell)! @@ -68,9 +72,9 @@ export class AnchorHandler extends BaseHandler { const anchor = this.anchors[i] const point = this.graph.view.getConnectionPoint(state, anchor)! - this.redrawAnchor(state, anchor, point, this.icons[i]) + this.redrawAnchor(state, anchor, point, this.knobs[i]) this.points[i] = point - this.currentArea.add(this.icons[i].bounds) + this.currentArea.add(this.knobs[i].bounds) } } } @@ -203,17 +207,13 @@ export class AnchorHandler extends BaseHandler { ) } + const graphX = e.getGraphX() + const graphY = e.getGraphY() const tol = this.getTolerance(e) - const x = currentPoint != null ? currentPoint.x : e.getGraphX() - const y = currentPoint != null ? currentPoint.y : e.getGraphY() + const x = currentPoint != null ? currentPoint.x : graphX + const y = currentPoint != null ? currentPoint.y : graphY const grid = new Rectangle(x - tol, y - tol, 2 * tol, 2 * tol) - const mouse = new Rectangle( - e.getGraphX() - tol, - e.getGraphY() - tol, - 2 * tol, - 2 * tol, - ) - + const mouse = new Rectangle(graphX - tol, graphY - tol, 2 * tol, 2 * tol) const state = this.graph.view.getState(this.getCell(e, currentPoint)) // Keeps focus icons visible while over node bounds and @@ -237,40 +237,32 @@ export class AnchorHandler extends BaseHandler { // highlight hovering anchor if ( - this.icons != null && + this.knobs != null && this.points != null && this.anchors != null && (state == null || this.currentState === state) ) { + // console.log('highlight hovering anchor') let bounds: Rectangle | null = null let minDist: number | null = null - const cx = mouse.getCenterX() - const cy = mouse.getCenterY() - - for (let i = 0, ii = this.icons.length; i < ii; i += 1) { - const dx = cx - this.icons[i].bounds.getCenterX() - const dy = cy - this.icons[i].bounds.getCenterY() + for (let i = 0, ii = this.knobs.length; i < ii; i += 1) { + const dx = graphX - this.knobs[i].bounds.getCenterX() + const dy = graphY - this.knobs[i].bounds.getCenterY() const dis = dx * dx + dy * dy - + // console.log(dx, dy, dis) if ( - (this.intersects(this.icons[i], mouse, isSource, existingEdge) || - (currentPoint != null && - this.intersects( - this.icons[i], - grid, - isSource, - existingEdge, - ))) && + (Math.sqrt(dis) < this.inductionSize || + this.intersects(this.knobs[i], mouse) || + (currentPoint != null && this.intersects(this.knobs[i], grid))) && (minDist == null || dis < minDist) ) { this.currentPoint = this.points[i] this.currentAnchor = this.anchors[i] minDist = dis - bounds = this.icons[i].bounds.clone() + bounds = this.knobs[i].bounds.clone() if (this.highlight == null) { - // lazy this.highlight = this.createHighlightShape(state) } } @@ -301,14 +293,14 @@ export class AnchorHandler extends BaseHandler { this.destroyIcons() - this.icons = [] + this.knobs = [] this.points = [] for (let i = 0, ii = this.anchors.length; i < ii; i += 1) { const c = this.anchors[i] const p = this.graph.view.getConnectionPoint(state, c)! const icon = this.redrawAnchor(state, c, p) - this.icons.push(icon) + this.knobs.push(icon) this.points.push(p) this.currentArea.add(icon.bounds) } @@ -334,19 +326,14 @@ export class AnchorHandler extends BaseHandler { return shape } - protected intersects( - icon: Shape, - mouse: Rectangle, - isSource: boolean, - existingEdge: boolean, - ) { + protected intersects(icon: Shape, mouse: Rectangle) { return icon.bounds.isIntersectWith(mouse) } protected destroyIcons() { - if (this.icons != null) { - this.icons.forEach(i => i.dispose()) - this.icons = null + if (this.knobs != null) { + this.knobs.forEach(i => i.dispose()) + this.knobs = null this.points = null } } diff --git a/packages/x6/src/handler/anchor/option.ts b/packages/x6/src/handler/anchor/option.ts index ca7b1df7a2a..c31794f2448 100644 --- a/packages/x6/src/handler/anchor/option.ts +++ b/packages/x6/src/handler/anchor/option.ts @@ -13,6 +13,7 @@ import { } from '../../option' export interface AnchorOptions { + inductionSize: number /** * The image for fixed connection points. */ @@ -30,7 +31,7 @@ export interface GetAnchorOptionsArgs { export function getAnchorOptions(args: GetAnchorOptionsArgs) { const { graph } = args - const options = graph.options.anchor as AnchorOptions + const options = graph.options.anchor return { image: drill(options.image, args.graph, args), cursor: drill(options.cursor, args.graph, args), @@ -58,7 +59,7 @@ export function createAnchorHighlightShape( args: CreateAnchorHighlightShapeArgs, ) { const { graph } = args - const opts = graph.options.anchorHighlight as AnchorHighlightOptions + const opts = graph.options.anchorHighlight const raw = drill(opts.shape, graph, args) const ctor = Shape.getShape(raw) || EllipseShape const shape = new ctor() as Shape diff --git a/packages/x6/src/option/preset.ts b/packages/x6/src/option/preset.ts index 6a255c07a85..4296dfb48cf 100644 --- a/packages/x6/src/option/preset.ts +++ b/packages/x6/src/option/preset.ts @@ -295,6 +295,7 @@ export const preset: FullOptions = { anchor: { image: images.cross, cursor: globals.defaultCursorPointer, + inductionSize: 20, }, anchorHighlight: {