Files
fe.ems.vue3/src/views/monitor/topologyBuild/hooks/registerNode.ts
T

396 lines
12 KiB
TypeScript

import { registerNode } from '@antv/g6';
/**
* cubic 圆形,节点放大缩小动画
* @type circle-animate-shape-r
*/
export function nodeCircleAnimateShapeR() {
registerNode(
'circle-animate-shape-r',
{
afterDraw(cfg, group) {
if (!group) return;
const shape = group.get('children')[0];
const r = Number(cfg?.size) || 2;
shape.animate(
(ratio: any) => {
const diff = ratio <= 0.5 ? ratio * 10 : (1 - ratio) * 10;
return {
r: r / 2 + diff,
};
},
{
repeat: true, // 是否重复执行动画
duration: 3000, // 执行一次的持续时间
easing: 'easeCubic',
}
);
},
},
'circle'
);
}
/**
* cubic 圆形,节点边缘扩散动画
* @type circle-animate-shape-stroke
*/
export function nodeCircleAnimateShapeStroke() {
registerNode(
'circle-animate-shape-stroke',
{
afterDraw(cfg, group) {
if (!group) return;
const size = Array.isArray(cfg?.size) ? cfg?.size[0] : cfg?.size;
let r = Number(size) || 2;
r = r / 2;
const fillColor = cfg?.style?.fill || '#1890ff';
// 第一个背景圆
const back1 = group.addShape('circle', {
zIndex: -3,
attrs: {
x: 0,
y: 0,
r,
fill: fillColor,
opacity: 0.6,
},
// 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
name: 'circle-shape1',
});
// 第二个背景圆
const back2 = group.addShape('circle', {
zIndex: -2,
attrs: {
x: 0,
y: 0,
r,
fill: fillColor,
opacity: 0.6,
},
// 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
name: 'circle-shape2',
});
// 第三个背景圆
const back3 = group.addShape('circle', {
zIndex: -1,
attrs: {
x: 0,
y: 0,
r,
fill: fillColor,
opacity: 0.6,
},
// 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
name: 'circle-shape3',
});
group.sort(); // 排序,根据 zIndex 排序
// 第一个背景圆逐渐放大,并消失
back1.animate(
{
r: r + 10,
opacity: 0.1,
},
{
repeat: true, // 循环
duration: 3000,
easing: 'easeCubic',
delay: 0, // 无延迟
}
);
// 第二个背景圆逐渐放大,并消失
back2.animate(
{
r: r + 10,
opacity: 0.1,
},
{
repeat: true, // 循环
duration: 3000,
easing: 'easeCubic',
delay: 1000, // 1 秒延迟
}
);
// 第三个背景圆逐渐放大,并消失
back3.animate(
{
r: r + 10,
opacity: 0.1,
},
{
repeat: true, // 循环
duration: 3000,
easing: 'easeCubic',
delay: 2000, // 2 秒延迟
}
);
},
},
'circle'
);
}
/**
* rect 矩形,含有状态动画
* @key rect-animate-state
* @name selected 选中状态
* @name stroke 边缘扩散状态
*/
export function nodeRectAnimateState() {
registerNode(
'rect-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') === 'rect-animate-state-keyShape'
);
// selected 选中状态
if (name === 'selected') {
if (value) {
const { fill, lineWidth, stroke, shadowBlur, shadowColor } =
item.getStateStyle('selected');
keyShape.attr({ fill, lineWidth, stroke, shadowBlur, shadowColor });
} else {
const { fill, lineWidth, stroke } = model.style;
keyShape.attr({
fill,
lineWidth,
stroke,
shadowBlur: null,
shadowColor: null,
});
}
return;
}
// stroke 边缘扩散状态
if (name === 'stroke') {
// 矩形边元素需要移除,请在设置状态前判断是否已设置
const backArr: any[] = group.findAll((ele: any) =>
ele.get('name').startsWith('rect-stroke')
);
if (value) {
if (Array.isArray(backArr) && backArr.length === 3) return;
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.animate(
{
stroke: fillColor,
lineWidth: lineWidth + 12, // 边宽度
strokeOpacity: 0.1,
},
{
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;
}
},
},
'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) {
const fillColor = typeof value === 'string' ? value : '#f5222d';
// 移除
if (Array.isArray(backArr) && backArr.length >= 3) {
for (const back of backArr) {
back.stopAnimate();
back.hide();
back.remove();
back.destroy();
}
backArr.length = 0;
}
// 根据大小确定半径
const size = Array.isArray(model?.size) ? model?.size : [40, 40];
const x = size[0] / 2;
const y = -size[1] / 2;
const r = 3;
// 第一个背景圆
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'
);
}