@antv/g6
Version:
graph visualization frame work
460 lines (394 loc) • 13.3 kB
JavaScript
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
var Shape = require('../shape');
var deepMix = require('@antv/util/lib/deep-mix');
var Global = require('../../global'); // 菱形shape
Shape.registerNode('triangle', {
// 自定义节点时的配置
options: {
size: 40,
direction: 'up',
style: {
stroke: Global.defaultShapeStrokeColor,
fill: Global.defaultShapeFillColor,
lineWidth: 1
},
// 文本样式配置
labelCfg: {
style: {
fill: '#595959'
},
offset: 15
},
stateStyles: {
// 鼠标hover状态下的配置
hover: {
fillOpacity: 0.8
},
// 选中节点状态下的配置
selected: {
lineWidth: 3
}
},
// 节点上左右上下四个方向上的链接circle配置
linkPoints: {
top: false,
right: false,
bottom: false,
left: false,
// circle的大小
size: 5,
lineWidth: 1,
fill: '#fff',
stroke: '#72CC4A'
},
// 节点中icon配置
icon: {
// 是否显示icon,值为 false 则不渲染icon
show: false,
// icon的地址,字符串类型
img: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',
width: 16,
height: 16,
offset: 6
}
},
shapeType: 'triangle',
// 文本位置
labelPosition: 'bottom',
drawShape: function drawShape(cfg, group) {
var customOptions = this.getCustomConfig(cfg) || {};
var _this$options = this.options,
defaultIcon = _this$options.icon,
defaultDirection = _this$options.direction;
var customIcon = customOptions.icon,
customDirection = customOptions.direction;
var style = this.getShapeStyle(cfg);
var icon = deepMix({}, defaultIcon, customIcon, cfg.icon);
var direction = cfg.direction || customDirection || defaultDirection;
var keyShape = group.addShape('path', {
attrs: style
});
var w = icon.width,
h = icon.height,
show = icon.show,
offset = icon.offset;
if (show) {
var iconW = -w / 2;
var iconH = -h / 2;
if (direction === 'up' || direction === 'down') {
iconH += offset;
}
if (direction === 'left' || direction === 'right') {
iconW += offset;
}
var image = group.addShape('image', {
attrs: _extends({
x: iconW,
y: iconH
}, icon),
className: 'triangle-icon'
});
image.set('capture', false);
}
this.drawLinkPoints(cfg, group);
return keyShape;
},
/**
* 绘制节点上的LinkPoints
* @param {Object} cfg data数据配置项
* @param {Group} group Group实例
*/
drawLinkPoints: function drawLinkPoints(cfg, group) {
var customOptions = this.getCustomConfig(cfg) || {};
var _this$options2 = this.options,
defaultLinkPoints = _this$options2.linkPoints,
defaultDirection = _this$options2.direction;
var customLinkPoints = customOptions.linkPoints,
customDirection = customOptions.direction;
var linkPoints = deepMix({}, defaultLinkPoints, customLinkPoints, cfg.linkPoints);
var direction = cfg.direction || customDirection || defaultDirection;
var top = linkPoints.top,
left = linkPoints.left,
right = linkPoints.right,
bottom = linkPoints.bottom,
markSize = linkPoints.size,
markStyle = _objectWithoutPropertiesLoose(linkPoints, ["top", "left", "right", "bottom", "size"]);
var size = this.getSize(cfg);
var len = size[0];
if (left) {
// up down left right 四个方向的坐标均不相同
var leftPos = null;
var diffY = len * Math.sin(1 / 3 * Math.PI);
var r = len * Math.sin(1 / 3 * Math.PI);
if (direction === 'up') {
leftPos = [-r, diffY];
} else if (direction === 'down') {
leftPos = [-r, -diffY];
} else if (direction === 'left') {
leftPos = [-r, r - diffY];
}
if (leftPos) {
// left circle
group.addShape('circle', {
attrs: _extends({}, markStyle, {
x: leftPos[0],
y: leftPos[1],
r: markSize
}),
className: 'triangle-mark-left'
});
}
}
if (right) {
// right circle
// up down left right 四个方向的坐标均不相同
var rightPos = null;
var _diffY = len * Math.sin(1 / 3 * Math.PI);
var _r = len * Math.sin(1 / 3 * Math.PI);
if (direction === 'up') {
rightPos = [_r, _diffY];
} else if (direction === 'down') {
rightPos = [_r, -_diffY];
} else if (direction === 'right') {
rightPos = [_r, _r - _diffY];
}
if (rightPos) {
group.addShape('circle', {
attrs: _extends({}, markStyle, {
x: rightPos[0],
y: rightPos[1],
r: markSize
}),
className: 'triangle-mark-right'
});
}
}
if (top) {
// up down left right 四个方向的坐标均不相同
var topPos = null;
var _diffY2 = len * Math.sin(1 / 3 * Math.PI);
var _r2 = len * Math.sin(1 / 3 * Math.PI);
if (direction === 'up') {
topPos = [_r2 - _diffY2, -_diffY2];
} else if (direction === 'left') {
topPos = [_r2, -_diffY2];
} else if (direction === 'right') {
topPos = [-_r2, -_diffY2];
}
if (topPos) {
// top circle
group.addShape('circle', {
attrs: _extends({}, markStyle, {
x: topPos[0],
y: topPos[1],
r: markSize
}),
className: 'triangle-mark-top'
});
}
}
if (bottom) {
// up down left right 四个方向的坐标均不相同
var bottomPos = null;
var _diffY3 = len * Math.sin(1 / 3 * Math.PI);
var _r3 = len * Math.sin(1 / 3 * Math.PI);
if (direction === 'down') {
bottomPos = [-_r3 + _diffY3, _diffY3];
} else if (direction === 'left') {
bottomPos = [_r3, _diffY3];
} else if (direction === 'right') {
bottomPos = [-_r3, _diffY3];
}
if (bottomPos) {
// bottom circle
group.addShape('circle', {
attrs: _extends({}, markStyle, {
x: bottomPos[0],
y: bottomPos[1],
r: markSize
}),
className: 'triangle-mark-bottom'
});
}
}
},
getPath: function getPath(cfg) {
var customOptions = this.getCustomConfig(cfg) || {};
var defaultDirection = this.options.direction;
var customDirection = customOptions.direction;
var direction = cfg.direction || customDirection || defaultDirection;
var size = this.getSize(cfg);
var len = size[0];
var diffY = len * Math.sin(1 / 3 * Math.PI);
var r = len * Math.sin(1 / 3 * Math.PI);
var path = [['M', -r, diffY], ['L', 0, -diffY], ['L', r, diffY], ['Z'] // 封闭
];
if (direction === 'down') {
path = [['M', -r, -diffY], ['L', r, -diffY], ['L', 0, diffY], ['Z'] // 封闭
];
} else if (direction === 'left') {
path = [['M', -r, r - diffY], ['L', r, -r], ['L', r, r], ['Z'] // 封闭
];
} else if (direction === 'right') {
path = [['M', r, r - diffY], ['L', -r, r], ['L', -r, -r], ['Z'] // 封闭
];
}
return path;
},
/**
* 获取节点的样式,供基于该节点自定义时使用
* @param {Object} cfg 节点数据模型
* @return {Object} 节点的样式
*/
getShapeStyle: function getShapeStyle(cfg) {
var customOptions = this.getCustomConfig(cfg) || {};
var defaultStyle = this.options.style;
var customStyle = customOptions.style;
var strokeStyle = {
stroke: cfg.color
}; // 如果设置了color,则覆盖默认的stroke属性
var style = deepMix({}, defaultStyle, customStyle, strokeStyle, cfg.style);
var path = this.getPath(cfg);
var styles = _extends({
path: path
}, style);
return styles;
},
update: function update(cfg, item) {
var group = item.getContainer();
var customOptions = this.getCustomConfig(cfg) || {};
var _this$options3 = this.options,
defaultStyle = _this$options3.style,
defaultIcon = _this$options3.icon,
defaultLabelCfg = _this$options3.labelCfg;
var customStyle = customOptions.style,
customIcon = customOptions.icon,
customLabelCfg = customOptions.labelCfg;
var style = deepMix({}, defaultStyle, customStyle, cfg.style);
var icon = deepMix({}, defaultIcon, customIcon, cfg.icon);
var keyShape = item.get('keyShape');
var path = this.getPath(cfg);
keyShape.attr(_extends({
path: path
}, style));
var labelCfg = deepMix({}, defaultLabelCfg, customLabelCfg, cfg.labelCfg);
var labelStyle = this.getLabelStyle(cfg, labelCfg, group);
var text = group.findByClassName('node-label');
if (text) {
text.attr(_extends({}, labelStyle));
}
var triangleIcon = group.findByClassName('triangle-icon');
if (triangleIcon) {
var w = icon.width,
h = icon.height;
triangleIcon.attr(_extends({
x: -w / 2,
y: -h / 2
}, icon));
}
this.updateLinkPoints(cfg, group);
},
/**
* 更新linkPoints
* @param {Object} cfg 节点数据配置项
* @param {Group} group Item所在的group
*/
updateLinkPoints: function updateLinkPoints(cfg, group) {
var customOptions = this.getCustomConfig(cfg) || {};
var _this$options4 = this.options,
defaultLinkPoints = _this$options4.linkPoints,
defaultDirection = _this$options4.direction;
var customLinkPoints = customOptions.linkPoints,
customDirection = customOptions.direction;
var linkPoints = deepMix({}, defaultLinkPoints, customLinkPoints, cfg.linkPoints);
var direction = cfg.direction || customDirection || defaultDirection;
var markSize = linkPoints.size,
markStyle = _objectWithoutPropertiesLoose(linkPoints, ["size"]);
var size = this.getSize(cfg);
var len = size[0];
var markLeft = group.findByClassName('triangle-mark-left');
if (markLeft) {
var leftPos = null;
var diffY = len * Math.sin(1 / 3 * Math.PI);
var r = len * Math.sin(1 / 3 * Math.PI);
if (direction === 'up') {
leftPos = [-r, diffY];
} else if (direction === 'down') {
leftPos = [-r, -diffY];
} else if (direction === 'left') {
leftPos = [-r, r - diffY];
}
if (leftPos) {
// left circle
markLeft.attr(_extends({}, markStyle, {
x: leftPos[0],
y: leftPos[1],
r: markSize
}));
}
}
var markRight = group.findByClassName('triangle-mark-right');
if (markRight) {
var rightPos = null;
var _diffY4 = len * Math.sin(1 / 3 * Math.PI);
var _r4 = len * Math.sin(1 / 3 * Math.PI);
if (direction === 'up') {
rightPos = [_r4, _diffY4];
} else if (direction === 'down') {
rightPos = [_r4, -_diffY4];
} else if (direction === 'right') {
rightPos = [_r4, _r4 - _diffY4];
}
if (rightPos) {
markRight.attr(_extends({}, markStyle, {
x: rightPos[0],
y: rightPos[1],
r: markSize
}));
}
}
var markTop = group.findByClassName('triangle-mark-top');
if (markTop) {
var topPos = null;
var _diffY5 = len * Math.sin(1 / 3 * Math.PI);
var _r5 = len * Math.sin(1 / 3 * Math.PI);
if (direction === 'up') {
topPos = [_r5 - _diffY5, -_diffY5];
} else if (direction === 'left') {
topPos = [_r5, -_diffY5];
} else if (direction === 'right') {
topPos = [-_r5, -_diffY5];
}
if (topPos) {
// top circle
markTop.attr(_extends({}, markStyle, {
x: topPos[0],
y: topPos[1],
r: markSize
}));
}
}
var markBottom = group.findByClassName('triangle-mark-bottom');
if (markBottom) {
var bottomPos = null;
var _diffY6 = len * Math.sin(1 / 3 * Math.PI);
var _r6 = len * Math.sin(1 / 3 * Math.PI);
if (direction === 'down') {
bottomPos = [-_r6 + _diffY6, _diffY6];
} else if (direction === 'left') {
bottomPos = [_r6, _diffY6];
} else if (direction === 'right') {
bottomPos = [-_r6, _diffY6];
}
if (bottomPos) {
// bottom circle
markBottom.attr(_extends({}, markStyle, {
x: bottomPos[0],
y: bottomPos[1],
r: markSize
}));
}
}
}
}, 'single-shape');