g6/plugins/tool.fisheye/tool.js
2018-08-08 10:08:34 +08:00

83 lines
1.9 KiB
JavaScript

/**
* @fileOverview force atlas 2
* @author shiwu.wyy@antfin.com
*/
const G6 = require('@antv/g6');
const Util = G6.Util;
class Tool {
constructor(options) {
Util.mix(this, {
/**
* radius
* @type {number}
*/
radius: 200,
/**
* defualt zoom center
* @type {array}
*/
center: [ 0, 0 ],
/**
* defualt magnification factor
* @type {number}
*/
d: 1.0
}, options);
}
zoom(centerx, centery) {
const {
graph,
radius,
d
} = this;
const center = [ centerx, centery ];
const nodes = graph.getNodes();
const size = nodes.length;
// pick out the nodes inside the radius
for (let i = 0; i < size; i += 1) {
const node = nodes[i].getModel();
const dist = Math.hypot(node.x - center[0], node.y - center[1]);
if (dist < radius) {
// take the center as the origin
const movedCoords = [ node.x - center[0], node.y - center[1] ];
// transform to polar coordinates
const { p, theta } = Rect2Polar(movedCoords[0], movedCoords[1]);
const pf = radius * (((d + 1) * (p / radius)) / (d * (p / radius) + 1)); // after fisheye zooming
// transform to rect coordinates
const { x, y } = Polar2Rect(pf, theta);
// move back to the original origin
nodes[i].getModel().x = x + center[0];
nodes[i].getModel().y = y + center[1];
}
}
}
}
function Rect2Polar(x, y) {
const p = Math.hypot(x, y);
let theta;
if (y >= 0) {
if (x === 0) {
theta = Math.PI / 2; // 90°
} else {
theta = Math.acos(x / p);
}
} else if (y < 0) {
if (x === 0) {
theta = 3 * Math.PI / 2; // 270°
} else {
theta = 2 * Math.PI - Math.acos(x / p);
}
}
return { p, theta };
}
function Polar2Rect(p, theta) {
const x = p * Math.cos(theta);
const y = p * Math.sin(theta);
return { x, y };
}
module.exports = Tool;