g6/plugins/layout.circle/layout.js
2018-06-14 11:50:35 +08:00

116 lines
2.6 KiB
JavaScript

/**
* @fileOverview 圆形布局
* @author huangtonger@aliyun.com
*/
const G6 = require('@antv/g6');
const Util = G6.Util;
class Layout {
constructor(options) {
Util.mix(this, {
/**
* 节点集
* @type {Array}
*/
nodes: null,
/**
* 圆半径
* @type {number}
*/
radius: null,
/**
* 起始点和结束点之间有多少个弧度
* @type {number}
*/
sweep: null,
/**
* 是否避免重叠
* @type {boolean}
*/
avoidOverlap: false,
/**
* 顺逆时针
* @type {boolean}
*/
clockwise: true,
/**
* 起始角度
* @type {boolean}
*/
startAngle: 3 / 2 * Math.PI,
/**
* 宽
* @type {number}
*/
width: null,
/**
* 高
* @type {number}
*/
height: null,
/**
* 图中心
* @type {object}
*/
center: null
}, options);
}
// 执行布局
execute() {
const graph = this.graph;
const nodes = this.nodes;
const width = this.width ? this.width : graph.getWidth();
const height = this.height ? this.height : graph.getHeight();
const center = this.center ? this.center : {
x: width / 2,
y: height / 2
};
const avoidOverlap = this.avoidOverlap;
const clockwise = this.clockwise;
const sweep = Util.isNil(this.sweep) ? 2 * Math.PI - 2 * Math.PI / nodes.length : this.sweep;
const dTheta = sweep / (Math.max(1, nodes.length - 1));
let radius = this.radius;
let minDistance = 0;
let i;
for (i = 0; i < nodes.length; i++) {
const node = nodes[ i ];
const width = node.width;
const height = node.height;
minDistance = Math.max(minDistance, width, height);
}
if (Util.isNumber(this.radius)) {
radius = this.radius;
} else if (nodes.length <= 1) {
radius = 0;
} else {
radius = Math.min(height, width) / 2 - minDistance;
}
if (nodes.length > 1 && avoidOverlap) {
minDistance *= 1.75;
const dcos = Math.cos(dTheta) - Math.cos(0);
const dsin = Math.sin(dTheta) - Math.sin(0);
const rMin = Math.sqrt(minDistance * minDistance / (dcos * dcos + dsin * dsin));
radius = Math.max(rMin, radius);
}
this.sort && nodes.sort(this.sort);
Util.each(nodes, (node, i) => {
const theta = this.startAngle + i * dTheta * (clockwise ? 1 : -1);
const rx = radius * Math.cos(theta);
const ry = radius * Math.sin(theta);
node.x = center.x + rx;
node.y = center.y + ry;
});
}
}
module.exports = Layout;