hierarchical-estimates-visu.../lib/d3experiment.js

281 lines
5.8 KiB
JavaScript
Raw Normal View History

import React, { useState, useEffect } from "react";
2022-01-30 15:29:45 +00:00
import * as d3 from "d3";
2022-01-30 15:29:45 +00:00
export function drawChart(height, width) {
d3.select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height)
.style("border", "1px solid black")
.append("text")
.attr("fill", "green")
.attr("x", 50)
.attr("y", 50)
.text("Hello D3");
}
2022-01-30 15:29:45 +00:00
export function drawCircles() {
var svg = d3
.select("#circles")
.append("svg")
.attr("width", 960)
.attr("height", 500)
.attr("bgcolor", "blue");
var background = svg
.append("rect")
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "blue");
2022-01-30 15:29:45 +00:00
var ball = svg
.append("circle")
.attr("r", 73)
.attr("cx", 480)
.attr("cy", 250)
.style("fill", "#ffe41e");
}
2022-01-30 15:29:45 +00:00
export function drawGraph() {
let margin = { top: 20, right: 30, bottom: 20, left: 30 };
let width = 900 - margin.left - margin.right;
let height = 600 - margin.top - margin.bottom;
2022-01-30 15:29:45 +00:00
var svg = d3
.select("#graph")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
2022-01-30 15:29:45 +00:00
let data = {
nodes: [
{
id: 1,
name: "A",
},
{
id: 2,
name: "B",
},
{
id: 3,
name: "C",
},
{
id: 4,
name: "D",
},
{
id: 5,
name: "E",
},
{
id: 6,
name: "F",
},
{
id: 7,
name: "G",
},
{
id: 8,
name: "H",
},
{
id: 9,
name: "I",
},
{
id: 10,
name: "J",
},
],
links: [
{
source: 1,
target: 2,
},
{
source: 1,
target: 5,
},
{
source: 1,
target: 6,
},
{
source: 2,
target: 3,
},
{
source: 2,
target: 7,
},
{
source: 3,
target: 4,
},
{
source: 8,
target: 3,
},
{
source: 4,
target: 5,
},
{
source: 4,
target: 9,
},
{
source: 5,
target: 10,
},
],
};
console.log(data);
// List of node names
var allNodes = data.nodes.map(function (d) {
return d.name;
});
2022-01-30 15:29:45 +00:00
// A linear scale to position the nodes on the X axis
var x = d3.scalePoint().range([0, width]).domain(allNodes);
// Add the circle for the nodes
svg
.selectAll("mynodes")
.data(data.nodes)
.enter()
.append("circle")
.attr("cx", function (d) {
return x(d.name);
})
.attr("cy", height - 30)
.attr("r", 8)
.style("fill", "#69b3a2");
// And give them a label
svg
.selectAll("mylabels")
.data(data.nodes)
.enter()
.append("text")
2022-01-30 15:29:45 +00:00
.attr("x", function (d) {
return x(d.name);
})
.attr("y", height - 10)
.text(function (d) {
return d.name;
})
.style("text-anchor", "middle");
2022-01-30 15:29:45 +00:00
// Add links between nodes. Here is the tricky part.
// In my input data, links are provided between nodes -id-, NOT between node names.
// So I have to do a link between this id and the name
var idToNode = {};
data.nodes.forEach(function (n) {
idToNode[n.id] = n;
});
// Cool, now if I do idToNode["2"].name I've got the name of the node with id 2
2022-01-30 15:29:45 +00:00
// Add the links
svg
.selectAll("mylinks")
.data(data.links)
.enter()
.append("path")
.attr("d", function (d) {
let start = x(idToNode[d.source].name);
// X position of start node on the X axis
let end = x(idToNode[d.target].name);
// X position of end node
return (
[
"M",
start,
height - 30,
// the arc starts at the coordinate x=start, y=height-30 (where the starting node is)
"A",
// This means we're gonna build an elliptical arc
(start - end) / 2,
",",
// Next 2 lines are the coordinates of the inflexion point. Height of this point is proportional with start - end distance
(start - end) / 2,
0,
0,
",",
start < end ? 1 : 0,
end,
",",
height - 30,
]
// We always want the arc on top. So if end is before start, putting 0 here turn the arc upside down.
.join(" ")
);
})
.style("fill", "none")
.attr("stroke", "black");
2022-01-30 15:29:45 +00:00
// labels for links
svg
.selectAll("mylinks")
.data(data.links)
.enter()
.append("text")
.attr("x", function (d) {
let start = x(idToNode[d.source].name);
// X position of start node on the X axis
let end = x(idToNode[d.target].name);
// X position of end node
return start + (end - start) / 2;
})
.attr("y", function (d) {
let start = x(idToNode[d.source].name);
// X position of start node on the X axis
let end = x(idToNode[d.target].name);
// X position of end node
return height - 30 - Math.abs(start - end) / 2; //height-30
})
.text(function (d) {
return `${idToNode[d.source].name}-${idToNode[d.target].name}`;
})
.style("text-anchor", "top");
2022-01-30 15:29:45 +00:00
svg
.selectAll("text")
.data(data.links)
.enter()
.append("text")
.attr("x", function (d) {
return d.source.x + (d.target.x - d.source.x) / 2;
})
.attr("y", function (d) {
return d.source.y + (d.target.y - d.source.y) / 2;
})
.text(function (d) {
return d.something;
});
}
2022-01-30 15:29:45 +00:00
export function D3Experiment() {
useEffect(() => {
drawGraph();
}, []);
2022-01-30 15:29:45 +00:00
return (
<div>
<div id="chart"></div>
<div id="circles"></div>
<div id="graph"></div>
</div>
);
}
2022-01-30 15:29:45 +00:00
export default D3Experiment;