From 50efbad66bcb338b5de25466f188da5f5c8f7219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=8E=E6=99=BA=E6=B4=B2?= <1543046129@qq.com> Date: Wed, 13 Apr 2022 18:23:07 +0800 Subject: [PATCH] bugfix --- src/BehaviorHelper/behaviorIssueHelper.ts | 2 +- src/BehaviorHelper/initG6Behaviors.ts | 2 +- src/View/reconcile.ts | 10 +- src/View/renderer.ts | 322 +++++++++++----------- src/View/viewContainer.ts | 1 + 5 files changed, 172 insertions(+), 165 deletions(-) diff --git a/src/BehaviorHelper/behaviorIssueHelper.ts b/src/BehaviorHelper/behaviorIssueHelper.ts index 890ce6b..96e5659 100644 --- a/src/BehaviorHelper/behaviorIssueHelper.ts +++ b/src/BehaviorHelper/behaviorIssueHelper.ts @@ -181,7 +181,7 @@ export function SolveDragCanvasWithLeak(viewContainer: ViewContainer) { let translateY = event.matrix[7], dy = translateY - viewContainer.lastLeakAreaTranslateY; - + viewContainer.lastLeakAreaTranslateY = translateY; viewContainer.leakAreaY = viewContainer.leakAreaY + dy; diff --git a/src/BehaviorHelper/initG6Behaviors.ts b/src/BehaviorHelper/initG6Behaviors.ts index 85f9f1c..8adadb9 100644 --- a/src/BehaviorHelper/initG6Behaviors.ts +++ b/src/BehaviorHelper/initG6Behaviors.ts @@ -61,7 +61,7 @@ export function InitG6Behaviors(engine: Engine, viewContainer: ViewContainer): M let node: SVNode = g6Item.SVModel; - if (g6Item === null || node.isNode() === false) { + if (node.isNode() === false) { return false; } diff --git a/src/View/reconcile.ts b/src/View/reconcile.ts index 0235be1..f9a790e 100644 --- a/src/View/reconcile.ts +++ b/src/View/reconcile.ts @@ -256,20 +256,24 @@ export class Reconcile { let { duration, timingFunction } = this.engine.animationOptions; appendModels.forEach(item => { + const G6Item = item.G6Item; + if (item instanceof SVNodeAppendage) { + G6Item.enableCapture(false); + // 先不显示泄漏区节点上面的地址文本 if (item instanceof SVAddressLabel) { // 先将透明度改为0,隐藏掉 - const AddressLabelG6Group = item.G6Item.getContainer(); + const AddressLabelG6Group = G6Item.getContainer(); AddressLabelG6Group.attr({ opacity: 0 }); } else { - Animations.FADE_IN(item.G6Item, { + Animations.FADE_IN(G6Item, { duration, timingFunction, }); } } else { - Animations.APPEND(item.G6Item, { + Animations.APPEND(G6Item, { duration, timingFunction, callback: () => item.afterRender(), diff --git a/src/View/renderer.ts b/src/View/renderer.ts index cc227df..6cc9b01 100644 --- a/src/View/renderer.ts +++ b/src/View/renderer.ts @@ -14,183 +14,185 @@ export type g6Behavior = | { type: string; shouldBegin?: Function; shouldUpdate?: Function; shouldEnd?: Function }; export class Renderer { - private engine: Engine; - private g6Instance: Graph; // g6 实例 - private shadowG6Instance: Graph; + private engine: Engine; + private g6Instance: Graph; // g6 实例 + private shadowG6Instance: Graph; - constructor(engine: Engine, DOMContainer: HTMLElement, behaviorsModes: Modes, isForce: boolean) { - this.engine = engine; + constructor(engine: Engine, DOMContainer: HTMLElement, behaviorsModes: Modes, isForce: boolean) { + this.engine = engine; - const enable: boolean = this.engine.animationOptions.enable, - duration: number = this.engine.animationOptions.duration, - timingFunction: string = this.engine.animationOptions.timingFunction; + const enable: boolean = this.engine.animationOptions.enable, + duration: number = this.engine.animationOptions.duration, + timingFunction: string = this.engine.animationOptions.timingFunction; - const tooltip = new Tooltip({ - offsetX: 10, - offsetY: 20, - shouldBegin(event) { - return event.item['SVModel'].isNode(); - }, - getContent: event => this.getTooltipContent(event.item['SVModel'], { address: 'sourceId', data: 'data' }), - itemTypes: ['node'] - }); + const tooltip = new Tooltip({ + offsetX: 10, + offsetY: 20, + shouldBegin(event) { + return event.item['SVModel'].isNode(); + }, + getContent: event => this.getTooltipContent(event.item['SVModel'], { address: 'sourceId', data: 'data' }), + itemTypes: ['node'], + }); - this.shadowG6Instance = new Graph({ - container: DOMContainer.cloneNode() as HTMLElement - }); - // 力导向的配置选项 - const forceOption = { - type: 'force', - linkDistance: 100, // 边长 - preventOverlap: true, // boolean,防止节点重叠 - // alphaDecay: 0, // 迭代阈值的衰减率。范围 [0, 1]。默认值0.028 - workEnabled: true, // 启用以防布局计算时间过长阻塞页面交互 - nodeStrength: -1, // 节点作用力,正数标识引力,负数表示斥力 - nodeSpacing: (d) => { // 设置了防止重叠后,节点边缘间距的最小值 - return 20; - }, - center: [DOMContainer.offsetWidth / 2, DOMContainer.offsetHeight / 3], - }; - // 布局配置 - const layout = isForce ? forceOption : null; - // 初始化g6实例 - this.g6Instance = new Graph({ - container: DOMContainer, - width: DOMContainer.offsetWidth, - height: DOMContainer.offsetHeight, - groupByTypes: false, - animate: enable, - animateCfg: { - duration: duration, - easing: timingFunction - }, - modes: behaviorsModes, - plugins: [tooltip], - layout, // 布局配置 - }); - /** - * 固定被拖拽节点 - */ - function refreshDragedNodePosition(e) { - const model = e.item.get('model'); - model.fx = e.x; - model.fy = e.y; - } - this.g6Instance.on('node:dragstart', (e) => { - this.g6Instance.layout(); - refreshDragedNodePosition(e); - }); - this.g6Instance.on('node:drag', (e) => { - refreshDragedNodePosition(e); - }); - if (typeof window !== 'undefined') { - window.onresize = () => { - if (!this.g6Instance || this.g6Instance.get('destroyed')) return; - if (!DOMContainer || !DOMContainer.scrollWidth || !DOMContainer.scrollHeight) return; - this.g6Instance.changeSize(DOMContainer.scrollWidth, DOMContainer.scrollHeight); - }; - } - } + this.shadowG6Instance = new Graph({ + container: DOMContainer.cloneNode() as HTMLElement, + }); + // 力导向的配置选项 + const forceOption = { + type: 'force', + linkDistance: 100, // 边长 + preventOverlap: true, // boolean,防止节点重叠 + // alphaDecay: 0, // 迭代阈值的衰减率。范围 [0, 1]。默认值0.028 + workEnabled: true, // 启用以防布局计算时间过长阻塞页面交互 + nodeStrength: -1, // 节点作用力,正数标识引力,负数表示斥力 + nodeSpacing: d => { + // 设置了防止重叠后,节点边缘间距的最小值 + return 20; + }, + center: [DOMContainer.offsetWidth / 2, DOMContainer.offsetHeight / 3], + }; + // 布局配置 + const layout = isForce ? forceOption : null; + // 初始化g6实例 + this.g6Instance = new Graph({ + container: DOMContainer, + width: DOMContainer.offsetWidth, + height: DOMContainer.offsetHeight, + groupByTypes: false, + animate: enable, + animateCfg: { + duration: duration, + easing: timingFunction, + }, + modes: behaviorsModes, + plugins: [tooltip], + layout, // 布局配置 + }); + /** + * 固定被拖拽节点 + */ + function refreshDragedNodePosition(e) { + const model = e.item.get('model'); + model.fx = e.x; + model.fy = e.y; + } + this.g6Instance.on('node:dragstart', e => { + this.g6Instance.layout(); + refreshDragedNodePosition(e); + }); + this.g6Instance.on('node:drag', e => { + refreshDragedNodePosition(e); + }); + if (typeof window !== 'undefined') { + window.onresize = () => { + if (!this.g6Instance || this.g6Instance.get('destroyed')) return; + if (!DOMContainer || !DOMContainer.scrollWidth || !DOMContainer.scrollHeight) return; + this.g6Instance.changeSize(DOMContainer.scrollWidth, DOMContainer.scrollHeight); + }; + } + } - /** - * 创造tooltip元素 - * @param model - * @param items - * @returns - */ - private getTooltipContent(model: SVModel, items: { [key: string]: string }): HTMLDivElement { - const wrapper = document.createElement('div'); + /** + * 创造tooltip元素 + * @param model + * @param items + * @returns + */ + private getTooltipContent(model: SVModel, items: { [key: string]: string }): HTMLDivElement { + const wrapper = document.createElement('div'); - if (model === null || model === undefined) { - return wrapper; - } + if (model === null || model === undefined) { + return wrapper; + } - Object.keys(items).map(key => { - let value = model[items[key]]; - if (value !== undefined && value !== null) { - let item = document.createElement('div'); - item.innerHTML = `${key}:${value}`; - wrapper.appendChild(item); - } - }); + Object.keys(items).map(key => { + let value = model[items[key]]; + if (value !== undefined && value !== null) { + let item = document.createElement('div'); + item.innerHTML = `${key}:${value}`; + wrapper.appendChild(item); + } + }); - return wrapper; - } + return wrapper; + } - /** - * 对每一个 model 在离屏 Canvas 上构建 G6 item,用作布局 - * @param renderModelList - */ - public build(renderModelList: SVModel[]) { - const g6Data: GraphData = Util.convertModelList2G6Data(renderModelList); + /** + * 对每一个 model 在离屏 Canvas 上构建 G6 item,用作布局 + * @param renderModelList + */ + public build(renderModelList: SVModel[]) { + const g6Data: GraphData = Util.convertModelList2G6Data(renderModelList); - this.shadowG6Instance.clear(); - this.shadowG6Instance.read(g6Data); - renderModelList.forEach(item => { - item.shadowG6Item = this.shadowG6Instance.findById(item.id); - item.shadowG6Instance = this.shadowG6Instance; - }); - } + this.shadowG6Instance.clear(); + this.shadowG6Instance.read(g6Data); + renderModelList.forEach(item => { + item.G6Item = null; + item.shadowG6Item = this.shadowG6Instance.findById(item.id); + item.shadowG6Instance = this.shadowG6Instance; + }); + } - /** - * 渲染函数 - * @param renderModelList - * @param isFirstRender - */ - public render(renderModelList: SVModel[]) { - const renderData: GraphData = Util.convertModelList2G6Data(renderModelList); + /** + * 渲染函数 + * @param renderModelList + * @param isFirstRender + */ + public render(renderModelList: SVModel[]) { + const renderData: GraphData = Util.convertModelList2G6Data(renderModelList); - this.g6Instance.changeData(renderData); + this.g6Instance.changeData(renderData); - renderModelList.forEach(item => { - item.g6Instance = this.g6Instance; - item.G6Item = this.g6Instance.findById(item.id); - item.G6Item['SVModel'] = item; - }); + renderModelList.forEach(item => { + item.g6Instance = this.g6Instance; + item.G6Item = this.g6Instance.findById(item.id); + item.G6Item['SVModel'] = item; + }); - this.g6Instance.getEdges().forEach(item => item.toFront()); - this.g6Instance.paint(); - } + this.g6Instance.getEdges().forEach(item => item.toFront()); + this.g6Instance.paint(); + } - /** - * 从视图中移除一个 Model - * @param model - */ - public removeModel(model: SVModel) { - this.g6Instance.removeItem(model.G6Item); - this.shadowG6Instance.removeItem(model.shadowG6Item); - } + /** + * 从视图中移除一个 Model + * @param model + */ + public removeModel(model: SVModel) { + this.g6Instance.removeItem(model.G6Item); + this.shadowG6Instance.removeItem(model.shadowG6Item); + } - /** - * 获取 G6 实例 - */ - public getG6Instance() { - return this.g6Instance; - } + /** + * 获取 G6 实例 + */ + public getG6Instance() { + return this.g6Instance; + } - /** - * - */ - public refresh() { - this.g6Instance.refresh(); - this.shadowG6Instance.refresh(); - } + /** + * + */ + public refresh() { + this.g6Instance.refresh(); + this.shadowG6Instance.refresh(); + } - /** - * - * @param width - * @param height - */ - public changeSize(width: number, height: number) { - this.g6Instance.changeSize(width, height); - this.shadowG6Instance.changeSize(width, height); - } + /** + * + * @param width + * @param height + */ + public changeSize(width: number, height: number) { + this.g6Instance.changeSize(width, height); + this.shadowG6Instance.changeSize(width, height); + } - /** - * 销毁 - */ - public destroy() { - this.shadowG6Instance.destroy(); - this.g6Instance.destroy(); - } + /** + * 销毁 + */ + public destroy() { + this.shadowG6Instance.destroy(); + this.g6Instance.destroy(); + } } diff --git a/src/View/viewContainer.ts b/src/View/viewContainer.ts index 194d8c4..62d4c6a 100644 --- a/src/View/viewContainer.ts +++ b/src/View/viewContainer.ts @@ -47,6 +47,7 @@ export class ViewContainer { this.hasLeak = false; // 判断是否已经发生过泄漏 this.brushSelectedModels = []; this.clickSelectNode = null; + this.lastLeakAreaTranslateY = 0; const g6Instance = this.renderer.getG6Instance(), leakAreaHeight = this.engine.viewOptions.leakAreaHeight,