396 lines
12 KiB
TypeScript
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'
|
|
);
|
|
}
|