mirror of
https://gitee.com/antv/g6.git
synced 2024-12-04 12:49:04 +08:00
* fix: image lost while updating the size for an image node, closes: #3938; * chore: update version num * 自环边样式 startPoint & endPoint 计算问题 #3974 (#3990) * fix: 自环问题连接点问题修复 * feat: change var to halfOfWidth and halfOfHeight * feat: 修改注释 * feat: 完善文档 * feat: 修改注释 * feat: 修改注释 * feat: add loop feat unit test * feat: 删除空行 * feat: 修改名称 Co-authored-by: linjie <xinxinsong.sxx@alibaba-inc.com> Co-authored-by: tulaoda <coderaxin@163.com> Co-authored-by: linjie <xinxinsong.sxx@alibaba-inc.com>
This commit is contained in:
parent
6561f296bd
commit
ce0dbae399
@ -1,5 +1,10 @@
|
||||
# ChangeLog
|
||||
|
||||
### 4.7.8
|
||||
|
||||
- feat: pointPadding config for loop edges with non-circle nodes, closes: #3974;
|
||||
- fix: image lost while updating the size for an image node, closes: #3938;
|
||||
|
||||
### 4.7.7
|
||||
|
||||
- feat: getContentPlaceholder and getTitlePlaceholder for Annotation plugin;
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@antv/g6-core",
|
||||
"version": "0.7.7",
|
||||
"version": "0.7.8",
|
||||
"description": "A Graph Visualization Framework in JavaScript",
|
||||
"keywords": [
|
||||
"antv",
|
||||
|
@ -79,9 +79,7 @@ export const shapeBase: ShapeOptions = {
|
||||
return {};
|
||||
},
|
||||
getOptions(cfg: ModelConfig, updateType?: UpdateType): ModelConfig {
|
||||
if (updateType === 'move' || updateType?.includes('bbox')) {
|
||||
return {};
|
||||
}
|
||||
if (updateType === 'move' || updateType?.includes('bbox')) return cfg;
|
||||
return deepMix(
|
||||
{},
|
||||
this.options,
|
||||
|
@ -64,7 +64,7 @@ const colorSet = {
|
||||
};
|
||||
|
||||
export default {
|
||||
version: '0.7.7',
|
||||
version: '0.7.8',
|
||||
rootContainerClassName: 'root-container',
|
||||
nodeContainerClassName: 'node-container',
|
||||
edgeContainerClassName: 'edge-container',
|
||||
|
@ -298,6 +298,8 @@ export type LoopConfig = Partial<{
|
||||
position: string;
|
||||
// 如果逆时针画,交换起点和终点
|
||||
clockwise: boolean;
|
||||
// 对于非圆形节点设置的连接点与节点中心坐标(`top-right`,`bottom-right`,`top-left`,`bottom-left`较特殊,为四个角坐标)在 x 轴或 y 轴方向的偏移量,默认为 `节点宽高中最小值的1/4`
|
||||
pointPadding: number;
|
||||
}>;
|
||||
|
||||
export interface LayoutConfig {
|
||||
|
@ -11,7 +11,7 @@ import {
|
||||
ComboTree,
|
||||
ComboConfig,
|
||||
ICombo,
|
||||
GraphAnimateConfig
|
||||
GraphAnimateConfig,
|
||||
} from '../types';
|
||||
import { applyMatrix } from './math';
|
||||
import letterAspectRatio from './letterAspectRatio';
|
||||
@ -83,93 +83,146 @@ export const getLoopCfgs = (cfg: EdgeData): EdgeData => {
|
||||
let startPoint = [cfg.startPoint.x, cfg.startPoint.y];
|
||||
let endPoint = [cfg.endPoint.x, cfg.endPoint.y];
|
||||
|
||||
let rstart = bbox.height / 2;
|
||||
let rend = bbox.height / 2;
|
||||
let halfOfHeight = bbox.height / 2;
|
||||
let halfOfWidth = bbox.width / 2;
|
||||
let rstart = halfOfHeight;
|
||||
let rend = halfOfHeight;
|
||||
|
||||
let sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
let cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
let sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
let cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
const shapeType = keyShape.get('type');
|
||||
|
||||
// 美观考虑,pointPadding 默认取宽高中最小的1/4
|
||||
const defaultPointPadding = Math.min(halfOfHeight / 2, halfOfWidth / 2);
|
||||
const maxPointPadding = Math.min(halfOfHeight, halfOfWidth);
|
||||
|
||||
// 对于非圆形节点设置的连接点与节点中心坐标(`top-right`,`bottom-right`,`top-left`,`bottom-left`较特殊,为四个角坐标)在 x 轴或 y 轴方向的偏移量,默认为 `节点宽高中最小值的1/4`
|
||||
const pointPadding = loopCfg?.pointPadding
|
||||
? Math.min(maxPointPadding, loopCfg?.pointPadding)
|
||||
: defaultPointPadding;
|
||||
|
||||
// 如果定义了锚点的,直接用锚点坐标,否则,根据自环的 cfg 计算
|
||||
if (startPoint[0] === endPoint[0] && startPoint[1] === endPoint[1]) {
|
||||
switch (position) {
|
||||
case 'top':
|
||||
startPoint = [center[0] - sinDeltaStart, center[1] - cosDeltaStart];
|
||||
endPoint = [center[0] + sinDeltaEnd, center[1] - cosDeltaEnd];
|
||||
if (shapeType === 'circle') {
|
||||
startPoint = [center[0] - sinDeltaStart, center[1] - cosDeltaStart];
|
||||
endPoint = [center[0] + sinDeltaEnd, center[1] - cosDeltaEnd];
|
||||
} else {
|
||||
startPoint = [center[0] - pointPadding, center[1] - halfOfHeight];
|
||||
endPoint = [center[0] + pointPadding, center[1] - halfOfHeight];
|
||||
}
|
||||
break;
|
||||
case 'top-right':
|
||||
rstart = bbox.height / 2;
|
||||
rend = bbox.width / 2;
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] + sinDeltaStart, center[1] - cosDeltaStart];
|
||||
endPoint = [center[0] + cosDeltaEnd, center[1] - sinDeltaEnd];
|
||||
rstart = halfOfHeight;
|
||||
rend = halfOfWidth;
|
||||
if (shapeType === 'circle') {
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] + sinDeltaStart, center[1] - cosDeltaStart];
|
||||
endPoint = [center[0] + cosDeltaEnd, center[1] - sinDeltaEnd];
|
||||
} else {
|
||||
startPoint = [center[0] + halfOfWidth - pointPadding, center[1] - halfOfHeight];
|
||||
endPoint = [center[0] + halfOfWidth, center[1] - halfOfHeight + pointPadding];
|
||||
}
|
||||
break;
|
||||
case 'right':
|
||||
rstart = bbox.width / 2;
|
||||
rend = bbox.width / 2;
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] + cosDeltaStart, center[1] - sinDeltaStart];
|
||||
endPoint = [center[0] + cosDeltaEnd, center[1] + sinDeltaEnd];
|
||||
rstart = halfOfWidth;
|
||||
rend = halfOfWidth;
|
||||
if (shapeType === 'circle') {
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] + cosDeltaStart, center[1] - sinDeltaStart];
|
||||
endPoint = [center[0] + cosDeltaEnd, center[1] + sinDeltaEnd];
|
||||
} else {
|
||||
startPoint = [center[0] + halfOfWidth, center[1] - pointPadding];
|
||||
endPoint = [center[0] + halfOfWidth, center[1] + pointPadding];
|
||||
}
|
||||
break;
|
||||
case 'bottom-right':
|
||||
rstart = bbox.width / 2;
|
||||
rend = bbox.height / 2;
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] + cosDeltaStart, center[1] + sinDeltaStart];
|
||||
endPoint = [center[0] + sinDeltaEnd, center[1] + cosDeltaEnd];
|
||||
rstart = halfOfWidth;
|
||||
rend = halfOfHeight;
|
||||
if (shapeType === 'circle') {
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] + cosDeltaStart, center[1] + sinDeltaStart];
|
||||
endPoint = [center[0] + sinDeltaEnd, center[1] + cosDeltaEnd];
|
||||
} else {
|
||||
startPoint = [center[0] + halfOfWidth, center[1] + halfOfHeight - pointPadding];
|
||||
endPoint = [center[0] + halfOfWidth - pointPadding, center[1] + halfOfHeight];
|
||||
}
|
||||
break;
|
||||
case 'bottom':
|
||||
rstart = bbox.height / 2;
|
||||
rend = bbox.height / 2;
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] + sinDeltaStart, center[1] + cosDeltaStart];
|
||||
endPoint = [center[0] - sinDeltaEnd, center[1] + cosDeltaEnd];
|
||||
rstart = halfOfHeight;
|
||||
rend = halfOfHeight;
|
||||
if (shapeType === 'circle') {
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] + sinDeltaStart, center[1] + cosDeltaStart];
|
||||
endPoint = [center[0] - sinDeltaEnd, center[1] + cosDeltaEnd];
|
||||
} else {
|
||||
startPoint = [center[0] - pointPadding, center[1] + halfOfHeight];
|
||||
endPoint = [center[0] + pointPadding, center[1] + halfOfHeight];
|
||||
}
|
||||
break;
|
||||
case 'bottom-left':
|
||||
rstart = bbox.height / 2;
|
||||
rend = bbox.width / 2;
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] - sinDeltaStart, center[1] + cosDeltaStart];
|
||||
endPoint = [center[0] - cosDeltaEnd, center[1] + sinDeltaEnd];
|
||||
rstart = halfOfHeight;
|
||||
rend = halfOfWidth;
|
||||
if (shapeType === 'circle') {
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] - sinDeltaStart, center[1] + cosDeltaStart];
|
||||
endPoint = [center[0] - cosDeltaEnd, center[1] + sinDeltaEnd];
|
||||
} else {
|
||||
startPoint = [center[0] - halfOfWidth, center[1] + halfOfHeight - pointPadding];
|
||||
endPoint = [center[0] - halfOfWidth + pointPadding, center[1] + halfOfHeight];
|
||||
}
|
||||
break;
|
||||
case 'left':
|
||||
rstart = bbox.width / 2;
|
||||
rend = bbox.width / 2;
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] - cosDeltaStart, center[1] + sinDeltaStart];
|
||||
endPoint = [center[0] - cosDeltaEnd, center[1] - sinDeltaEnd];
|
||||
rstart = halfOfWidth;
|
||||
rend = halfOfWidth;
|
||||
if (shapeType === 'circle') {
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] - cosDeltaStart, center[1] + sinDeltaStart];
|
||||
endPoint = [center[0] - cosDeltaEnd, center[1] - sinDeltaEnd];
|
||||
} else {
|
||||
startPoint = [center[0] - halfOfWidth, center[1] - pointPadding];
|
||||
endPoint = [center[0] - halfOfWidth, center[1] + pointPadding];
|
||||
}
|
||||
break;
|
||||
case 'top-left':
|
||||
rstart = bbox.width / 2;
|
||||
rend = bbox.height / 2;
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] - cosDeltaStart, center[1] - sinDeltaStart];
|
||||
endPoint = [center[0] - sinDeltaEnd, center[1] - cosDeltaEnd];
|
||||
rstart = halfOfWidth;
|
||||
rend = halfOfHeight;
|
||||
if (shapeType === 'circle') {
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
cosDeltaEnd = rend * SELF_LINK_COS;
|
||||
startPoint = [center[0] - cosDeltaStart, center[1] - sinDeltaStart];
|
||||
endPoint = [center[0] - sinDeltaEnd, center[1] - cosDeltaEnd];
|
||||
} else {
|
||||
startPoint = [center[0] - halfOfWidth + pointPadding, center[1] - halfOfHeight];
|
||||
endPoint = [center[0] - halfOfWidth, center[1] - halfOfHeight + pointPadding];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rstart = bbox.width / 2;
|
||||
rend = bbox.width / 2;
|
||||
rstart = halfOfWidth;
|
||||
rend = halfOfWidth;
|
||||
sinDeltaStart = rstart * SELF_LINK_SIN;
|
||||
cosDeltaStart = rstart * SELF_LINK_COS;
|
||||
sinDeltaEnd = rend * SELF_LINK_SIN;
|
||||
@ -381,7 +434,7 @@ export const truncateLabelByLength = (text: string, length: number) => {
|
||||
return text;
|
||||
}
|
||||
return text.substring(0, length) + '...';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* construct the trees from combos data
|
||||
@ -600,7 +653,11 @@ export const reconstructTree = (
|
||||
return trees;
|
||||
};
|
||||
|
||||
export const getComboBBox = (children: ComboTree[], graph: IAbstractGraph, combo?: ICombo): BBox => {
|
||||
export const getComboBBox = (
|
||||
children: ComboTree[],
|
||||
graph: IAbstractGraph,
|
||||
combo?: ICombo,
|
||||
): BBox => {
|
||||
const comboBBox = {
|
||||
minX: Infinity,
|
||||
minY: Infinity,
|
||||
@ -625,7 +682,7 @@ export const getComboBBox = (children: ComboTree[], graph: IAbstractGraph, combo
|
||||
x: x,
|
||||
y: y,
|
||||
width: undefined,
|
||||
height: undefined
|
||||
height: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
@ -671,26 +728,26 @@ export const shouldRefreshEdge = (cfg) => {
|
||||
|
||||
export const cloneBesidesImg = (obj) => {
|
||||
const clonedObj = {};
|
||||
Object.keys(obj).forEach(key1 => {
|
||||
Object.keys(obj).forEach((key1) => {
|
||||
const obj2 = obj[key1];
|
||||
if (isObject(obj2) && !isArray(obj2)) {
|
||||
const clonedObj2 = {};
|
||||
Object.keys(obj2).forEach(key2 => {
|
||||
Object.keys(obj2).forEach((key2) => {
|
||||
const v = obj2[key2];
|
||||
if (key2 === 'img' && !isString(v)) return;
|
||||
clonedObj2[key2] = clone(v);
|
||||
})
|
||||
});
|
||||
clonedObj[key1] = clonedObj2;
|
||||
} else {
|
||||
clonedObj[key1] = clone(obj2);
|
||||
}
|
||||
});
|
||||
return clonedObj;
|
||||
}
|
||||
};
|
||||
|
||||
export const getAnimateCfgWithCallback = ({
|
||||
animateCfg,
|
||||
callback
|
||||
callback,
|
||||
}: {
|
||||
animateCfg: GraphAnimateConfig;
|
||||
callback: () => void;
|
||||
@ -699,7 +756,7 @@ export const getAnimateCfgWithCallback = ({
|
||||
if (!animateCfg) {
|
||||
animateConfig = {
|
||||
duration: 500,
|
||||
callback
|
||||
callback,
|
||||
};
|
||||
} else {
|
||||
animateConfig = clone(animateCfg);
|
||||
@ -708,10 +765,10 @@ export const getAnimateCfgWithCallback = ({
|
||||
animateConfig.callback = () => {
|
||||
callback();
|
||||
animateCfgCallback();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
animateConfig.callback = callback;
|
||||
}
|
||||
}
|
||||
return animateConfig;
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@antv/g6-element",
|
||||
"version": "0.7.7",
|
||||
"version": "0.7.8",
|
||||
"description": "A Graph Visualization Framework in JavaScript",
|
||||
"keywords": [
|
||||
"antv",
|
||||
@ -61,7 +61,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/g-base": "^0.5.1",
|
||||
"@antv/g6-core": "0.7.7",
|
||||
"@antv/g6-core": "0.7.8",
|
||||
"@antv/util": "~2.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@antv/g6",
|
||||
"version": "4.7.7",
|
||||
"version": "4.7.8",
|
||||
"description": "A Graph Visualization Framework in JavaScript",
|
||||
"keywords": [
|
||||
"antv",
|
||||
@ -66,7 +66,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/g6-pc": "0.7.7"
|
||||
"@antv/g6-pc": "0.7.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.7.7",
|
||||
|
@ -1,7 +1,7 @@
|
||||
import G6 from '@antv/g6-pc';
|
||||
|
||||
G6.version = '4.7.7';
|
||||
G6.version = '4.7.8';
|
||||
|
||||
export * from '@antv/g6-pc';
|
||||
export default G6;
|
||||
export const version = '4.7.7';
|
||||
export const version = '4.7.8';
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@antv/g6-pc",
|
||||
"version": "0.7.7",
|
||||
"version": "0.7.8",
|
||||
"description": "A Graph Visualization Framework in JavaScript",
|
||||
"keywords": [
|
||||
"antv",
|
||||
@ -75,9 +75,9 @@
|
||||
"@antv/g-canvas": "^0.5.2",
|
||||
"@antv/g-math": "^0.1.1",
|
||||
"@antv/g-svg": "^0.5.1",
|
||||
"@antv/g6-core": "0.7.7",
|
||||
"@antv/g6-element": "0.7.7",
|
||||
"@antv/g6-plugin": "0.7.7",
|
||||
"@antv/g6-core": "0.7.8",
|
||||
"@antv/g6-element": "0.7.8",
|
||||
"@antv/g6-plugin": "0.7.8",
|
||||
"@antv/hierarchy": "^0.6.7",
|
||||
"@antv/layout": "^0.3.0",
|
||||
"@antv/matrix-util": "^3.1.0-beta.3",
|
||||
|
@ -7,7 +7,7 @@ const textColor = 'rgb(0, 0, 0)';
|
||||
const colorSet = getColorsWithSubjectColor(subjectColor, backColor);
|
||||
|
||||
export default {
|
||||
version: '0.7.7',
|
||||
version: '0.7.8',
|
||||
rootContainerClassName: 'root-container',
|
||||
nodeContainerClassName: 'node-container',
|
||||
edgeContainerClassName: 'edge-container',
|
||||
|
372
packages/pc/tests/unit/issues-loop-spec.ts
Normal file
372
packages/pc/tests/unit/issues-loop-spec.ts
Normal file
@ -0,0 +1,372 @@
|
||||
import G6, { Graph } from '../../src';
|
||||
import { Arrow } from '../../src';
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.id = 'container';
|
||||
document.body.appendChild(div);
|
||||
|
||||
|
||||
describe('issues', () => {
|
||||
it('basic test ui', () => {
|
||||
|
||||
const nodes = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'rect',
|
||||
color: '#333',
|
||||
x: 100,
|
||||
y: 200,
|
||||
size: [80, 80],
|
||||
label: 'rect',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
type: 'rect',
|
||||
color: '#333',
|
||||
x: 100,
|
||||
y: 400,
|
||||
size: [400, 80],
|
||||
label: 'rect',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
type: 'circle',
|
||||
color: '#666',
|
||||
x: 100,
|
||||
y: 700,
|
||||
size: [200, 40],
|
||||
label: 'circle',
|
||||
},
|
||||
];
|
||||
|
||||
const directions = [
|
||||
'top-left',
|
||||
'top',
|
||||
'top-right',
|
||||
'right',
|
||||
'bottom-right',
|
||||
'bottom',
|
||||
'bottom-left',
|
||||
'left',
|
||||
];
|
||||
|
||||
const edges = [];
|
||||
nodes.forEach((node) => {
|
||||
const perNodeEdge = directions.map((currentDirection) => ({
|
||||
source: node.id,
|
||||
target: node.id,
|
||||
type: 'loop',
|
||||
loopCfg: {
|
||||
position: currentDirection,
|
||||
dist: 20,
|
||||
pointPadding: 15,
|
||||
clockwise: true,
|
||||
},
|
||||
}));
|
||||
edges.push(...perNodeEdge);
|
||||
});
|
||||
|
||||
const data = {
|
||||
nodes,
|
||||
edges,
|
||||
};
|
||||
const graph = new G6.Graph({
|
||||
container: div,
|
||||
width: 800,
|
||||
height: 800,
|
||||
fitCenter: true,
|
||||
defaultNode: {
|
||||
type: 'rect',
|
||||
},
|
||||
});
|
||||
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
});
|
||||
|
||||
it('test position right calc pointPadding value is ok ', () => {
|
||||
const node =
|
||||
{
|
||||
id: '1',
|
||||
type: 'rect',
|
||||
color: '#333',
|
||||
x: 100,
|
||||
y: 200,
|
||||
size: [80, 80],
|
||||
label: 'rect',
|
||||
style: {
|
||||
lineWidth: 0
|
||||
},
|
||||
}
|
||||
const edge = {
|
||||
source: '1',
|
||||
target: '1',
|
||||
type: 'loop',
|
||||
loopCfg: {
|
||||
position: 'right',
|
||||
dist: 20,
|
||||
pointPadding: 15,
|
||||
},
|
||||
}
|
||||
|
||||
const data = {
|
||||
nodes: [node],
|
||||
edges: [edge],
|
||||
};
|
||||
|
||||
const graph = new G6.Graph({
|
||||
container: div,
|
||||
width: 800,
|
||||
height: 800,
|
||||
fitCenter: true,
|
||||
});
|
||||
|
||||
const center = [node.x, node.y]
|
||||
const halfOfWidth = node.size[0] / 2
|
||||
const halfOfHeight = node.size[1] / 2
|
||||
const pointPadding = edge.loopCfg.pointPadding
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
const startPoint = [center[0] + halfOfWidth, center[1] - pointPadding];
|
||||
const endPoint = [center[0] + halfOfWidth, center[1] + pointPadding];
|
||||
|
||||
const { edges } = data
|
||||
const currentEdges = edges[0]
|
||||
|
||||
//@ts-ignore
|
||||
expect([currentEdges.startPoint.x, currentEdges.startPoint.y]).toEqual(startPoint);
|
||||
//@ts-ignore
|
||||
expect([currentEdges.endPoint.x, currentEdges.endPoint.y]).toEqual(endPoint);
|
||||
})
|
||||
|
||||
it('test position top-right calc pointPadding value is ok ', () => {
|
||||
const node =
|
||||
{
|
||||
id: '1',
|
||||
type: 'rect',
|
||||
color: '#333',
|
||||
x: 100,
|
||||
y: 200,
|
||||
size: [80, 80],
|
||||
label: 'rect',
|
||||
style: {
|
||||
lineWidth: 0
|
||||
},
|
||||
}
|
||||
const edge = {
|
||||
source: '1',
|
||||
target: '1',
|
||||
type: 'loop',
|
||||
loopCfg: {
|
||||
position: 'top-right',
|
||||
dist: 20,
|
||||
pointPadding: 15,
|
||||
},
|
||||
}
|
||||
|
||||
const data = {
|
||||
nodes: [node],
|
||||
edges: [edge],
|
||||
};
|
||||
|
||||
const graph = new G6.Graph({
|
||||
container: div,
|
||||
width: 800,
|
||||
height: 800,
|
||||
fitCenter: true,
|
||||
});
|
||||
|
||||
|
||||
const center = [node.x, node.y]
|
||||
const halfOfWidth = node.size[0] / 2
|
||||
const halfOfHeight = node.size[1] / 2
|
||||
const pointPadding = edge.loopCfg.pointPadding
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
|
||||
const startPoint = [center[0] + halfOfWidth - pointPadding, center[1] - halfOfHeight];
|
||||
const endPoint = [center[0] + halfOfWidth, center[1] - halfOfHeight + pointPadding];
|
||||
|
||||
const { edges } = data
|
||||
const currentEdges = edges[0]
|
||||
|
||||
//@ts-ignore
|
||||
expect([currentEdges.startPoint.x, currentEdges.startPoint.y]).toEqual(startPoint);
|
||||
//@ts-ignore
|
||||
expect([currentEdges.endPoint.x, currentEdges.endPoint.y]).toEqual(endPoint);
|
||||
})
|
||||
|
||||
|
||||
it('test unset pointPadding and final pointPadding calc is ok', () => {
|
||||
const node =
|
||||
{
|
||||
id: '1',
|
||||
type: 'rect',
|
||||
color: '#333',
|
||||
x: 100,
|
||||
y: 200,
|
||||
size: [80, 80],
|
||||
label: 'rect',
|
||||
style: {
|
||||
lineWidth: 0
|
||||
},
|
||||
}
|
||||
const edge = {
|
||||
source: '1',
|
||||
target: '1',
|
||||
type: 'loop',
|
||||
loopCfg: {
|
||||
position: 'top-right',
|
||||
dist: 20,
|
||||
},
|
||||
}
|
||||
|
||||
const data = {
|
||||
nodes: [node],
|
||||
edges: [edge],
|
||||
};
|
||||
|
||||
const graph = new G6.Graph({
|
||||
container: div,
|
||||
width: 800,
|
||||
height: 800,
|
||||
fitCenter: true,
|
||||
});
|
||||
|
||||
const center = [node.x, node.y]
|
||||
const halfOfWidth = node.size[0] / 2
|
||||
const halfOfHeight = node.size[1] / 2
|
||||
// 预期 pointPadding 为 20
|
||||
const pointPadding = 20
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
|
||||
const startPoint = [center[0] + halfOfWidth - pointPadding, center[1] - halfOfHeight];
|
||||
const endPoint = [center[0] + halfOfWidth, center[1] - halfOfHeight + pointPadding];
|
||||
|
||||
const { edges } = data
|
||||
const currentEdges = edges[0]
|
||||
|
||||
//@ts-ignore
|
||||
expect([currentEdges.startPoint.x, currentEdges.startPoint.y]).toEqual(startPoint);
|
||||
//@ts-ignore
|
||||
expect([currentEdges.endPoint.x, currentEdges.endPoint.y]).toEqual(endPoint);
|
||||
})
|
||||
|
||||
it('test set pointPadding greater than minimum height and width minimum value , final pointPadding calc is ok', () => {
|
||||
const node =
|
||||
{
|
||||
id: '1',
|
||||
type: 'rect',
|
||||
color: '#333',
|
||||
x: 100,
|
||||
y: 200,
|
||||
size: [80, 80],
|
||||
label: 'rect',
|
||||
style: {
|
||||
lineWidth: 0
|
||||
},
|
||||
}
|
||||
const edge = {
|
||||
source: '1',
|
||||
target: '1',
|
||||
type: 'loop',
|
||||
loopCfg: {
|
||||
position: 'top-right',
|
||||
dist: 20,
|
||||
clockwise: true,
|
||||
pointPadding: 1000,
|
||||
},
|
||||
}
|
||||
|
||||
const data = {
|
||||
nodes: [node],
|
||||
edges: [edge],
|
||||
};
|
||||
|
||||
const graph = new G6.Graph({
|
||||
container: div,
|
||||
width: 800,
|
||||
height: 800,
|
||||
fitCenter: true,
|
||||
});
|
||||
|
||||
const center = [node.x, node.y]
|
||||
const halfOfWidth = node.size[0] / 2
|
||||
const halfOfHeight = node.size[1] / 2
|
||||
// 预期 pointPadding 为 40
|
||||
const pointPadding = 40
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
|
||||
const startPoint = [center[0] + halfOfWidth - pointPadding, center[1] - halfOfHeight];
|
||||
const endPoint = [center[0] + halfOfWidth, center[1] - halfOfHeight + pointPadding];
|
||||
|
||||
const { edges } = data
|
||||
const currentEdges = edges[0]
|
||||
|
||||
//@ts-ignore
|
||||
expect([currentEdges.startPoint.x, currentEdges.startPoint.y]).toEqual(startPoint);
|
||||
//@ts-ignore
|
||||
expect([currentEdges.endPoint.x, currentEdges.endPoint.y]).toEqual(endPoint);
|
||||
})
|
||||
|
||||
|
||||
it('test set clockwise => true, calc pointPadding is ok', () => {
|
||||
const node =
|
||||
{
|
||||
id: '1',
|
||||
type: 'rect',
|
||||
color: '#333',
|
||||
x: 100,
|
||||
y: 200,
|
||||
size: [80, 80],
|
||||
label: 'rect',
|
||||
style: {
|
||||
lineWidth: 0
|
||||
},
|
||||
}
|
||||
const edge = {
|
||||
source: '1',
|
||||
target: '1',
|
||||
type: 'loop',
|
||||
loopCfg: {
|
||||
position: 'top-right',
|
||||
dist: 20,
|
||||
clockwise: true,
|
||||
pointPadding: 1000,
|
||||
},
|
||||
}
|
||||
|
||||
const data = {
|
||||
nodes: [node],
|
||||
edges: [edge],
|
||||
};
|
||||
|
||||
const graph = new G6.Graph({
|
||||
container: div,
|
||||
width: 800,
|
||||
height: 800,
|
||||
fitCenter: true,
|
||||
});
|
||||
|
||||
const center = [node.x, node.y]
|
||||
const halfOfWidth = node.size[0] / 2
|
||||
const halfOfHeight = node.size[1] / 2
|
||||
// 预期 pointPadding 为 40
|
||||
const pointPadding = 40
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
|
||||
const startPoint = [center[0] + halfOfWidth - pointPadding, center[1] - halfOfHeight];
|
||||
const endPoint = [center[0] + halfOfWidth, center[1] - halfOfHeight + pointPadding];
|
||||
|
||||
const { edges } = data
|
||||
const currentEdges = edges[0]
|
||||
|
||||
//@ts-ignore
|
||||
expect([currentEdges.startPoint.x, currentEdges.startPoint.y]).toEqual(startPoint);
|
||||
//@ts-ignore
|
||||
expect([currentEdges.endPoint.x, currentEdges.endPoint.y]).toEqual(endPoint);
|
||||
})
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@antv/g6-plugin",
|
||||
"version": "0.7.7",
|
||||
"version": "0.7.8",
|
||||
"description": "G6 Plugin",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
@ -22,8 +22,8 @@
|
||||
"@antv/g-base": "^0.5.1",
|
||||
"@antv/g-canvas": "^0.5.2",
|
||||
"@antv/g-svg": "^0.5.2",
|
||||
"@antv/g6-core": "0.7.7",
|
||||
"@antv/g6-element": "0.7.7",
|
||||
"@antv/g6-core": "0.7.8",
|
||||
"@antv/g6-element": "0.7.8",
|
||||
"@antv/matrix-util": "^3.1.0-beta.3",
|
||||
"@antv/scale": "^0.3.4",
|
||||
"@antv/util": "^2.0.9",
|
||||
|
@ -132,11 +132,12 @@ const graph = new G6.Graph({
|
||||
|
||||
### loopCfg
|
||||
|
||||
`loopCfg` is an object that configures the direction, height, and clockwise.
|
||||
`loopCfg` is an object that configures the direction, height, and clockwise, connection point start and end position.
|
||||
|
||||
- `position`: The relative position to the source/target node. Options: `top`, `top-right`, `right`,`bottom-right`, `bottom`, `bottom-left`, `left`, `top-left`. `top` by default.
|
||||
- `dist`: The distance between the keyShape of the source/target node to the highest position of the loop. It is equal to the height of the source/target node by default.
|
||||
- `clockwise`: Whether to draw the loop clockwisely. `true` by default
|
||||
- `pointPadding`: For non-circular nodes, the offset between the connection point and the node center coordinates ('top right', 'bottom right', 'top left', 'bottom left', which are special, four angular coordinates) in the x-axis or y-axis direction, the default value is' 1/4 of the minimum value of node width and height '. *Supported by v4.7.8.*
|
||||
|
||||
Base on the code in [style](#style) section, we add `loopCfg` to `defaultEdge`.<br /> <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*z9dwTZvACcEAAAAAAAAAAABkARQnAQ' width=100 alt='img'/>
|
||||
|
||||
@ -152,6 +153,7 @@ const graph = new G6.Graph({
|
||||
position: 'left',
|
||||
dist: 100,
|
||||
clockwise: false,
|
||||
pointPadding: 15,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -132,11 +132,12 @@ const graph = new G6.Graph({
|
||||
|
||||
### 自环特殊配置 loopCfg
|
||||
|
||||
Object 类型。通过 `loopCfg` 配置自环的方位、高度、顺逆时针。
|
||||
Object 类型。通过 `loopCfg` 配置自环的方位、高度、顺逆时针、连接起始点位置。
|
||||
|
||||
- `position`: 指定自环与节点的相对位置。默认为:`top`。支持的值有:`top`, `top-right`, `right`,`bottom-right`, `bottom`, `bottom-left`, `left`, `top-left`
|
||||
- `dist`: 从节点 keyShape 的边缘到自环最顶端的位置,用于指定自环的曲度,默认为节点的高度。
|
||||
- `clockwise`: 指定是否顺时针画环,默认为 `true`。
|
||||
- `pointPadding`: 对于非圆形节点设置的连接点与节点中心坐标(`top-right`,`bottom-right`,`top-left`,`bottom-left`较特殊,为四个角坐标)在 x 轴或 y 轴方向的偏移量,默认为 `节点宽高中最小值的1/4`,*v4.7.8 后支持*。
|
||||
|
||||
基于上面 [样式属性 style](#XQFb2) 中的代码,下面代码在 `defaultEdge` 中增加了 `loopCfg` 配置项进行文本的配置,使之达到如下图效果。<br /> <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*z9dwTZvACcEAAAAAAAAAAABkARQnAQ' width=100 alt='img'/>
|
||||
|
||||
@ -152,6 +153,7 @@ const graph = new G6.Graph({
|
||||
position: 'left',
|
||||
dist: 100,
|
||||
clockwise: false,
|
||||
pointPadding: 15,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@antv/g6-site",
|
||||
"version": "4.7.7",
|
||||
"version": "4.7.8",
|
||||
"description": "G6 sites deployed on gh-pages",
|
||||
"keywords": [
|
||||
"antv",
|
||||
@ -36,7 +36,7 @@
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^4.0.6",
|
||||
"@antv/chart-node-g6": "^0.0.3",
|
||||
"@antv/g6": "4.7.7",
|
||||
"@antv/g6": "4.7.8",
|
||||
"@antv/gatsby-theme-antv": "1.1.15",
|
||||
"@antv/util": "^2.0.9",
|
||||
"@antv/vis-predict-engine": "^0.1.1",
|
||||
|
Loading…
Reference in New Issue
Block a user