From 299808ce299ea1d67a317726a5c15af3b36a85bd Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Tue, 9 Jan 2024 11:18:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8B=93=E6=89=91=E5=9B=BE=E7=BB=84?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=87=AA=E5=AE=9A=E4=B9=89=E8=BE=B9=E5=92=8C?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../topologyBuild/hooks/registerEdge.ts | 110 ++++++++ .../topologyBuild/hooks/registerNode.ts | 257 ++++++++++++------ 2 files changed, 291 insertions(+), 76 deletions(-) diff --git a/src/views/monitor/topologyBuild/hooks/registerEdge.ts b/src/views/monitor/topologyBuild/hooks/registerEdge.ts index 2219e73e..b1c6ca0f 100644 --- a/src/views/monitor/topologyBuild/hooks/registerEdge.ts +++ b/src/views/monitor/topologyBuild/hooks/registerEdge.ts @@ -89,6 +89,8 @@ export function edgeCubicAnimateCircleMove() { /** * line 直线,含有状态动画 * @key line-animate-state + * @name selected 选中状态 + * @name circle-move 圆点沿边运动 * @name line-dash 虚线运动 * @name line-path 线路径加载运动 */ @@ -102,9 +104,115 @@ export function edgeLineAnimateState() { const keyShape = group.find( (ele: any) => ele.get('name') === 'edge-shape' ); + + // selected 选中状态 + if (name === 'selected') { + if (value) { + const { lineWidth, stroke, shadowBlur, shadowColor } = + item.getStateStyle('selected'); + keyShape.attr({ + lineWidth, + stroke, + shadowBlur, + shadowColor, + }); + } else { + const { lineWidth, stroke } = model.style; + keyShape.attr({ + lineWidth, + stroke, + shadowBlur: null, + shadowColor: null, + }); + } + return; + } + + // circle-move 圆点沿边运动 + if (name === 'circle-move') { + let back1 = group.find( + (ele: any) => ele.get('name') === 'circle-stroke1' + ); + if (back1) { + back1.remove(); + back1.destroy(); + } + let back2 = group.find( + (ele: any) => ele.get('name') === 'circle-stroke2' + ); + if (back2) { + back2.remove(); + back2.destroy(); + } + if (value) { + // 第一个矩形边 + const fillColor = model?.labelCfg?.style?.fill || '#1890ff'; + // 边缘路径的起始位置 + const startPoint = keyShape.getPoint(0); + back1 = group.addShape('circle', { + attrs: { + x: startPoint.x, + y: startPoint.y, + fill: fillColor, + r: 3, + }, + // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性 + name: 'circle-stroke1', + }); + back1.animate( + (ratio: any) => { + // 每帧中的操作。比率范围从 0 到 1,表示动画的进度。返回修改后的配置 + // 根据比率获取边缘上的位置 + const tmpPoint = keyShape.getPoint(ratio); + // 在此处返回修改后的配置,在此处返回 x 和 y + return { + x: tmpPoint.x, + y: tmpPoint.y, + }; + }, + { + repeat: true, // 是否重复执行动画 + duration: 3 * 1000, // 执行一次的持续时间 + } + ); + // 第二个矩形边 + const endPoint = keyShape.getPoint(1); + back2 = group.addShape('circle', { + zIndex: -2, + attrs: { + x: endPoint.x, + y: endPoint.y, + fill: fillColor, + r: 3, + }, + // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性 + name: 'circle-stroke2', + }); + + back2.animate( + (ratio: any) => { + // 每帧中的操作。比率范围从 0 到 1,表示动画的进度。返回修改后的配置 + // 根据比率获取边缘上的位置 + const tmpPoint = keyShape.getPoint(1 - ratio); + // 在此处返回修改后的配置,在此处返回 x 和 y + return { + x: tmpPoint.x, + y: tmpPoint.y, + }; + }, + { + repeat: true, // 是否重复执行动画 + duration: 2 * 1000, // 执行一次的持续时间 + } + ); + } + return; + } + // line-dash 虚线运动 if (name === 'line-dash') { if (value) { + if (keyShape.cfg.animating) return; let index = 0; keyShape.animate( () => { @@ -131,6 +239,7 @@ export function edgeLineAnimateState() { } return; } + // line-path 线路径加载运动 if (name === 'line-path') { // 线路径 @@ -152,6 +261,7 @@ export function edgeLineAnimateState() { back.toBack(); // 置于底层 if (value) { + if (keyShape.cfg.animating) return; // 直线加载 const length = keyShape.getTotalLength(); keyShape.animate( diff --git a/src/views/monitor/topologyBuild/hooks/registerNode.ts b/src/views/monitor/topologyBuild/hooks/registerNode.ts index 84492cbd..a21f22ce 100644 --- a/src/views/monitor/topologyBuild/hooks/registerNode.ts +++ b/src/views/monitor/topologyBuild/hooks/registerNode.ts @@ -139,76 +139,13 @@ export function nodeCircleAnimateShapeStroke() { /** * rect 矩形,含有状态动画 * @key rect-animate-state - * @name stroke 边缘扩散动画 + * @name selected 选中状态 + * @name stroke 边缘扩散状态 */ export function nodeRectAnimateState() { registerNode( 'rect-animate-state', { - afterDraw(cfg, group) { - if (!group) return; - - const size = Array.isArray(cfg?.size) ? cfg?.size : [40, 40]; - const fillColor = cfg?.style?.fill || '#1783ff'; - const radius = cfg?.style?.radius || 2; - const lineWidth = cfg?.style?.lineWidth || 1; - - // 矩形边,边缘扩散动画 =============Start - // 第一个矩形边 - const back1 = group.addShape('rect', { - zIndex: -3, - attrs: { - x: -size[0] / 2, - y: -size[1] / 2, - width: size[0], - height: size[1], - stroke: fillColor, - lineWidth: lineWidth, - radius: radius, - strokeOpacity: 0.6, - }, - // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性 - name: 'rect-stroke1', - }); - back1.hide(); - // 第二个矩形边 - const back2 = group.addShape('rect', { - zIndex: -2, - attrs: { - x: -size[0] / 2, - y: -size[1] / 2, - width: size[0], - height: size[1], - stroke: fillColor, - lineWidth: lineWidth, - radius: radius, - opacity: 0.6, - }, - // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性 - name: 'rect-stroke2', - }); - back2.hide(); - // 第三个矩形边 - const back3 = group.addShape('rect', { - zIndex: -1, - attrs: { - x: -size[0] / 2, - y: -size[1] / 2, - width: size[0], - height: size[1], - stroke: fillColor, - lineWidth: lineWidth, - radius: radius, - opacity: 0.6, - }, - // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性 - name: 'rect-stroke3', - }); - back3.hide(); - // 矩形边,边缘扩散动画 =============End - - group.sort(); // 排序,根据 zIndex 排序 - }, setState: (name, value, item: any) => { const group = item.get('group'); const model = item.getModel(); @@ -217,7 +154,7 @@ export function nodeRectAnimateState() { (ele: any) => ele.get('name') === 'rect-animate-state-keyShape' ); - // 选中状态 + // selected 选中状态 if (name === 'selected') { if (value) { const { fill, lineWidth, stroke, shadowBlur, shadowColor } = @@ -236,21 +173,78 @@ export function nodeRectAnimateState() { return; } - // 矩形边,边缘扩散动画 + // stroke 边缘扩散状态 if (name === 'stroke') { - const backArr = group.findAll((ele: any) => + // 矩形边元素需要移除,请在设置状态前判断是否已设置 + const backArr: any[] = group.findAll((ele: any) => ele.get('name').startsWith('rect-stroke') ); - if (!Array.isArray(backArr)) return; if (value) { - const { lineWidth } = keyShape.attr(); + if (Array.isArray(backArr) && backArr.length === 3) return; + console.log(value, '==', keyShape.cfg.animating); + const size = Array.isArray(model?.size) ? model?.size : [40, 40]; + const { fill, lineWidth, stroke, radius } = model.style; + const fillColor = fill || stroke; + // 第一个矩形边 + const back1 = group.addShape('rect', { + zIndex: -3, + attrs: { + x: -size[0] / 2, + y: -size[1] / 2, + width: size[0], + height: size[1], + stroke: fillColor, + lineWidth: lineWidth, + radius: radius, + strokeOpacity: 0.6, + }, + // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性 + name: 'rect-stroke1', + }); + backArr.push(back1); + // 第二个矩形边 + const back2 = group.addShape('rect', { + zIndex: -2, + attrs: { + x: -size[0] / 2, + y: -size[1] / 2, + width: size[0], + height: size[1], + stroke: fillColor, + lineWidth: lineWidth, + radius: radius, + opacity: 0.6, + }, + // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性 + name: 'rect-stroke2', + }); + backArr.push(back2); + // 第三个矩形边 + const back3 = group.addShape('rect', { + zIndex: -1, + attrs: { + x: -size[0] / 2, + y: -size[1] / 2, + width: size[0], + height: size[1], + stroke: fillColor, + lineWidth: lineWidth, + radius: radius, + opacity: 0.6, + }, + // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性 + name: 'rect-stroke3', + }); + backArr.push(back3); + for (let i = 0; i < backArr.length; i++) { const back = backArr[i]; - back.show(); + back.show(); back.animate( { - lineWidth: lineWidth + 10, + stroke: fillColor, + lineWidth: lineWidth + 12, // 边宽度 strokeOpacity: 0.1, }, { @@ -262,13 +256,12 @@ export function nodeRectAnimateState() { ); } } else { + if (Array.isArray(backArr) && backArr.length === 0) return; for (const back of backArr) { back.stopAnimate(); back.hide(); - back.attr({ - lineWidth: 1, - strokeOpacity: 1, - }); + back.remove(); + back.destroy(); } } return; @@ -278,3 +271,115 @@ export function nodeRectAnimateState() { 'rect' ); } + +/** + * image 图片,含有状态动画 + * @key image-animate-state + * @name top-right-dot 右上角圆点状态 + */ +export function nodeImageAnimateState() { + registerNode( + 'image-animate-state', + { + setState: (name, value, item: any) => { + const group = item.get('group'); + const model = item.getModel(); + // 原始图形 + // const keyShape = group.find( + // (ele: any) => ele.get('name') === 'image-animate-state-keyShape' + // ); + + // selected 选中状态 + if (name === 'selected') { + return; + } + + // top-right-dot 右上角圆点状态 + if (name === 'top-right-dot') { + // 矩形边元素需要移除,请在设置状态前判断是否已设置 + const backArr: any[] = group.findAll((ele: any) => + ele.get('name').startsWith('circle-shape') + ); + if (value) { + if (Array.isArray(backArr) && backArr.length === 3) return; + const size = Array.isArray(model?.size) ? model?.size : [40, 40]; + const x = size[0] / 2; + const y = -size[1] / 2; + const r = 3; + const fillColor = typeof value === 'string' ? value : '#f5222d'; + + // 第一个背景圆 + const back1 = group.addShape('circle', { + zIndex: -3, + attrs: { + x, + y, + r, + fill: fillColor, + opacity: 0.6, + }, + // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性 + name: 'circle-shape1', + }); + backArr.push(back1); + // 第二个背景圆 + const back2 = group.addShape('circle', { + zIndex: -2, + attrs: { + x, + y, + r, + fill: fillColor, + opacity: 0.6, + }, + // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性 + name: 'circle-shape2', + }); + backArr.push(back2); + // 第三个背景圆 + const back3 = group.addShape('circle', { + zIndex: -1, + attrs: { + x, + y, + r, + fill: fillColor, + opacity: 0.6, + }, + // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性 + name: 'circle-shape3', + }); + backArr.push(back3); + + for (let i = 0; i < backArr.length; i++) { + const back = backArr[i]; + back.show(); + back.animate( + { + r: 6, + opacity: 0.3, + }, + { + repeat: true, // 循环 + duration: 3000, + easing: 'easeCubic', + delay: i * 1000, // 逐渐延迟 + } + ); + } + } else { + if (Array.isArray(backArr) && backArr.length === 0) return; + for (const back of backArr) { + back.stopAnimate(); + back.hide(); + back.remove(); + back.destroy(); + } + } + return; + } + }, + }, + 'image' + ); +}