feat: 拓扑图组优化自定义边和自定义节点

This commit is contained in:
TsMask
2024-01-09 11:18:38 +08:00
parent 3c2d4c15c3
commit 299808ce29
2 changed files with 291 additions and 76 deletions

View File

@@ -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(

View File

@@ -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'
);
}