chart202006 = {
const width = visSetting.width;
const height = visSetting.height;
let dtStartDateThreshold = 1577836800000;
console.log(dtStartDateThreshold);
const reflectAmountNode = visSetting.reflectAmountNode;
const linkFilter = function(links, removedNodes){
let filtered = [];
let leftNodeIds = [];
for(let i =0;i<links.length; i++){
if (removedNodes.indexOf(links[i].source) >= 0 || removedNodes.indexOf(links[i].target) >= 0){
continue;
}else{
filtered.push(links[i]);
leftNodeIds.push(links[i].source);
leftNodeIds.push(links[i].target);
}
}
return [filtered, leftNodeIds];
}
const grantTypeFilter = visSetting.filters.grantType;
const isGrantType = function(n) {
if (n.type != "Grant")
return true;
else{
return n.category == grantTypeFilter;
}
}
const nodeTypeFilter = visSetting.filters.nodeTypes;
const isNodeType = function(n){
return nodeTypeFilter.indexOf(n.type) >= 0;
}
const isValidGranByTime = function(n){
if (n.type != "Grant")
return true;
return n.start <= dtStartDateThreshold;
}
//set filter function
let filterFuncImp = null;
if (visSetting.filters.filterAction == "nodeTypes")
filterFuncImp = isNodeType;
else if (visSetting.filters.filterAction == "grantType")
filterFuncImp = isGrantType;
const nodeFilter = function(nodes, filterFunc){
let left = [];
let removed = []
for(let i =0;i<nodes.length; i++){
if (isValidGranByTime(nodes[i]) && (filterFunc == null || filterFunc(nodes[i]))){
left.push(nodes[i]);
}
else
removed.push(nodes[i].id);
}
return [left, removed];
}
const nodeFilterResults = nodeFilter(data.nodes, filterFuncImp);
const linkFilteredResults = linkFilter(data.links, nodeFilterResults[1]);
const leftNodeIds = linkFilteredResults[1];
const filteredLinks = linkFilteredResults[0];
// need to do another filtering to only keep nodes which have at least one link
let leftNodes = [];
let filteredNodes = nodeFilterResults[0];
let totalAmount = 0;
let nums = {"grant": 0, "org": 0}
for (let i=0;i<filteredNodes.length;i++){
if (leftNodeIds.indexOf(filteredNodes[i].id) >= 0){
leftNodes.push(filteredNodes[i]);
if (filteredNodes[i].type == "Grant"){
totalAmount += filteredNodes[i].amount;
nums["grant"] += 1;
}else if(filteredNodes[i].type == "organisation"){
nums["org"] += 1;
}
}
}
jQuery('#messageBoard').html(
"Total £:" + (totalAmount / 1000 / 1000).toFixed(2) + "m" +
" #grants:" + nums["grant"] +
" #org:" + nums["org"]
);
const links = filteredLinks.map(d => Object.create(d));
const nodes = leftNodes.map(d => Object.create(d));
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
const g = svg.append("g");
const link = g
.attr("stroke", "#999")
.attr("stroke-opacity", 0.6)
.selectAll("line")
.data(links)
.join("line")
// .attr("stroke-width", d => d.strength)
// .attr("stroke-width", function (d) {
// if (d.ref == "PI_PER")
// return 1;
// else
// return 0.5;
// }).attr("stroke", function (d) {
// if (d.strength < 1)
// return "green";
// });
const node = g
// svg.append("g")
// .attr("stroke", "#fff")
// .attr("stroke-width", 1.5)
.selectAll("g")
.data(nodes)
.join("g");
const circles = node.append("circle")
.join("circle")
.attr("r", function (d) {
if (d.type == reflectAmountNode){
if (d.amount == 0)
return visSetting.nodeSize;
else
return Math.log(d.amount);
}else{
return visSetting.nodeSize;
}
})
.attr("fill", color)
.call(drag(simulation));
node.append("text")
.attr("y", 3)
.attr("x", 6)
.text(function(d){
if (visSetting.showNameNodeTypes.indexOf(d.type) >= 0)
return d.name;
else
return "";
})
.style("font-size", `${visSetting.fontSize}px`)
.style("font-family", "Verdana, sans-serif");
node.append("title")
.text(function(d) {
let r = d.name
if (d.type == "Grant"){
const dt = new Date(d.start);
r += " started at " + dt.getFullYear();
}
return r;
});
// display the legend
const legend_g = svg.selectAll(".legend")
.data(nodeTypes)
.enter().append("g")
.attr("transform", (d, i) => `translate(${width - 160},${i * 20 + 10})`);
legend_g.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", visSetting.nodeSize)
.attr("fill", styColor);
legend_g.append("text")
.attr("x", 10)
.attr("y", 5)
.style("font-size", `${visSetting.fontSize}px`)
.style("font-family", "Verdana")
.text(d => d);
simulation.on("tick", () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
// node
// .attr("cx", d => d.x)
// .attr("cy", d => d.y);
node
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
});
invalidation.then(() => simulation.stop());
svg.call(d3.zoom()
.extent([[0, 0], [width / 2, height / 2]])
.scaleExtent([.1, 8])
.on("zoom", zoomed));
function zoomed({transform}) {
g.attr("transform", transform);
}
return svg.node();
}