chart = {
let cluster = clusterWidget == "true" ? true : false;
const width = 800, height = 600;
const stage = new PIXI.Container();
const renderer = PIXI.autoDetectRenderer({
width: width,
height: height,
antialias: true,
autoResize:true,
resolution: 2,
backgroundColor: 0xFFFFFF
});
const context = new PIXI.Graphics();
stage.addChild(context);
const color = (function() {
let scale = d3.scaleOrdinal(d3.schemeCategory10);
return (num) => parseInt(scale(num).slice(1), 16);
})();
const links = new PIXI.Graphics();
stage.addChild(links);
graph.nodes.forEach((node) => {
node.gfx = new PIXI.Graphics();
node.gfx.lineStyle(1.5, 0xFFFFFF);
node.gfx.beginFill(color(node.group));
node.gfx.drawCircle(0, 0, 5);
node.gfx.interactive = true;
node.gfx.buttonMode = true;
node.gfx.on("pointerover", ()=>pointerOver(node));
node.gfx.on("pointerout", ()=>pointerOut(node));
stage.addChild(node.gfx);
});
const simulation = d3.forceSimulation()
.nodes(graph.nodes)
.force('link', d3.forceLink().id((d) => d.id))
.force('charge', d3.forceManyBody().strength(-5))
.force('center', d3.forceCenter(width / 2, height / 2))
.force("forceInABox", forceInABox()
.strength(0.5)
.groupBy("group")
.enableGrouping(cluster)
.forceNodeSize(d => 8)
.size([width, height])
)
.on('tick', ticked);
simulation
.force('link')
.links(graph.links);
function ticked() {
graph.nodes.forEach((node) => {
let { x, y, gfx } = node;
gfx.position = new PIXI.Point(x, y);
});
links.clear();
links.alpha = 0.6;
graph.links.forEach((link) => {
let { source, target } = link;
links.lineStyle(Math.sqrt(link.value), 0xEEEEEE);
links.moveTo(source.x, source.y);
links.lineTo(target.x, target.y);
});
links.endFill();
renderer.render(stage);
}
d3.select(renderer.view)
.call(d3.drag()
.container(renderer.view)
.subject((d)=>simulation.find(d.x, d.y, 10))
.on('start', dragstarted)
.on('drag', dragged)
.on('end', dragended)
);
function dragstarted(e, d) {
hideTooltip();
if (!e.active) {
simulation
.alphaTarget(0.3)
.restart();
}
e.subject.fx = e.subject.x;
e.subject.fy = e.subject.y;
}
function dragged(e,d) {
e.subject.fx = e.x;
e.subject.fy = e.y;
}
function dragended(e,d) {
if (!e.active) {
simulation.alphaTarget(0);
}
e.subject.fx = null;
e.subject.fy = null;
}
function pointerOver(node){
showTooltip(node);
node.gfx.tint = 0x666666;
renderer.render(stage);
}
function pointerOut(node){
hideTooltip();
node.gfx.tint = 0xFFFFFF;
renderer.render(stage);
}
const tooltipDom = d3.select("body")
.append("div")
.attr("style",`
display: none;
font-family: sans-serif;
font-size: 12px;
position: absolute;
padding: 0.5em;
color: #fff;
background-color: #333;
z-index: +9;
`);
function showTooltip(node){
const offset = document.querySelector("canvas").getBoundingClientRect();
tooltipDom
.text(node.id)
.style("display","inline-block")
.style("left",`${offset.x + node.x + 10 }px`)
.style("top",`${offset.y + node.y + 10}px`)
}
function hideTooltip() {
tooltipDom
.text("")
.style("display","none")
.style("top","-100px")
.style("left","-100px");
}
return Object.assign(renderer.view, { style: `width: ${width}px` });
}