295 lines
8.7 KiB
TypeScript
295 lines
8.7 KiB
TypeScript
import { registerEdge } from '@antv/g6';
|
|
|
|
/**
|
|
* cubic 三阶贝塞尔曲线,虚线运动
|
|
* @key cubic-animate-line-dash
|
|
*/
|
|
export function edgeCubicAnimateLineDash() {
|
|
registerEdge(
|
|
'cubic-animate-line-dash',
|
|
{
|
|
afterDraw(cfg, group) {
|
|
if (!group) return;
|
|
// 获取组中的第一个形状
|
|
const shape = group.get('children')[0];
|
|
// 定义动画
|
|
let index = 0;
|
|
shape.animate(
|
|
() => {
|
|
index++;
|
|
if (index > 8) {
|
|
index = 0;
|
|
}
|
|
return {
|
|
lineDash: [4, 2, 1, 2],
|
|
lineDashOffset: -index,
|
|
};
|
|
},
|
|
{
|
|
repeat: true, // 是否重复执行动画
|
|
duration: 3000, // 执行一次的持续时间
|
|
}
|
|
);
|
|
},
|
|
},
|
|
'cubic' // 扩展内置边
|
|
);
|
|
}
|
|
|
|
/**
|
|
* cubic 三阶贝塞尔曲线,圆点沿边运动
|
|
* @key cubic-animate-circle-move
|
|
*/
|
|
export function edgeCubicAnimateCircleMove() {
|
|
registerEdge(
|
|
'cubic-animate-circle-move',
|
|
{
|
|
afterDraw(cfg, group) {
|
|
if (!group) return;
|
|
// 获取组中的第一个形状
|
|
const shape = group.get('children')[0];
|
|
// 边缘路径的起始位置
|
|
const startPoint = shape.getPoint(0);
|
|
const fillColor = cfg?.labelCfg?.style?.fill || '#1890ff';
|
|
// 添加圆圈形状
|
|
const circle = group.addShape('circle', {
|
|
attrs: {
|
|
x: startPoint.x,
|
|
y: startPoint.y,
|
|
fill: fillColor,
|
|
r: 3,
|
|
},
|
|
// 在 G6 3.3 及更高版本中必须指定。它可以是你想要的任何字符串,但在自定义项目类型中应该是唯一的
|
|
name: 'circle-shape',
|
|
});
|
|
|
|
// 定义动画
|
|
circle.animate(
|
|
(ratio: any) => {
|
|
// 每帧中的操作。比率范围从 0 到 1,表示动画的进度。返回修改后的配置
|
|
// 根据比率获取边缘上的位置
|
|
const tmpPoint = shape.getPoint(ratio);
|
|
// 在此处返回修改后的配置,在此处返回 x 和 y
|
|
return {
|
|
x: tmpPoint.x,
|
|
y: tmpPoint.y,
|
|
};
|
|
},
|
|
{
|
|
repeat: true, // 是否重复执行动画
|
|
duration: 3000, // 执行一次的持续时间
|
|
}
|
|
);
|
|
},
|
|
},
|
|
'cubic' // 扩展内置边
|
|
);
|
|
}
|
|
|
|
/**
|
|
* line 直线,含有状态动画
|
|
* @key line-animate-state
|
|
* @name selected 选中状态
|
|
* @name circle-move 圆点沿边运动
|
|
* @name line-dash 虚线运动
|
|
* @name line-path 线路径加载运动
|
|
*/
|
|
export function edgeLineAnimateState() {
|
|
registerEdge(
|
|
'line-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') === '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') {
|
|
const backArr = group.findAll((ele: any) =>
|
|
ele.get('name').startsWith('circle-stroke')
|
|
);
|
|
if (value) {
|
|
if (backArr.length > 0) return;
|
|
|
|
// 第一个矩形边
|
|
const fillColor = typeof value === 'string' ? value : '#1890ff';
|
|
// 边缘路径的起始位置
|
|
const startPoint = keyShape.getPoint(0);
|
|
const back1 = group.addShape('circle', {
|
|
attrs: {
|
|
x: startPoint.x,
|
|
y: startPoint.y,
|
|
fill: fillColor,
|
|
r: 3,
|
|
},
|
|
// 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
|
|
name: 'circle-stroke1',
|
|
});
|
|
back1.show();
|
|
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);
|
|
const 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.show();
|
|
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, // 执行一次的持续时间
|
|
}
|
|
);
|
|
} else {
|
|
if (backArr.length <= 0) return;
|
|
backArr.forEach((ele: any) => {
|
|
ele.hide();
|
|
ele.remove();
|
|
ele.destroy();
|
|
});
|
|
backArr.length = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// line-dash 虚线运动
|
|
if (name === 'line-dash') {
|
|
if (value) {
|
|
if (keyShape.cfg.animating) return;
|
|
let index = 0;
|
|
keyShape.animate(
|
|
() => {
|
|
index++;
|
|
if (index > 8) {
|
|
index = 0;
|
|
}
|
|
return {
|
|
lineDash: [4, 2, 1, 2],
|
|
lineDashOffset: -index,
|
|
};
|
|
},
|
|
{
|
|
repeat: true, // 是否重复执行动画
|
|
duration: 3000, // 执行一次的持续时间
|
|
}
|
|
);
|
|
} else {
|
|
keyShape.stopAnimate();
|
|
keyShape.attr({
|
|
lineDash: null,
|
|
lineDashOffset: null,
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
|
|
// line-path 线路径加载运动
|
|
if (name === 'line-path') {
|
|
// 线路径
|
|
let back = group.find((ele: any) => ele.get('name') === 'line-path');
|
|
if (back) {
|
|
back.remove();
|
|
back.destroy();
|
|
}
|
|
|
|
const { path, stroke, lineWidth } = keyShape.attr();
|
|
back = group.addShape('path', {
|
|
attrs: {
|
|
path,
|
|
stroke,
|
|
lineWidth,
|
|
opacity: 0.2,
|
|
},
|
|
name: 'line-path',
|
|
});
|
|
back.toBack(); // 置于底层
|
|
|
|
if (value) {
|
|
if (keyShape.cfg.animating) return;
|
|
// 直线加载
|
|
const length = keyShape.getTotalLength();
|
|
keyShape.animate(
|
|
(ratio: any) => {
|
|
const startLen = ratio * length;
|
|
return {
|
|
lineDash: [startLen, length - startLen],
|
|
};
|
|
},
|
|
{
|
|
repeat: true,
|
|
duration: 2000,
|
|
}
|
|
);
|
|
} else {
|
|
keyShape.stopAnimate();
|
|
keyShape.attr({
|
|
lineDash: null,
|
|
});
|
|
back.remove();
|
|
back.destroy();
|
|
}
|
|
return;
|
|
}
|
|
},
|
|
},
|
|
'line' // 扩展内置边
|
|
);
|
|
}
|