in client/client/app/components/ngbTargetPanel/ngbIdentificationsTab/ngbDiseasesPanel/ngbDiseasesBubbles/ngbDiseasesBubbles.controller.js [36:171]
drawChart(svg) {
if (!svg || !this.results) {
return;
}
const width = svg.attr('width');
const height = svg.attr('height');
const data = {
children: this.results.map((item) => ({
...item,
area: true,
children: (item.diseases || [])
.filter((disease) => disease.score >= this.scoreFilter)
.map((disease) => ({
...disease,
value: disease.score,
disease: true
}))
}))
.filter((area) => area.children.length > 0)
};
// Create a pack layout
const pack = d3hierarchy.pack()
.size([width, height])
.padding((d) => {
if (d.data && (d.data.area || d.data.disease)) {
return 5;
}
return 30;
});
const root = d3hierarchy.hierarchy(data)
.sum((d) => d.value);
const nodes = pack(root).descendants();
const getColor = (d) => {
if (d.data && d.data.disease) {
return this.ngbDiseasesChartService.getColorForScore(d.data.score);
}
return undefined;
}
const getFill = (d) => {
if (d.data && d.data.area) {
return '#ffffff';
}
return 'transparent';
}
const getStroke = (d) => {
if (d.data && (d.data.area || d.data.disease)) {
return '#eeeeee';
}
return 'transparent';
}
const getNodeID = (d, prefix) => {
if (d.data && d.data.area) {
return `${prefix}-${d.data.id}`;
}
if (
d.data &&
d.data.disease &&
d.parent &&
d.parent.data &&
d.parent.data.area
) {
return `${prefix}-${d.parent.data.id}-${d.data.id}`;
}
return undefined;
}
const blocks = svg
.selectAll('circle')
.data(nodes)
.enter()
.append('g')
.attr('transform', (d) => `translate(${d.x}, ${d.y})`);
blocks
.append('path')
.attr('class', 'node-image')
.attr('id', d=> getNodeID(d, 'path'))
.attr('d', d => circlePath(d.r))
.attr('fill', (d) => getColor(d) || getFill(d))
.attr('stroke', (d) => getColor(d) || getStroke(d));
const getYShift = (idx, total) => `${-(total / 2.0) + idx + 1.0}em`;
const showInfo = this.showInfo.bind(this);
const hideInfo = this.hideInfo.bind(this);
blocks.each(function (d) {
if (d.data && d.data.disease) {
const self = d3.select(this);
self
.on('mouseover', (node) => showInfo(node.data, node.x, node.y))
.on('mouseout', hideInfo);
}
if (d.data && d.data.disease && d.data.name && d.r > 10) {
const self = d3.select(this);
const getUrl = d => {
const id = getNodeID(d, 'clip');
if (id) {
return `url(#${id})`;
}
return undefined;
}
self
.append('clipPath')
.attr('id', d => getNodeID(d, 'clip'))
.append('circle')
.attr('cx', 0)
.attr('cy', 0)
.attr('r', d => d.r);
const text = self
.append('text')
.attr('pointer-events', 'none')
.attr('text-anchor', 'middle')
.attr('font-size', '8')
.attr('fill', 'white')
.attr('clip-path', getUrl);
d.data.name.split(/[\s,;.!?()]/)
.forEach((line, idx, total) => {
text
.append('tspan')
.text(line)
.attr('x', 0)
.attr('y', getYShift(idx, total.length));
})
} else if (d.data.area) {
d3.select(this)
.append('text')
.attr('pointer-events', 'none')
.attr('text-anchor', 'middle')
.attr('font-size', '10')
.attr('fill', '#666666')
.append('textPath')
.attr('startOffset', '50%')
.attr('href', d => getNodeID(d, '#path'))
.text(d => d.data.name);
}
});
}