mirror of
https://gitee.com/antv/g6.git
synced 2024-12-15 01:51:00 +08:00
116 lines
2.6 KiB
JavaScript
116 lines
2.6 KiB
JavaScript
/**
|
|
* @fileOverview 圆形布局
|
|
* @author huangtonger@aliyun.com
|
|
*/
|
|
const G6 = require('../../src/index');
|
|
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;
|