From f52d2e475a5e3ef6dc9512f971c626852e536589 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Mon, 19 Aug 2024 10:55:38 +0800 Subject: [PATCH 01/23] =?UTF-8?q?feat:windows=E4=B8=8B=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/x6-example-features/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/x6-example-features/package.json b/examples/x6-example-features/package.json index da862fa857..2bdac9c80b 100644 --- a/examples/x6-example-features/package.json +++ b/examples/x6-example-features/package.json @@ -3,7 +3,7 @@ "name": "@antv/x6-example-features", "version": "2.1.1", "scripts": { - "start": "export NODE_OPTIONS=--openssl-legacy-provider && umi dev", + "start": "set NODE_OPTIONS=--openssl-legacy-provider && umi dev", "build": "umi build", "lint": "eslint 'src/**/*.{js,ts}?(x)' --fix" }, From e4ed2d48f84520f06102cdc383e444f2e7259e9b Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Mon, 19 Aug 2024 10:57:15 +0800 Subject: [PATCH 02/23] =?UTF-8?q?bug:x6=E5=B0=8F=E5=9C=B0=E5=9B=BE?= =?UTF-8?q?=E5=AE=9A=E4=BD=8D=E4=B8=8D=E5=87=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6-plugin-minimap/src/index.ts | 97 ++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 11 deletions(-) diff --git a/packages/x6-plugin-minimap/src/index.ts b/packages/x6-plugin-minimap/src/index.ts index 42a4167a80..e7cb12c79f 100644 --- a/packages/x6-plugin-minimap/src/index.ts +++ b/packages/x6-plugin-minimap/src/index.ts @@ -1,4 +1,4 @@ -import { FunctionExt, CssLoader, Dom, View, Graph, EventArgs } from '@antv/x6' +import { FunctionExt, CssLoader, Dom, View, Graph, EventArgs } from '../../x6/src/index' import { content } from './style/raw' export class MiniMap extends View implements Graph.Plugin { @@ -108,6 +108,7 @@ export class MiniMap extends View implements Graph.Plugin { this.sourceGraph.on('model:updated', this.onModelUpdated, this) } this.sourceGraph.on('resize', this.updatePaper, this) + // 当前container委托mousedown、touchstart事件到startAction事件;只有小地图容器被点击,才开始在startAction中监听mousemove等拖拽事件 this.delegateEvents({ mousedown: 'startAction', touchstart: 'startAction', @@ -140,12 +141,17 @@ export class MiniMap extends View implements Graph.Plugin { } protected onModelUpdated() { + // 模型每次更新,都调用小地图的targetGraph 缩放到合适位置 this.targetGraph.zoomToFit() } protected updatePaper(width: number, height: number): this protected updatePaper({ width, height }: EventArgs['resize']): this protected updatePaper(w: number | EventArgs['resize'], h?: number) { + // Graph 中指定的是viewPort 视口宽高,contentArea会根据内容撑开 + // MiniMap option中的宽高也是指定的 viewPort 视口宽高 + // 置于为什么contentArea 比viewPortArea小,并且全部显示了;还能拖拽移动,是svg的transform: matrix的作用 + let width: number let height: number if (typeof w === 'object') { @@ -156,14 +162,18 @@ export class MiniMap extends View implements Graph.Plugin { height = h as number } + // ratio:宽高比、scale:缩放比 + const origin = this.sourceGraph.options const scale = this.sourceGraph.transform.getScale() + // 小地图的最大宽高 = 宽高 - 2 * padding const maxWidth = this.options.width - 2 * this.options.padding const maxHeight = this.options.height - 2 * this.options.padding - + // 主视图的实际宽高 = 宽高 / 缩放比 width /= scale.sx // eslint-disable-line height /= scale.sy // eslint-disable-line + // 小地图宽|高比 = min(小地图viewArea宽/主视图viewArea宽, 小地图viewArea高/主地图viewArea高) this.ratio = Math.min(maxWidth / width, maxHeight / height) const ratio = this.ratio @@ -172,20 +182,26 @@ export class MiniMap extends View implements Graph.Plugin { width *= ratio // eslint-disable-line height *= ratio // eslint-disable-line + // 小地图图形实际宽高 = 主视图宽高 * 小地图宽|高比 this.targetGraph.resize(width, height) this.targetGraph.translate(x, y) if (this.scroller) { + // 有Scroller插件,直接使用宽高比作为缩放比 this.targetGraph.scale(ratio, ratio) } else { + // 没有使用Scroller插件,自适应缩放;并且计算小地图的缩放比 this.targetGraph.zoomToFit() } this.updateViewport() return this } - + // 更新小地图视口的框选区域 protected updateViewport() { + + + // 缩放比例 const sourceGraphScale = this.sourceGraph.transform.getScale() const targetGraphScale = this.targetGraph.transform.getScale() @@ -197,12 +213,21 @@ export class MiniMap extends View implements Graph.Plugin { } const position = Dom.position(this.targetGraph.container) + const translation = this.targetGraph.translate() translation.ty = translation.ty || 0 + + // 小地图框选div(整体区域)位置 this.geometry = { + // viewPort元素本身的top/left(不变) + 大窗口x.y位置 * 小地图缩放比例 + 小地图matrix矩阵偏移 x.y(不变) top: position.top + origin.y * targetGraphScale.sy + translation.ty, left: position.left + origin.x * targetGraphScale.sx + translation.tx, + // 小地图区域宽度 = 大窗口宽度 * 小地图缩放比例 / 大窗口缩放比例 + // 依据公式:小地图区域宽度 / 小地图缩放比例 = 大窗口宽度 / 大窗口缩放比例 + // 小地图缩放比例越小,小地图区域宽度也就越小 + + // 缩放比 = 视口宽高 / 画布内容区域宽高 width: (this.graphContainer.clientWidth! * targetGraphScale.sx) / sourceGraphScale.sx, @@ -215,8 +240,10 @@ export class MiniMap extends View implements Graph.Plugin { protected startAction(evt: Dom.MouseDownEvent) { const e = this.normalizeEvent(evt) + // 缩放还是平移 const action = e.target === this.zoomHandle ? 'zooming' : 'panning' const { tx, ty } = this.sourceGraph.translate() + const eventData: Util.EventData = { action, clientX: e.clientX, @@ -232,29 +259,44 @@ export class MiniMap extends View implements Graph.Plugin { this.targetGraphTransforming = true this.delegateDocumentEvents(Util.documentEvents, eventData) } - + // 拖动 protected doAction(evt: Dom.MouseMoveEvent) { const e = this.normalizeEvent(evt) const clientX = e.clientX const clientY = e.clientY const data = e.data as Util.EventData switch (data.action) { + // 平移 case 'panning': { const scale = this.sourceGraph.transform.getScale() + const targetScale = this.targetGraph.transform.getScale() + + // 相对于起始位置偏移了多少px const rx = (clientX - data.clientX) * scale.sx const ry = (clientY - data.clientY) * scale.sy + if (this.scroller) { this.graphContainer.scrollLeft = data.scrollLeft + rx / this.ratio this.graphContainer.scrollTop = data.scrollTop + ry / this.ratio } else { + // this.sourceGraph.translate( + // data.translateX - rx / this.ratio, + // data.translateY - ry / this.ratio, + // ) + + // 计算每次的偏移距离 + const x = (rx ) / targetScale.sx + const y = (ry ) / targetScale.sy + + // 现有偏移位置 - 每次偏移距离 this.sourceGraph.translate( - data.translateX - rx / this.ratio, - data.translateY - ry / this.ratio, + data.translateX - x, + data.translateY - y, ) } break } - + // 缩放 case 'zooming': { const startScale = data.scale const startGeometry = data.geometry @@ -284,7 +326,7 @@ export class MiniMap extends View implements Graph.Plugin { this.undelegateDocumentEvents() this.targetGraphTransforming = false } - + // 点击滚动 protected scrollTo(evt: Dom.MouseDownEvent) { const e = this.normalizeEvent(evt) @@ -294,6 +336,8 @@ export class MiniMap extends View implements Graph.Plugin { const ts = this.targetGraph.translate() ts.ty = ts.ty || 0 + console.log('scrollTo ts', ts) + if (e.offsetX == null) { const offset = Dom.offset(this.targetGraph.container) x = e.pageX - offset.left @@ -303,9 +347,40 @@ export class MiniMap extends View implements Graph.Plugin { y = e.offsetY } - const cx = (x - ts.tx) / this.ratio - const cy = (y - ts.ty) / this.ratio - this.sourceGraph.centerPoint(cx, cy) + const sourceScale = this.sourceGraph.transform.getScale() + const targetScale = this.targetGraph.transform.getScale() + + // // const cx = (x - ts.tx) / this.ratio + // // const cy = (y - ts.ty) / this.ratio + + // const originX = (x - ts.tx) + // const originY = (y - ts.ty) + // console.log('scrollTo', this.ratio, originX, originY) + // // 小地图scale缩小,大地图scale被放大, cx就越大;偏移差距也就越大 + // // 小地图scale放大,大地图scale被缩小, cx就越小;偏移差距也就越小 + // const cx = (originX * sourceScale.sx)/ targetScale.sx + // const cy = (originY * sourceScale.sy)/ targetScale.sy + + // console.log('big position', cx, cy) + + const position = Dom.position(this.viewport) + const containerPosition = Dom.position(this.targetGraph.container) + const {width, height} = this.viewport.getBoundingClientRect() + const start = { + x: position.left + width/2, + y: position.top - containerPosition.top + height/2, + } + const cx = (x - start.x) * sourceScale.sx / targetScale.sx + const cy = (y - start.y) * sourceScale.sy / targetScale.sy + + const { tx, ty } = this.sourceGraph.translate() + + this.sourceGraph.translate(tx - cx, ty - cy) + + + + + // this.sourceGraph.centerPoint(cx, cy) } @View.dispose() From df812a72527645cddab6ef4b26c2d13e9766d453 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Mon, 19 Aug 2024 11:02:41 +0800 Subject: [PATCH 03/23] =?UTF-8?q?feat:=E9=83=A8=E5=88=86=E6=BA=90=E7=A0=81?= =?UTF-8?q?=E5=A4=87=E6=B3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../x6-example-features/src/pages/index.tsx | 4 ++ .../src/pages/minimap/index.less | 8 +-- .../src/pages/minimap/index.tsx | 59 ++++++++++++------- packages/x6-common/src/dom/event/core.ts | 1 + packages/x6-geometry/src/rectangle.ts | 1 + packages/x6/src/graph/graph.ts | 2 +- packages/x6/src/graph/transform.ts | 12 +++- packages/x6/src/index.ts | 2 +- packages/x6/src/model/cell.ts | 4 +- 9 files changed, 62 insertions(+), 31 deletions(-) diff --git a/examples/x6-example-features/src/pages/index.tsx b/examples/x6-example-features/src/pages/index.tsx index d218d81ced..c676fb0d2a 100755 --- a/examples/x6-example-features/src/pages/index.tsx +++ b/examples/x6-example-features/src/pages/index.tsx @@ -183,6 +183,10 @@ const dataSource = [ example: 'history', description: '时光回溯', }, + { + example: 'minimap', + description: '小地图', + }, ].map((item, index) => ({ key: index, ...item })) const columns = [ diff --git a/examples/x6-example-features/src/pages/minimap/index.less b/examples/x6-example-features/src/pages/minimap/index.less index d79bb95346..166801ed6e 100644 --- a/examples/x6-example-features/src/pages/minimap/index.less +++ b/examples/x6-example-features/src/pages/minimap/index.less @@ -9,10 +9,10 @@ .app-minimap { position: absolute; - bottom: 0; - left: 620px; - width: 200px; - height: 150px; + bottom: 16px; + right: 167px; + width: 400px; + height: 400px; } .x6-widget-minimap-viewport { diff --git a/examples/x6-example-features/src/pages/minimap/index.tsx b/examples/x6-example-features/src/pages/minimap/index.tsx index 4b6add5436..cb141f820e 100644 --- a/examples/x6-example-features/src/pages/minimap/index.tsx +++ b/examples/x6-example-features/src/pages/minimap/index.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { Graph } from '@antv/x6' -import { MiniMap } from '@antv/x6-plugin-minimap' +import { MiniMap } from '../../../../../packages/x6-plugin-minimap/src/index' import { Scroller } from '@antv/x6-plugin-scroller' import { Radio } from 'antd' import { SimpleNodeView } from './simple-view' @@ -18,29 +18,28 @@ export default class Example extends React.Component { componentDidMount() { this.graph = new Graph({ + panning: { + enabled: true, + modifiers: [], + eventTypes: ['leftMouseDown'], + }, + mousewheel: { + enabled: true, + }, container: this.container, - width: 600, - height: 320, + width: 1600, + height: 800, background: { color: '#F2F7FA', }, }) - this.graph.use( - new Scroller({ - pageVisible: true, - pageBreak: false, - pannable: true, - }), - ) - this.graph.use( - new MiniMap({ - container: this.minimapContainer, - width: 200, - height: 160, - padding: 10, - }), - ) + // this.graph.use( + // new Scroller({ + // pannable: false, + // }), + // ) + this.graph.addNode({ x: 200, @@ -78,8 +77,8 @@ export default class Example extends React.Component { const target = this.graph.addNode({ shape: 'circle', - x: 160, - y: 180, + x: 1160, + y: 2180, width: 60, height: 60, label: 'World', @@ -102,6 +101,22 @@ export default class Example extends React.Component { }, }, }) + + + this.graph.use( + new MiniMap({ + container: this.minimapContainer, + width: 400, + height: 400, + padding: 1, + preserveAspectRatio:false, + graphOptions:{ + width:400, + height:400 + } + }), + ) + } onMinimapViewChange = (val: string) => { @@ -148,6 +163,9 @@ export default class Example extends React.Component { refMiniMapContainer = (container: HTMLDivElement) => { this.minimapContainer = container } + changeSize = () => { + this.graph.resize(1800, 800) + } render() { return ( @@ -159,6 +177,7 @@ export default class Example extends React.Component { defaultValue={'detailed'} optionType="button" /> +
diff --git a/packages/x6-common/src/dom/event/core.ts b/packages/x6-common/src/dom/event/core.ts index e37a917195..ee076737e3 100644 --- a/packages/x6-common/src/dom/event/core.ts +++ b/packages/x6-common/src/dom/event/core.ts @@ -244,6 +244,7 @@ export namespace Core { event.data = handleObj.data const hookHandle = EventHook.get(handleObj.originType).handle + console.log('dispatch 事件触发', handleObj.originType, hookHandle, handleObj.handler) const result = hookHandle ? hookHandle(matched.elem as Store.EventTarget, event, ...args) diff --git a/packages/x6-geometry/src/rectangle.ts b/packages/x6-geometry/src/rectangle.ts index f728e2dbba..7d1d785f06 100644 --- a/packages/x6-geometry/src/rectangle.ts +++ b/packages/x6-geometry/src/rectangle.ts @@ -624,6 +624,7 @@ export class Rectangle extends Geometry implements Rectangle.RectangleLike { /** * Returns a rectangle that is a union of this rectangle and rectangle `rect`. + * 返回一个矩形区域,该矩形是两个矩形区域的并集(最大区域)。 */ union(rect: Rectangle.RectangleLike | Rectangle.RectangleData) { const ref = Rectangle.clone(rect) diff --git a/packages/x6/src/graph/graph.ts b/packages/x6/src/graph/graph.ts index ea57fdf198..ed192acafc 100644 --- a/packages/x6/src/graph/graph.ts +++ b/packages/x6/src/graph/graph.ts @@ -1,5 +1,5 @@ import { Basecoat, NumberExt, Dom, KeyValue } from '@antv/x6-common' -import { Point, Rectangle } from '@antv/x6-geometry' +import { Point, Rectangle } from '../../../x6-geometry/src/index' import { Model, Collection, Cell, Node, Edge } from '../model' import { CellView } from '../view' import * as Registry from '../registry' diff --git a/packages/x6/src/graph/transform.ts b/packages/x6/src/graph/transform.ts index b4178d2c47..1e6d4bc5ff 100644 --- a/packages/x6/src/graph/transform.ts +++ b/packages/x6/src/graph/transform.ts @@ -1,5 +1,5 @@ -import { Dom, NumberExt } from '@antv/x6-common' -import { Point, Rectangle } from '@antv/x6-geometry' +import { Dom, NumberExt } from '../../../x6-common/src/index' +import { Point, Rectangle } from '../../../x6-geometry/src/index' import { Base } from './base' import { Util } from '../util' import { Cell } from '../model' @@ -322,6 +322,7 @@ export class TransformManager extends Base { options: TransformManager.ScaleContentToFitOptions = {}, translate = true, ) { + console.log('scaleContentToFitImpl', options) let contentBBox let contentLocalOrigin if (options.contentArea) { @@ -367,8 +368,10 @@ export class TransformManager extends Base { }) const currentScale = this.getScale() - + // 新的X轴缩放比(scaleX) = (视口宽 / 内容区域宽) * 当前X轴缩放比 + // 保证区域内容都在视口中展示 let newSX = (fittingBox.width / contentBBox.width) * currentScale.sx + // 新的y轴缩放比(scaleY) = (视口高 / 内容区域高) * 当前Y轴缩放比 let newSY = (fittingBox.height / contentBBox.height) * currentScale.sy if (options.preserveAspectRatio !== false) { @@ -421,8 +424,10 @@ export class TransformManager extends Base { const area = Rectangle.create(rect) const graph = this.graph + // 内容区域位置信息 options.contentArea = area if (options.viewportArea == null) { + // 视口位置信息(视口一般会小于内容区域位置,移动视口可以看内容区域不同位置) options.viewportArea = { x: graph.options.x, y: graph.options.y, @@ -459,6 +464,7 @@ export class TransformManager extends Base { y = cy - y * scale.sy // eslint-disable-line if (ts.tx !== x || ts.ty !== y) { + console.log('centerPoint', x, y) this.translate(x, y) } } diff --git a/packages/x6/src/index.ts b/packages/x6/src/index.ts index 7b9f015750..51f31725ac 100644 --- a/packages/x6/src/index.ts +++ b/packages/x6/src/index.ts @@ -7,7 +7,7 @@ export * from './graph' export * from './config' export * from './util' -export * from '@antv/x6-common' +export * from '../../x6-common/src/index' export * from '@antv/x6-geometry' export { Shape, Registry } diff --git a/packages/x6/src/model/cell.ts b/packages/x6/src/model/cell.ts index 87e94587a7..a0b66c2cd5 100644 --- a/packages/x6/src/model/cell.ts +++ b/packages/x6/src/model/cell.ts @@ -8,8 +8,8 @@ import { KeyValue, Size, Basecoat, -} from '@antv/x6-common' -import { Rectangle, Point } from '@antv/x6-geometry' +} from '../../../x6-common/src/index' +import { Rectangle, Point } from '../../../x6-geometry/src/index' import { NonUndefined } from 'utility-types' import { Attr } from '../registry' import { Model } from './model' From 494716f431d141618f1ea0f191b26f8680f18178 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Mon, 19 Aug 2024 13:11:11 +0800 Subject: [PATCH 04/23] =?UTF-8?q?feat:x6-plugin-history=EF=BC=8C=E6=92=A4?= =?UTF-8?q?=E9=94=80=E5=9B=9E=E9=80=80=E6=8F=92=E4=BB=B6=E5=8E=9F=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6-plugin-history/src/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/x6-plugin-history/src/index.ts b/packages/x6-plugin-history/src/index.ts index dd685eb411..004c17cb4d 100644 --- a/packages/x6-plugin-history/src/index.ts +++ b/packages/x6-plugin-history/src/index.ts @@ -176,6 +176,7 @@ export class History this.model.on('batch:start', this.initBatchCommand, this) this.model.on('batch:stop', this.storeBatchCommand, this) if (this.options.eventNames) { + // 监听哪些事件操作需要进入撤销回退队列,统一进入addCommand中处理 this.options.eventNames.forEach((name, index) => { this.handlers[index] = this.addCommand.bind(this, name) this.model.on(name, this.handlers[index]) @@ -525,11 +526,13 @@ export class History } protected push(cmd: History.Command, options: KeyValue) { + // 有新的操作进入撤销队列undoStack时,重做队列redoStack清空 this.redoStack = [] if (cmd.batch) { this.lastBatchIndex = Math.max(this.lastBatchIndex, 0) this.emit('batch', { cmd, options }) } else { + // 操作进入撤销队列 this.undoStackPush(cmd) this.consolidateCommands() this.notify('add', cmd, options) From ff4bf7121b51f8f6220897442bc9a77ccace8839 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Mon, 19 Aug 2024 13:38:39 +0800 Subject: [PATCH 05/23] =?UTF-8?q?feat:=20Dom=E5=85=AC=E5=85=B1=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E5=B0=81=E8=A3=85=EF=BC=88=E5=8F=AF=E5=80=9F=E9=89=B4?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6-common/src/dom/index.ts | 2 +- packages/x6-common/src/dom/position.ts | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/x6-common/src/dom/index.ts b/packages/x6-common/src/dom/index.ts index 0a5c952325..4432a36d39 100644 --- a/packages/x6-common/src/dom/index.ts +++ b/packages/x6-common/src/dom/index.ts @@ -1,3 +1,3 @@ import * as Dom from './main' - +// 封装Dom相关的操作方法,可以借鉴 export { Dom } diff --git a/packages/x6-common/src/dom/position.ts b/packages/x6-common/src/dom/position.ts index 0bd5804306..10dfebe11c 100644 --- a/packages/x6-common/src/dom/position.ts +++ b/packages/x6-common/src/dom/position.ts @@ -20,7 +20,11 @@ export function height(elem: Element) { const rect = elem.getBoundingClientRect() return rect.height } - +/** + * 计算元素相对于父元素的绝对定位 + * @param elem + * @returns + */ export function position(elem: Element) { const isFixed = computeStyle(elem, 'position') === 'fixed' let offsetValue: ReturnType @@ -38,6 +42,7 @@ export function position(elem: Element) { (offsetParent === doc.body || offsetParent === doc.documentElement) && computeStyle(offsetParent, 'position') === 'static' ) { + // 如果 offsetParent 是 body 或 html 并且其定位属性为 static,则继续寻找更高层的定位父元素 offsetParent = offsetParent.parentNode } if (offsetParent !== elem && isElement(offsetParent)) { From db423672c99dad94e3a665470c3255f7fb2ef78f Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Mon, 19 Aug 2024 14:59:53 +0800 Subject: [PATCH 06/23] =?UTF-8?q?feat:=E5=AF=B9=E8=B1=A1=E5=B1=9E=E6=80=A7?= =?UTF-8?q?mixins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6-common/src/object/mixins.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/x6-common/src/object/mixins.ts b/packages/x6-common/src/object/mixins.ts index ff848ad125..661493fe54 100644 --- a/packages/x6-common/src/object/mixins.ts +++ b/packages/x6-common/src/object/mixins.ts @@ -1,4 +1,5 @@ /** + * 对象属性混入mixins * @see https://www.typescriptlang.org/docs/handbook/mixins.html */ export function applyMixins(derivedCtor: any, ...baseCtors: any[]) { From 70702af01b1ef84c69fb33ee6800455a246fd1fb Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Mon, 19 Aug 2024 15:23:32 +0800 Subject: [PATCH 07/23] =?UTF-8?q?feat:Dom=E4=BA=8B=E4=BB=B6=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E4=B8=8EGraph=E6=9C=AC=E8=BA=AB=E7=9A=84=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E6=B3=A8=E5=86=8C=E5=8C=BA=E5=88=86=E5=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6-common/src/dom/event/core.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/x6-common/src/dom/event/core.ts b/packages/x6-common/src/dom/event/core.ts index ee076737e3..66296c198c 100644 --- a/packages/x6-common/src/dom/event/core.ts +++ b/packages/x6-common/src/dom/event/core.ts @@ -8,6 +8,8 @@ import './special' export namespace Core { let triggered: string | undefined + + // Dom的事件注册,与Graph本身的事件注册机制区分开;使用Dom.Event.on进行Dom事件注册 export function on( elem: Store.EventTarget, types: string, @@ -44,6 +46,7 @@ export namespace Core { let mainHandler = store.handler if (mainHandler == null) { mainHandler = store.handler = function (e, ...args: any[]) { + // 事件处理器 return triggered !== e.type ? dispatch(elem, e, ...args) : undefined } } From 65ddd454203601fa793b012c8dee67dd2657d74d Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Mon, 19 Aug 2024 15:46:09 +0800 Subject: [PATCH 08/23] =?UTF-8?q?feat:=20Renderer=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E5=99=A8=E6=B8=B2=E6=9F=93=E5=8E=9F=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6/src/renderer/renderer.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/x6/src/renderer/renderer.ts b/packages/x6/src/renderer/renderer.ts index 72225ccd22..6f023df7c3 100644 --- a/packages/x6/src/renderer/renderer.ts +++ b/packages/x6/src/renderer/renderer.ts @@ -7,6 +7,7 @@ import { CellView, EdgeView } from '../view' import { Util } from '../util' export class Renderer extends Base { + // 初始化Renderer时,传入graph;再Renderer中的Scheduler调度器中,监听graph的相关事件(例如添加节点cell:added),然后进行渲染更新 private readonly schedule: Scheduler = new Scheduler(this.graph) requestViewUpdate(view: CellView, flag: number, options: any = {}) { From 5ebb94a420509824458f947ff7bef250e9589c58 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Mon, 19 Aug 2024 16:45:33 +0800 Subject: [PATCH 09/23] =?UTF-8?q?feat:=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/x6-example-features/src/pages/minimap/index.tsx | 2 +- packages/x6/src/graph/graph.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/x6-example-features/src/pages/minimap/index.tsx b/examples/x6-example-features/src/pages/minimap/index.tsx index cb141f820e..f423fc471e 100644 --- a/examples/x6-example-features/src/pages/minimap/index.tsx +++ b/examples/x6-example-features/src/pages/minimap/index.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { Graph } from '@antv/x6' +import { Graph } from '../../../../../packages/x6' import { MiniMap } from '../../../../../packages/x6-plugin-minimap/src/index' import { Scroller } from '@antv/x6-plugin-scroller' import { Radio } from 'antd' diff --git a/packages/x6/src/graph/graph.ts b/packages/x6/src/graph/graph.ts index ed192acafc..6df21af833 100644 --- a/packages/x6/src/graph/graph.ts +++ b/packages/x6/src/graph/graph.ts @@ -1,4 +1,4 @@ -import { Basecoat, NumberExt, Dom, KeyValue } from '@antv/x6-common' +import { Basecoat, NumberExt, Dom, KeyValue } from '../../../x6-common' import { Point, Rectangle } from '../../../x6-geometry/src/index' import { Model, Collection, Cell, Node, Edge } from '../model' import { CellView } from '../view' @@ -52,6 +52,7 @@ export class Graph extends Basecoat { this.css = new Css(this) this.view = new GraphView(this) this.defs = new Defs(this) + // 坐标 this.coord = new Coord(this) this.transform = new Transform(this) this.highlight = new Highlight(this) @@ -68,6 +69,7 @@ export class Graph extends Basecoat { this.renderer = new ViewRenderer(this) this.panning = new Panning(this) this.mousewheel = new Wheel(this) + // 虚拟渲染 this.virtualRender = new VirtualRender(this) this.size = new Size(this) } From 1f88d3da6ae640b7ea8a2408c44e57eec1eddd68 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Mon, 19 Aug 2024 18:11:52 +0800 Subject: [PATCH 10/23] =?UTF-8?q?feat:=E9=BC=A0=E6=A0=87=E4=BA=A4=E4=BA=92?= =?UTF-8?q?=EF=BC=8C=E5=8F=8A=E5=85=83=E7=B4=A0=E6=8D=95=E6=8D=89+?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E8=A7=A6=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6/src/graph/graph.ts | 8 +++++++- packages/x6/src/graph/view.ts | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/x6/src/graph/graph.ts b/packages/x6/src/graph/graph.ts index 6df21af833..ec9a0ab305 100644 --- a/packages/x6/src/graph/graph.ts +++ b/packages/x6/src/graph/graph.ts @@ -52,7 +52,7 @@ export class Graph extends Basecoat { this.css = new Css(this) this.view = new GraphView(this) this.defs = new Defs(this) - // 坐标 + // 坐标?(用于捕捉交互的元素?) this.coord = new Coord(this) this.transform = new Transform(this) this.highlight = new Highlight(this) @@ -826,6 +826,12 @@ export class Graph extends Basecoat { // #region coord + /** + * 捕捉到栅格?(是否捕捉到栅格上的元素) + * @param x + * @param y + * @returns + */ snapToGrid(p: Point.PointLike): Point snapToGrid(x: number, y: number): Point snapToGrid(x: number | Point.PointLike, y?: number) { diff --git a/packages/x6/src/graph/view.ts b/packages/x6/src/graph/view.ts index 1923f1942a..83d5b2ae8b 100644 --- a/packages/x6/src/graph/view.ts +++ b/packages/x6/src/graph/view.ts @@ -50,6 +50,7 @@ export class GraphView extends View { } delegateEvents() { + // 委托监听this.container dom事件上的交互事件;在对应的handler上再去触发graph上的事件 const ctor = this.constructor as typeof GraphView super.delegateEvents(ctor.events) return this @@ -126,9 +127,11 @@ export class GraphView extends View { } const localPoint = this.graph.snapToGrid(e.clientX, e.clientY) + // 捕捉到元素,触发事件 if (view) { view.onClick(e, localPoint.x, localPoint.y) } else { + // 没有找到,触发空白点击事件 this.graph.trigger('blank:click', { e, x: localPoint.x, From c3b844e421a705977f206d807771835356eb0a40 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Tue, 20 Aug 2024 09:02:48 +0800 Subject: [PATCH 11/23] =?UTF-8?q?feat:=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../x6-example-features/src/pages/minimap/index.tsx | 2 +- packages/x6/src/graph/graph.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/x6-example-features/src/pages/minimap/index.tsx b/examples/x6-example-features/src/pages/minimap/index.tsx index f423fc471e..8d65106023 100644 --- a/examples/x6-example-features/src/pages/minimap/index.tsx +++ b/examples/x6-example-features/src/pages/minimap/index.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { Graph } from '../../../../../packages/x6' +import { Graph } from '../../../../../packages/x6/src/index' import { MiniMap } from '../../../../../packages/x6-plugin-minimap/src/index' import { Scroller } from '@antv/x6-plugin-scroller' import { Radio } from 'antd' diff --git a/packages/x6/src/graph/graph.ts b/packages/x6/src/graph/graph.ts index ec9a0ab305..e170d43c04 100644 --- a/packages/x6/src/graph/graph.ts +++ b/packages/x6/src/graph/graph.ts @@ -1,4 +1,4 @@ -import { Basecoat, NumberExt, Dom, KeyValue } from '../../../x6-common' +import { Basecoat, NumberExt, Dom, KeyValue } from '@antv/x6-common/es' import { Point, Rectangle } from '../../../x6-geometry/src/index' import { Model, Collection, Cell, Node, Edge } from '../model' import { CellView } from '../view' @@ -826,11 +826,11 @@ export class Graph extends Basecoat { // #region coord - /** + /** * 捕捉到栅格?(是否捕捉到栅格上的元素) - * @param x - * @param y - * @returns + * @param x + * @param y + * @returns */ snapToGrid(p: Point.PointLike): Point snapToGrid(x: number, y: number): Point From 624da976b917b55dd1f19e49c3cd097a8fc01bf9 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Tue, 20 Aug 2024 14:36:30 +0800 Subject: [PATCH 12/23] =?UTF-8?q?feat:=E4=BA=8B=E4=BB=B6=E5=A4=84=E7=90=86?= =?UTF-8?q?=EF=BC=8C=E6=9E=84=E5=BB=BA=E8=87=AA=E5=AE=9A=E4=B9=89event?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6-common/src/dom/event/core.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/x6-common/src/dom/event/core.ts b/packages/x6-common/src/dom/event/core.ts index 66296c198c..d36adf52d0 100644 --- a/packages/x6-common/src/dom/event/core.ts +++ b/packages/x6-common/src/dom/event/core.ts @@ -212,6 +212,7 @@ export namespace Core { evt: Event | EventObject | string, ...args: any[] ) { + // 构建自定义的event数据 const event = EventObject.create(evt) event.delegateTarget = elem as Element @@ -243,11 +244,14 @@ export namespace Core { event.rnamespace == null || (handleObj.namespace && event.rnamespace.test(handleObj.namespace)) ) { + if(handleObj.originType === 'mousedown'){ + console.log('handleObj', handleObj.originType, handleObj) + } event.handleObj = handleObj event.data = handleObj.data const hookHandle = EventHook.get(handleObj.originType).handle - console.log('dispatch 事件触发', handleObj.originType, hookHandle, handleObj.handler) + // console.log('dispatch 事件触发', handleObj.originType) const result = hookHandle ? hookHandle(matched.elem as Store.EventTarget, event, ...args) From 48f6c0d08fc874f640c65aa30f34a30e3d5437b7 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Tue, 20 Aug 2024 14:37:42 +0800 Subject: [PATCH 13/23] =?UTF-8?q?feat:=20render=E5=8F=8AqueueJob=20?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E9=98=9F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6/src/renderer/queueJob.ts | 13 +++++++++++-- packages/x6/src/renderer/renderer.ts | 2 +- packages/x6/src/renderer/scheduler.ts | 1 + 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/x6/src/renderer/queueJob.ts b/packages/x6/src/renderer/queueJob.ts index 0a6690f00a..1a9128fcdc 100644 --- a/packages/x6/src/renderer/queueJob.ts +++ b/packages/x6/src/renderer/queueJob.ts @@ -58,7 +58,9 @@ export class JobQueue { this.queueFlush() } } - + /** + * 同步刷新执行任务队列 + */ flushJobsSync() { this.isFlushPending = false this.isFlushing = true @@ -76,6 +78,11 @@ export class JobQueue { this.isFlushing = false } + /** + * 二分法查找任务插入的位置,优先级高的排列在前 + * @param job + * @returns + */ private findInsertionIndex(job: Job) { let left = 0 let ins = this.queue.length @@ -92,7 +99,9 @@ export class JobQueue { } return ins } - + /** + * 异步任务调度,使用requestIdleCallback/setTimeout实现 + */ private scheduleJob() { if ('requestIdleCallback' in window) { if (this.scheduleId) { diff --git a/packages/x6/src/renderer/renderer.ts b/packages/x6/src/renderer/renderer.ts index 6f023df7c3..67c3a990ef 100644 --- a/packages/x6/src/renderer/renderer.ts +++ b/packages/x6/src/renderer/renderer.ts @@ -7,7 +7,7 @@ import { CellView, EdgeView } from '../view' import { Util } from '../util' export class Renderer extends Base { - // 初始化Renderer时,传入graph;再Renderer中的Scheduler调度器中,监听graph的相关事件(例如添加节点cell:added),然后进行渲染更新 + // 初始化Renderer时,传入graph;再Renderer中的Scheduler调度器中,监听graph的相关事件,注意这里监听的是model的事件(例如添加节点cell:added),然后进行渲染更新 private readonly schedule: Scheduler = new Scheduler(this.graph) requestViewUpdate(view: CellView, flag: number, options: any = {}) { diff --git a/packages/x6/src/renderer/scheduler.ts b/packages/x6/src/renderer/scheduler.ts index 7abddb9269..e2f8dd714c 100644 --- a/packages/x6/src/renderer/scheduler.ts +++ b/packages/x6/src/renderer/scheduler.ts @@ -316,6 +316,7 @@ export class Scheduler extends Disposable { if (viewItem) { const zIndex = view.cell.getZIndex() const pivot = this.addZPivot(zIndex) + // 先将view(NodeView/EdgeView)的Dom框架内容插入到container this.container.insertBefore(view.container, pivot) if (!view.cell.isVisible()) { From 17bef501c6b573c1830fd8dbc5eab56f203c99fb Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Tue, 20 Aug 2024 14:44:28 +0800 Subject: [PATCH 14/23] =?UTF-8?q?feat:model=E4=B8=AD=E5=88=9B=E5=BB=BANode?= =?UTF-8?q?=E3=80=81Edge=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6/src/model/edge.ts | 1 + packages/x6/src/model/model.ts | 2 ++ packages/x6/src/model/node.ts | 1 + 3 files changed, 4 insertions(+) diff --git a/packages/x6/src/model/edge.ts b/packages/x6/src/model/edge.ts index 1f7ce8b856..c8427b943c 100644 --- a/packages/x6/src/model/edge.ts +++ b/packages/x6/src/model/edge.ts @@ -1183,6 +1183,7 @@ export namespace Edge { export function create(options: Metadata) { const shape = options.shape || 'edge' + // 从registry 注册中心获取对应边的构造函数 const Ctor = registry.get(shape) if (Ctor) { return new Ctor(options) diff --git a/packages/x6/src/model/model.ts b/packages/x6/src/model/model.ts index a40912ccd5..92d2474ccb 100644 --- a/packages/x6/src/model/model.ts +++ b/packages/x6/src/model/model.ts @@ -252,6 +252,7 @@ export class Model extends Basecoat { } createNode(metadata: Node.Metadata) { + // 构建Node模型 return Node.create(metadata) } @@ -262,6 +263,7 @@ export class Model extends Basecoat { } createEdge(metadata: Edge.Metadata) { + // 构建Edge模型 return Edge.create(metadata) } diff --git a/packages/x6/src/model/node.ts b/packages/x6/src/model/node.ts index 0241e93093..a42e216c4b 100644 --- a/packages/x6/src/model/node.ts +++ b/packages/x6/src/model/node.ts @@ -1188,6 +1188,7 @@ export namespace Node { export function create(options: Metadata) { const shape = options.shape || 'rect' + // 从registry 注册中心获取对应图形的构造函数(自定义的图形也会在registry中注册) const Ctor = registry.get(shape) if (Ctor) { return new Ctor(options) From 86376baf426718f9014f2ad751e07433f71d9690 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Tue, 20 Aug 2024 15:06:09 +0800 Subject: [PATCH 15/23] =?UTF-8?q?feat:=E5=85=83=E7=B4=A0=E6=8D=95=E6=8D=89?= =?UTF-8?q?=E9=80=BB=E8=BE=91(=E5=BD=93=E5=89=8D=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E5=90=91=E4=B8=8A=E9=80=92=E5=BD=92=E6=8B=A5=E6=9C=89data-cell?= =?UTF-8?q?-id=E7=9A=84=E7=88=B6=E5=85=83=E7=B4=A0=E7=9A=84id=E5=80=BC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6/src/graph/view.ts | 8 ++++++-- packages/x6/src/renderer/renderer.ts | 2 ++ packages/x6/src/renderer/scheduler.ts | 2 ++ packages/x6/src/view/view.ts | 4 ++-- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/x6/src/graph/view.ts b/packages/x6/src/graph/view.ts index 83d5b2ae8b..423b6b18ef 100644 --- a/packages/x6/src/graph/view.ts +++ b/packages/x6/src/graph/view.ts @@ -88,7 +88,11 @@ export class GraphView extends View { return true } - + /** + * 根据element查找对应的view (NodeView/EdgeView) + * @param elem + * @returns + */ protected findView(elem: Element) { return this.graph.findViewByElem(elem) } @@ -127,7 +131,7 @@ export class GraphView extends View { } const localPoint = this.graph.snapToGrid(e.clientX, e.clientY) - // 捕捉到元素,触发事件 + // 捕捉到元素(NodeView、EdgeView),触发对应view中的onclick事件 if (view) { view.onClick(e, localPoint.x, localPoint.y) } else { diff --git a/packages/x6/src/renderer/renderer.ts b/packages/x6/src/renderer/renderer.ts index 67c3a990ef..e733563d15 100644 --- a/packages/x6/src/renderer/renderer.ts +++ b/packages/x6/src/renderer/renderer.ts @@ -35,10 +35,12 @@ export class Renderer extends Base { : elem[0] if (target) { + // 通过当前target元素,一直向上查找元素,直到找到拥有data-cell-id属性的元素,获取id值,在schedule中的views中,通过id找到对应的view const id = this.graph.view.findAttr('data-cell-id', target) if (id) { const views = this.schedule.views if (views[id]) { + // 返回view return views[id].view } } diff --git a/packages/x6/src/renderer/scheduler.ts b/packages/x6/src/renderer/scheduler.ts index e2f8dd714c..d5f1fc0d71 100644 --- a/packages/x6/src/renderer/scheduler.ts +++ b/packages/x6/src/renderer/scheduler.ts @@ -7,6 +7,7 @@ import { FlagManager } from '../view/flag' import { Graph } from '../graph' export class Scheduler extends Disposable { + // 存储所有的NodeView、EdgeView public views: KeyValue = {} public willRemoveViews: KeyValue = {} protected zPivots: KeyValue @@ -186,6 +187,7 @@ export class Scheduler extends Disposable { options, state: Scheduler.ViewState.CREATED, } + // scheduler中的views,存储所有的CellView(NodeView、EdgeView) this.views[id] = viewItem } } diff --git a/packages/x6/src/view/view.ts b/packages/x6/src/view/view.ts index d6d255884d..307526da96 100644 --- a/packages/x6/src/view/view.ts +++ b/packages/x6/src/view/view.ts @@ -1,4 +1,4 @@ -import { Dom, KeyValue, Basecoat } from '@antv/x6-common' +import { Dom, KeyValue, Basecoat } from '../../../x6-common/src/index.ts' import { EventArgs } from '@antv/x6-common/lib/event/types' import { Config } from '../config' import { Markup } from './markup' @@ -111,7 +111,7 @@ export abstract class View extends Basecoat { if (current === this.container) { return null } - + // 向上递归寻找拥有指定属性attrName的元素 current = current.parentNode as Element } From ea2b31bd6e5715518071712480b09e5d85c625c5 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Tue, 20 Aug 2024 15:23:17 +0800 Subject: [PATCH 16/23] =?UTF-8?q?feat:=20view=E5=B1=82=EF=BC=8C=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6handler=EF=BC=8C=E8=A7=A6=E5=8F=91=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E7=9A=84CellView(NodeView/EdgeView)=E7=9A=84=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E7=9B=91=E5=90=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6/src/graph/view.ts | 1 + packages/x6/src/view/edge.ts | 2 ++ packages/x6/src/view/node.ts | 3 +++ 3 files changed, 6 insertions(+) diff --git a/packages/x6/src/graph/view.ts b/packages/x6/src/graph/view.ts index 423b6b18ef..60ab72c4d0 100644 --- a/packages/x6/src/graph/view.ts +++ b/packages/x6/src/graph/view.ts @@ -133,6 +133,7 @@ export class GraphView extends View { const localPoint = this.graph.snapToGrid(e.clientX, e.clientY) // 捕捉到元素(NodeView、EdgeView),触发对应view中的onclick事件 if (view) { + // view事件触发 view.onClick(e, localPoint.x, localPoint.y) } else { // 没有找到,触发空白点击事件 diff --git a/packages/x6/src/view/edge.ts b/packages/x6/src/view/edge.ts index 98502e2f17..864ac81e44 100644 --- a/packages/x6/src/view/edge.ts +++ b/packages/x6/src/view/edge.ts @@ -1403,7 +1403,9 @@ export class EdgeView< } onClick(e: Dom.ClickEvent, x: number, y: number) { + // 触发CellView的click事件 graph.on('cell:click') super.onClick(e, x, y) + // 触发EdgeView的click事件 graph.on('edge:click') this.notify('edge:click', this.getEventArgs(e, x, y)) } diff --git a/packages/x6/src/view/node.ts b/packages/x6/src/view/node.ts index 07ddcc5760..3d9fb80b86 100644 --- a/packages/x6/src/view/node.ts +++ b/packages/x6/src/view/node.ts @@ -518,8 +518,11 @@ export class NodeView< } onClick(e: Dom.ClickEvent, x: number, y: number) { + // 触发CellView的click事件 graph.on('cell:click') super.onClick(e, x, y) + // 触发NodeView的click事件 graph.on('node:click'),这个监听会更具体 this.notify('node:click', this.getEventArgs(e, x, y)) + // 触发连接桩点击事件 this.notifyPortEvent('node:port:click', e, { x, y }) } From 8b9675efd6386e448b2eb51eeba902502a4a6c38 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Tue, 20 Aug 2024 17:38:54 +0800 Subject: [PATCH 17/23] =?UTF-8?q?feat:=E4=BA=8B=E4=BB=B6=E8=A7=A6=E5=8F=91?= =?UTF-8?q?=EF=BC=8C=E9=80=9A=E8=BF=87store=E5=AD=98=E5=82=A8=E4=B9=8B?= =?UTF-8?q?=E5=89=8Devent=E4=B8=AD=E7=9A=84data=E6=95=B0=E6=8D=AE=EF=BC=8C?= =?UTF-8?q?=E4=B8=8B=E6=AC=A1=E6=93=8D=E4=BD=9C=E5=90=8C=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E8=83=BD=E5=8F=96=E5=88=B0=E7=9B=B8=E5=BA=94?= =?UTF-8?q?=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6-common/src/dom/event/core.ts | 10 ++++++---- packages/x6-common/src/dom/event/store.ts | 1 + packages/x6-common/src/dom/event/util.ts | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/x6-common/src/dom/event/core.ts b/packages/x6-common/src/dom/event/core.ts index d36adf52d0..41bb2ceda8 100644 --- a/packages/x6-common/src/dom/event/core.ts +++ b/packages/x6-common/src/dom/event/core.ts @@ -39,7 +39,7 @@ export namespace Core { // if (!Util.isValidSelector(elem, selector)) { // throw new Error('Delegate event with invalid selector.') // } - + // 确保elem进入store,后续dispatch 中Util.getHandlerQueue(elem, event)会用到 const store = Store.ensure(elem) // Ensure the main handle @@ -64,6 +64,8 @@ export namespace Core { } let type = originType + // 事件名称hook,通过事件名转换成其它事件名称;EventHook.register方法注册转换逻辑 + // 例如mouseenter 会被转换为mouseover 事件 let hook = EventHook.get(type) // If selector defined, determine special event type, otherwise given type @@ -109,8 +111,10 @@ export namespace Core { Util.setHandlerId(handleObj.handler, guid) } + // Add to the element's handler list, delegates in front if (selector) { + // 有选择器的情况下(理解为具体的cell选择器),将delegateCount+1,代表有多少个具体cell选择器 bag.handlers.splice(bag.delegateCount, 0, handleObj) bag.delegateCount += 1 } else { @@ -244,9 +248,7 @@ export namespace Core { event.rnamespace == null || (handleObj.namespace && event.rnamespace.test(handleObj.namespace)) ) { - if(handleObj.originType === 'mousedown'){ - console.log('handleObj', handleObj.originType, handleObj) - } + // 恢复之前的操作数据 event.handleObj = handleObj event.data = handleObj.data diff --git a/packages/x6-common/src/dom/event/store.ts b/packages/x6-common/src/dom/event/store.ts index 515ead168a..202f075937 100644 --- a/packages/x6-common/src/dom/event/store.ts +++ b/packages/x6-common/src/dom/event/store.ts @@ -27,6 +27,7 @@ export namespace Store { export function ensure(target: EventTarget) { if (!cache.has(target)) { + // 构建以element为key 的events对象 cache.set(target, { events: Object.create(null) }) } return cache.get(target)! diff --git a/packages/x6-common/src/dom/event/util.ts b/packages/x6-common/src/dom/event/util.ts index 9f1e788fc4..3ef3eb513e 100644 --- a/packages/x6-common/src/dom/event/util.ts +++ b/packages/x6-common/src/dom/event/util.ts @@ -100,6 +100,7 @@ export namespace Util { export namespace Util { export function getHandlerQueue(elem: Store.EventTarget, event: EventObject) { const queue = [] + // Store中使用WeakMap进行cache缓存,缓存相关数据 const store = Store.get(elem) const bag = store && store.events && store.events[event.type] const handlers = (bag && bag.handlers) || [] @@ -161,6 +162,7 @@ export namespace Util { // Add the remaining (directly-bound) handlers if (delegateCount < handlers.length) { + // 截取delegateCount之后的handler,也就是用于具体cell选择器的handler queue.push({ elem, handlers: handlers.slice(delegateCount) }) } From 630895074e575459620adbc9d65db6f6ca56218e Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Tue, 20 Aug 2024 17:40:07 +0800 Subject: [PATCH 18/23] =?UTF-8?q?feat:=E5=85=B3=E4=BA=8E=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E4=BA=8B=E4=BB=B6event=EF=BC=8C=E5=AD=98=E5=82=A8?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89data=E7=9A=84=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6/src/view/node.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/x6/src/view/node.ts b/packages/x6/src/view/node.ts index 3d9fb80b86..17b8621a66 100644 --- a/packages/x6/src/view/node.ts +++ b/packages/x6/src/view/node.ts @@ -1055,21 +1055,28 @@ export class NodeView< return area || null } - + /** + * 开始节点拖拽 + * @param e + * @param x + * @param y + * @returns + */ protected startNodeDragging(e: Dom.MouseDownEvent, x: number, y: number) { const targetView = this.getDelegatedView() if (targetView == null || !targetView.can('nodeMovable')) { return this.notifyUnhandledMouseDown(e, x, y) } - + // 往自定义event中传数据 this.setEventData(e, { targetView, action: 'move', }) - + // 当前cell的位置 const position = Point.create(targetView.cell.getPosition()) targetView.setEventData(e, { moving: false, + // 当前点击位置相对于cell的位置的偏移量 offset: position.diff(x, y), restrict: this.getRestrictArea(targetView), }) @@ -1107,7 +1114,12 @@ export class NodeView< this.processEmbedding(e, data) } } - + /** + * 结束时间拖拽 + * @param e + * @param x + * @param y + */ protected stopNodeDragging(e: Dom.MouseUpEvent, x: number, y: number) { const data = this.getEventData(e) if (data.embedding) { From 0e97ca47b76cf49f4db03dd9b208c05a570a92e5 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Tue, 20 Aug 2024 17:41:39 +0800 Subject: [PATCH 19/23] =?UTF-8?q?feat:=20CellView=EF=BC=88NodeView/EdgeVie?= =?UTF-8?q?w=EF=BC=89=E4=B8=AD=E5=8C=85=E5=90=ABCell=EF=BC=88Node/Edge?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6/src/view/cell.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x6/src/view/cell.ts b/packages/x6/src/view/cell.ts index 970c1135f7..9101389b84 100644 --- a/packages/x6/src/view/cell.ts +++ b/packages/x6/src/view/cell.ts @@ -102,7 +102,7 @@ export class CellView< constructor(cell: Entity, options: Partial = {}) { super() - + // CellView中包含 Model中的Node、Edge this.cell = cell this.options = this.ensureOptions(options) this.graph = this.options.graph From 7478b0b660bca873f109754588e982ed3598c55c Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Tue, 20 Aug 2024 17:46:08 +0800 Subject: [PATCH 20/23] =?UTF-8?q?feat:=20Model=E4=B8=AD=E7=9A=84Collection?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0Cell=EF=BC=8C=E9=80=9A=E8=BF=87=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E5=91=8A=E7=9F=A5Scheduler=E8=B0=83=E5=BA=A6=E5=99=A8?= =?UTF-8?q?=EF=BC=8C=E8=BF=9B=E8=A1=8C=E7=9B=B8=E5=BA=94=E7=9A=84CellView?= =?UTF-8?q?=E7=9A=84=E5=88=9B=E5=BB=BA=EF=BC=8C=E5=B9=B6=E9=80=9A=E8=BF=87?= =?UTF-8?q?queueJob=E4=BB=BB=E5=8A=A1=E9=98=9F=E5=88=97=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E8=A7=86=E5=9B=BE=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6/src/model/collection.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/x6/src/model/collection.ts b/packages/x6/src/model/collection.ts index 38c38918cd..e612b0b041 100644 --- a/packages/x6/src/model/collection.ts +++ b/packages/x6/src/model/collection.ts @@ -105,6 +105,8 @@ export class Collection extends Basecoat { } this.trigger('added', args) if (!localOptions.dryrun) { + // 元素添加后触发added事件,从而创建对应的CellView对象(NodeView、EdgeView ) + // 会触发model.notify('cell:added')事件,Scheduler 监听了model.on('cell:added')事件,从而在Scheduler中创建对应的CellView对象(NodeView、EdgeView ) cell.notify('added', { ...args }) } }) From b85ca7fb2848bbb7fbca58e57b5862724d6de797 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Tue, 20 Aug 2024 17:46:22 +0800 Subject: [PATCH 21/23] =?UTF-8?q?feat:=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/minimap/index.tsx | 35 +++++++++++-------- packages/x6/src/graph/graph.ts | 2 +- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/examples/x6-example-features/src/pages/minimap/index.tsx b/examples/x6-example-features/src/pages/minimap/index.tsx index 8d65106023..c3f528141e 100644 --- a/examples/x6-example-features/src/pages/minimap/index.tsx +++ b/examples/x6-example-features/src/pages/minimap/index.tsx @@ -39,7 +39,6 @@ export default class Example extends React.Component { // pannable: false, // }), // ) - this.graph.addNode({ x: 200, @@ -102,20 +101,28 @@ export default class Example extends React.Component { }, }) + // this.graph.use( + // new MiniMap({ + // container: this.minimapContainer, + // width: 400, + // height: 400, + // padding: 1, + // preserveAspectRatio: false, + // graphOptions: { + // width: 400, + // height: 400, + // }, + // }), + // ) - this.graph.use( - new MiniMap({ - container: this.minimapContainer, - width: 400, - height: 400, - padding: 1, - preserveAspectRatio:false, - graphOptions:{ - width:400, - height:400 - } - }), - ) + + this.graph.on('cell:click', ({ e, x, y, cell, view }) => { + console.log('graph cell:click') + }) + + this.graph.on('node:click',()=>{ + console.log('graph node:click') + }) } diff --git a/packages/x6/src/graph/graph.ts b/packages/x6/src/graph/graph.ts index e170d43c04..1f2b45161b 100644 --- a/packages/x6/src/graph/graph.ts +++ b/packages/x6/src/graph/graph.ts @@ -827,7 +827,7 @@ export class Graph extends Basecoat { // #region coord /** - * 捕捉到栅格?(是否捕捉到栅格上的元素) + * 当前事件在栅格中的坐标 * @param x * @param y * @returns From dc6ca1a089f16f3ba347dccc05e60cbfeb988c8f Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Tue, 20 Aug 2024 18:31:17 +0800 Subject: [PATCH 22/23] =?UTF-8?q?feat=EF=BC=9A=E4=BA=8B=E4=BB=B6=E5=A7=94?= =?UTF-8?q?=E6=89=98=EF=BC=8C=E8=A7=A6=E5=8F=91=E6=B5=81=E7=A8=8B=E5=A4=87?= =?UTF-8?q?=E6=B3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6/src/graph/view.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/x6/src/graph/view.ts b/packages/x6/src/graph/view.ts index 60ab72c4d0..a59fcaa261 100644 --- a/packages/x6/src/graph/view.ts +++ b/packages/x6/src/graph/view.ts @@ -51,6 +51,9 @@ export class GraphView extends View { delegateEvents() { // 委托监听this.container dom事件上的交互事件;在对应的handler上再去触发graph上的事件 + // 1. GraphView中将ctor.events事件都绑定在this.container上,回调事件根据配置,指向GraphView上具体的函数 + // 2.this.container中的DOM事件触发之后,根据事件信息,找到对应的CellView子类,然后触发CellView上的事件 + // 3.CellView中的notify,会触发this.graph.trigger事件,从而将事件传递给graph;业务层如果监听了graph上的事件(例如 this.graph.on('cell:added'))),也会收到事件 const ctor = this.constructor as typeof GraphView super.delegateEvents(ctor.events) return this From a14c3c58ac8968596fe4ddeed5e863aba9d905f9 Mon Sep 17 00:00:00 2001 From: yelikang <530331059@qq.com> Date: Wed, 21 Aug 2024 16:43:49 +0800 Subject: [PATCH 23/23] =?UTF-8?q?feat:=20coord=20=E5=9D=90=E6=A0=87?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x6/src/graph/graph.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/x6/src/graph/graph.ts b/packages/x6/src/graph/graph.ts index 1f2b45161b..fe558303e4 100644 --- a/packages/x6/src/graph/graph.ts +++ b/packages/x6/src/graph/graph.ts @@ -52,7 +52,7 @@ export class Graph extends Basecoat { this.css = new Css(this) this.view = new GraphView(this) this.defs = new Defs(this) - // 坐标?(用于捕捉交互的元素?) + // 坐标(用于画布与客户端/浏览器的坐标转换) this.coord = new Coord(this) this.transform = new Transform(this) this.highlight = new Highlight(this) @@ -889,7 +889,10 @@ export class Graph extends Basecoat { return this.coord.localToPagePoint(x, y) } - + /** + * 画布坐标转换为客户端坐标(浏览器坐标) + * @param rect + */ clientToLocal(rect: Rectangle.RectangleLike): Rectangle clientToLocal(x: number, y: number, width: number, height: number): Rectangle clientToLocal(p: Point.PointLike): Point @@ -915,7 +918,10 @@ export class Graph extends Basecoat { return this.coord.clientToLocalPoint(x, y) } - + /** + * 浏览器坐标转换为画布端坐标 + * @param rect + */ localToClient(rect: Rectangle.RectangleLike): Rectangle localToClient(x: number, y: number, width: number, height: number): Rectangle localToClient(p: Point.PointLike): Point