Built with blockbuilder.org
Sujet : https://lyondataviz.github.io/teaching/lyon1-m2/2019/tp4.html
https://blockbuilder.org/BruJu/3b44cacedf231bedc18bc1ec00245c68
license: | |
height: NaN |
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v5.min.js"></script> | |
<style> | |
body { | |
margin: 0; | |
position: fixed; | |
top: 0; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<script> | |
var svg = d3.select("body").append("svg") | |
.attr("width", 960) | |
.attr("height", 500) | |
let colorRange = ["#ffffff", "#fcfbfd", "#fbfafc", "#fbfafc", "#faf9fc", "#faf9fc", "#faf8fb", "#f9f8fb", "#f9f7fb", "#f8f7fb", "#f8f7fa", "#f7f6fa", "#f7f6fa", "#f7f5fa", "#f6f5f9", "#f6f4f9", "#f5f4f9", "#f5f3f9", "#f4f3f8", "#f4f2f8", "#f4f2f8", "#f3f2f8", "#f3f1f7", "#f2f1f7", "#f2f0f7", "#f1f0f7", "#f1eff6", "#f0eff6", "#f0eef6", "#efeef5", "#efedf5", "#eeedf5", "#eeecf5", "#edecf4", "#edebf4", "#ecebf4", "#ebeaf3", "#ebe9f3", "#eae9f3", "#eae8f3", "#e9e8f2", "#e8e7f2", "#e8e7f2", "#e7e6f1", "#e7e5f1", "#e6e5f1", "#e5e4f0", "#e5e4f0", "#e4e3f0", "#e3e2ef", "#e3e2ef", "#e2e1ef", "#e1e1ee", "#e1e0ee", "#e0dfee", "#dfdfed", "#dedeed", "#dedded", "#ddddec", "#dcdcec", "#dbdbec", "#dbdaeb", "#dadaeb", "#d9d9ea", "#d8d8ea", "#d7d7ea", "#d7d7e9", "#d6d6e9", "#d5d5e8", "#d4d4e8", "#d3d3e8", "#d2d3e7", "#d2d2e7", "#d1d1e6", "#d0d0e6", "#cfcfe5", "#cecee5", "#cdcee5", "#cccde4", "#cbcce4", "#cbcbe3", "#cacae3", "#c9c9e2", "#c8c8e2", "#c7c7e1", "#c6c6e1", "#c5c5e0", "#c4c4e0", "#c3c3df", "#c2c3df", "#c1c2de", "#c0c1de", "#bfc0dd", "#bebfdd", "#bebedc", "#bdbddc", "#bcbcdb", "#bbbbda", "#babada", "#b9b9d9", "#b8b8d9", "#b7b7d8", "#b6b5d8", "#b5b4d7", "#b4b3d6", "#b3b2d6", "#b2b1d5", "#b1b0d5", "#b0afd4", "#afaed4", "#aeadd3", "#aeacd2", "#adabd2", "#acaad1", "#aba9d1", "#aaa8d0", "#a9a7cf", "#a8a6cf", "#a7a5ce", "#a6a4ce", "#a5a3cd", "#a4a2cd", "#a3a1cc", "#a2a0cb", "#a19fcb", "#a09eca", "#9f9dca", "#9e9cc9", "#9e9ac9", "#9d9ac8", "#9c99c8", "#9b98c7", "#9a97c7", "#9996c6", "#9895c6", "#9794c5", "#9693c5", "#9592c4", "#9491c4", "#9390c3", "#928fc3", "#918ec2", "#908dc2", "#908cc1", "#8f8bc1", "#8e8ac0", "#8d89c0", "#8c88bf", "#8b87bf", "#8a86be", "#8985be", "#8884bd", "#8883bd", "#8782bc", "#8680bc", "#857fbb", "#847eba", "#837dba", "#827cb9", "#827bb9", "#817ab8", "#8079b8", "#7f77b7", "#7e76b6", "#7e75b6", "#7d74b5", "#7c73b4", "#7b71b4", "#7b70b3", "#7a6fb3", "#796eb2", "#786cb1", "#786bb1", "#776ab0", "#7668af", "#7567af", "#7566ae", "#7465ad", "#7363ad", "#7362ac", "#7261ab", "#715fab", "#705eaa", "#705ca9", "#6f5ba8", "#6e5aa8", "#6e58a7", "#6d57a6", "#6c56a6", "#6c54a5", "#6b53a4", "#6a52a4", "#6950a3", "#694fa2", "#684ea2", "#674ca1", "#674ba0", "#664aa0", "#65489f", "#65479e", "#64469e", "#63449d", "#63439c", "#62429c", "#61409b", "#613f9a", "#603e9a", "#5f3c99", "#5e3b99", "#5e3a98", "#5d3897", "#5c3797", "#5c3696", "#5b3595", "#5a3395", "#5a3294", "#593194", "#582f93", "#582e92", "#572d92", "#562b91", "#562a91", "#552990", "#54288f", "#54268f", "#53258e", "#52248e", "#52238d", "#51218c", "#50208c", "#501f8b", "#4f1e8b", "#4e1c8a", "#4e1b8a", "#4d1a89", "#4c1988", "#4c1788", "#4b1687", "#4a1587", "#4a1486", "#491286", "#481185", "#481084", "#470f84", "#460d83", "#460c83", "#450b82", "#440a82", "#440981", "#430780", "#420680", "#42057f", "#41047f", "#40027e", "#40017e", "#3f007d"]; | |
function createAdjacencyMatrix(nodes, edges) { | |
var edgeHash = {}; | |
for (x in edges) { | |
var id = edges[x].source + "-" + edges[x].target; | |
edgeHash[id] = edges[x]; | |
} | |
matrix = []; | |
//create all possible edges | |
for (const [a, node_a] of nodes.entries()) { | |
for (const [b, node_b] of nodes.entries()) { | |
var grid = { id: node_a.id + "-" + node_b.id, x: a, y: b, sharedfollowers: 0 }; | |
if (edgeHash[grid.id]) { | |
grid.sharedfollowers = parseInt(edgeHash[grid.id].sharedfollowers); | |
} | |
matrix.push(grid); | |
} | |
} | |
return matrix; | |
} | |
function getMaximum(matrix) { | |
let maxValue = 0; | |
for (let i = 0; i != matrix.length; i++) { | |
if (maxValue < matrix[i].sharedfollowers) { | |
maxValue = matrix[i].sharedfollowers; | |
} | |
} | |
return maxValue; | |
} | |
d3.csv("liens.csv") | |
.then(function (liens) { | |
d3.csv("noeuds.csv") | |
.then(function (nodes) { | |
let matrix = createAdjacencyMatrix(nodes, liens); | |
let maxSharedFollowers = getMaximum(matrix); | |
let color = d3.scaleQuantize() | |
.domain([0, maxSharedFollowers]) | |
.range(colorRange); | |
let matriceElt = d3.select("svg") | |
.append("g") | |
.attr("transform", "translate(50,50)") | |
.attr("id", "adjacencyMatrix"); | |
const size = 25; | |
let rectangles = matriceElt.selectAll('rect') | |
.data(matrix) | |
.enter() | |
.append('rect') | |
.attr('x', function (d) { return d.x * size; }) | |
.attr('y', function (d) { return d.y * size; }) | |
.attr('width', size) | |
.attr('height', size) | |
.attr('fill', function (d) { return color(d.sharedfollowers); }) | |
.style("stroke", "grey") | |
.style("stroke-width", 0.2); | |
// Scale bands | |
let scaleSize = nodes.length * size; | |
x = d3.scaleBand() | |
.domain(nodes.map(function (el) { return el.id })) | |
.range([0, scaleSize]) | |
y = d3.scaleBand() | |
.domain(nodes.map(function (el) { return el.id }).reverse()) | |
// reverse() inverse l'ordre des éléments pour que l'affichage se fasse dans le bon ordre en x : testez sans pour voir ce qui se passe. | |
.range([scaleSize, 0]) | |
d3.select("#adjacencyMatrix") | |
.append("g") | |
.attr("transform", 'translate(0, ' + (25 * nodes.length) + ')') | |
.call(d3.axisBottom(x)) | |
.selectAll("text") | |
.attr("transform", "rotate(90)") | |
.style("text-anchor", 'start') | |
.attr("x", 10) | |
.attr("y", -5); | |
d3.select("#adjacencyMatrix") | |
.append("g") | |
.call(d3.axisLeft(y)); | |
// Guides | |
function makeGuide(guide) { | |
guide.attr('fill-opacity', 0) | |
.attr('x', 0) | |
.attr('y', 0) | |
.attr('stroke', 'black') | |
.attr('stroke-width', 1) | |
.attr('display', 'none') | |
.attr('pointer-events', 'none'); | |
} | |
let horizontalGuide = matriceElt.append('rect') | |
.attr('width', size * nodes.length) | |
.attr('height', size); | |
let verticalGuide = matriceElt.append('rect') | |
.attr('width', size) | |
.attr('height', size * nodes.length); | |
makeGuide(horizontalGuide); | |
makeGuide(verticalGuide); | |
rectangles.on('mouseover', function (e) { | |
horizontalGuide.attr('display', 'block') | |
.attr('y', e.y * size); | |
verticalGuide.attr('display', 'block') | |
.attr('x', e.x * size); | |
//console.log(e); | |
}).on('mouseout', function () { | |
verticalGuide.attr('display', 'none'); | |
horizontalGuide.attr('display', 'none'); | |
}).attr('pointer-events', 'all'); | |
//console.log(maxSharedFollowers); | |
console.log(matrix); | |
}); | |
}); | |
</script> | |
</body> |
source | target | sharedfollowers | |
---|---|---|---|
valerie | francois | 1 | |
charles | francois | 9 | |
charles | valerie | 2 | |
marie | francois | 5 | |
marie | gaston | 12 | |
marie | nicolas | 15 | |
marie | danielle | 1 | |
gaston | nicolas | 21 | |
gaston | danielle | 1 | |
danielle | marie | 3 | |
danielle | nicolas | 4 | |
danielle | francois | 4 | |
nicolas | marie | 1 | |
nicolas | gaston | 2 | |
nicolas | danielle | 5 | |
victorine | gigi | 3 |
id | followers | following | |
---|---|---|---|
valerie | 17 | 500 | |
charles | 83 | 80 | |
francois | 904 | 15 | |
marie | 7 | 5 | |
gaston | 11 | 50 | |
danielle | 80 | 85 | |
nicolas | 150 | 300 | |
victorine | 38 | 7 | |
gigi | 12 | 12 |