versio 0.1
d3 = require("d3@7")
data = d3.csv("https://gist.githubusercontent.com/Juuso1/4b92d153a02263380b2560f2e7e42d09/raw/muuttoliike_kangasala_2021.csv", d3.autoType)
data_2 = d3.csv("https://gist.githubusercontent.com/Juuso1/f2fcdaf8c6053f315f1bc1a67bbd4c61/raw/kangasala_tampere_pienalue_2021.csv", d3.autoType)
data_3 = d3.csv("https://gist.githubusercontent.com/Juuso1/722dc5a035c757f2032125fbea751142/raw/kangasala_lempaala_pienalue_2021.csv", d3.autoType)
data_4 = d3.csv("https://gist.githubusercontent.com/Juuso1/145ce37f1f10433c6cbc4831f244602e/raw/kangasala_nokia_pienalue_2021.csv", d3.autoType)
data_5 = d3.csv("https://gist.githubusercontent.com/Juuso1/7951de54348c5de46db9e4bf3173afe6/raw/kangasala_orivesi_pienalue.csv", d3.autoType)
data_6 = d3.csv("https://gist.githubusercontent.com/Juuso1/e66c94b930972e105c450045aea8c7b2/raw/kangasala_pirkkala_pienalue_2021.csv", d3.autoType)
data_7 = d3.csv("https://gist.githubusercontent.com/Juuso1/5690853d57d677826555a37f759c1c95/raw/kangasala_palkane_pienalue_2021.csv", d3.autoType)
data_8 = d3.csv("https://gist.githubusercontent.com/Juuso1/dcb98508964bc6c255280637be4135cc/raw/kangasala_akaa_pienalue.csv", d3.autoType)
data_9 = d3.csv("https://gist.githubusercontent.com/Juuso1/22b5fe1ec9e3a8bf353c7b17a301d4a9/raw/kangasala_valkeakoski-pienalueet.csv", d3.autoType)
data_10 = d3.csv("https://gist.githubusercontent.com/Juuso1/47bebabe370259a9a5ae2709460fac9b/raw/kangasala_ylojarvi_pienalueet.csv", d3.autoType)
chord = d3.chordDirected()
.padAngle(0.8 / innerRadius)
.sortSubgroups(d3.ascending)
.sortChords(d3.ascending)
matrix = {
const index = new Map(names.map((name, i) => [name, i]));
const matrix = Array.from(index, () => new Array(names.length).fill(0));
for (const {source, target, value} of data) matrix[index.get(source)][index.get(target)] += value;
return matrix;
}
chart = {
let sum_target;
let sum_source;
let sum_yht;
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 3, width, height]);
const chords = chord(matrix);
const group = svg.append("g")
.attr("font-size", 2)
.attr("font-family", "Century Gothic")
.attr("font-weight", "bold")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("fill", d => {
sum_target = d3.sum(chords, c => (c.target.index === d.index) * c.target.value);
sum_source = d3.sum(chords, c => (c.source.index === d.index) * c.source.value);
sum_yht = sum_target-sum_source;
if (sum_yht > 0) { return "#009651" }
else if (sum_yht == 0) { return "#28336C" }
else { return "#DE232F" }
})
.attr("d", arc);
group.append("text")
.each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
.attr("dy", "0.35em")
.attr("transform", d => `
rotate(${(d.angle * 180 / Math.PI - 90)})
translate(${outerRadius + 5})
${d.angle > Math.PI ? "rotate(180)" : ""}
`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text(d => names[d.index])
.attr("fill", d => {
sum_target = d3.sum(chords, c => (c.target.index === d.index) * c.target.value);
sum_source = d3.sum(chords, c => (c.source.index === d.index) * c.source.value);
sum_yht = sum_target-sum_source;
if (sum_yht > 0) { return "#009651" }
else if (sum_yht == 0) { return "#28336C" }
else { return "#DE232F" }
});
group.append("title")
.text(d => `${names[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);
svg.append("g")
.attr("fill-opacity", 0.75)
.selectAll("path")
.data(chords)
.join("path")
.style("mix-blend-mode", "multiply")
//.attr("fill", d => color(names[d.source.index]))
.attr("fill", d => {
//if (names[d.index] === "Kangasala") {return "#DE232F"}
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
else { return "#28336C" }
;})
.attr("d", ribbon)
.append("title")
.text(d => `${names[d.source.index]} --> ${names[d.target.index]} ${d.source.value}`);
return svg.node();
}
chord_2 = d3.chordDirected()
.padAngle(1 / innerRadius)
.sortSubgroups(d3.ascending)
.sortChords(d3.ascending)
matrix_2 = {
const index = new Map(names_2.map((name, i) => [name, i]));
const matrix_2 = Array.from(index, () => new Array(names_2.length).fill(0));
for (const {source, target, value} of data_2) matrix_2[index.get(source)][index.get(target)] += value;
return matrix_2;
}
chart_2 = {
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 3, width, height]);
const chords = chord_2(matrix_2);
const group = svg.append("g")
.attr("font-size", 2)
.attr("font-family", "Century Gothic")
.attr("font-weight", "bold")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;})
.attr("d", arc);
group.append("text")
.each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
.attr("dy", "0.35em")
.attr("transform", d => `
rotate(${(d.angle * 180 / Math.PI - 90)})
translate(${outerRadius + 5})
${d.angle > Math.PI ? "rotate(180)" : ""}
`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text(d => names_2[d.index])
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;});
group.append("title")
.text(d => `${names_2[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);
svg.append("g")
.attr("fill-opacity", 0.75)
.selectAll("path")
.data(chords)
.join("path")
.style("mix-blend-mode", "multiply")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
else { return "#28336C" }
;})
.attr("d", ribbon_2)
.append("title")
.text(d => `${names_2[d.source.index]} --> ${names_2[d.target.index]} ${d.source.value}`);
return svg.node();
}
chord_3 = d3.chordDirected()
.padAngle(1 / innerRadius)
.sortSubgroups(d3.ascending)
.sortChords(d3.ascending)
matrix_3 = {
const index = new Map(names_3.map((name, i) => [name, i]));
const matrix_3 = Array.from(index, () => new Array(names_3.length).fill(0));
for (const {source, target, value} of data_3) matrix_3[index.get(source)][index.get(target)] += value;
return matrix_3;
}
chart_3 = {
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 3, width, height]);
const chords = chord_3(matrix_3);
const group = svg.append("g")
.attr("font-size", 2)
.attr("font-family", "Century Gothic")
.attr("font-weight", "bold")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;})
.attr("d", arc);
group.append("text")
.each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
.attr("dy", "0.35em")
.attr("transform", d => `
rotate(${(d.angle * 180 / Math.PI - 90)})
translate(${outerRadius + 5})
${d.angle > Math.PI ? "rotate(180)" : ""}
`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text(d => names_3[d.index])
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;});
group.append("title")
.text(d => `${names_3[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);
svg.append("g")
.attr("fill-opacity", 0.75)
.selectAll("path")
.data(chords)
.join("path")
.style("mix-blend-mode", "multiply")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
else { return "#28336C" }
;})
.attr("d", ribbon_3)
.append("title")
.text(d => `${names_3[d.source.index]} --> ${names_3[d.target.index]} ${d.source.value}`);
return svg.node();
}
chord_4 = d3.chordDirected()
.padAngle(1 / innerRadius)
.sortSubgroups(d3.ascending)
.sortChords(d3.ascending)
matrix_4 = {
const index = new Map(names_4.map((name, i) => [name, i]));
const matrix_4 = Array.from(index, () => new Array(names_4.length).fill(0));
for (const {source, target, value} of data_4) matrix_4[index.get(source)][index.get(target)] += value;
return matrix_4;
}
chart_4 = {
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 3, width, height]);
const chords = chord_4(matrix_4);
const group = svg.append("g")
.attr("font-size", 2)
.attr("font-family", "Century Gothic")
.attr("font-weight", "bold")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;})
.attr("d", arc);
group.append("text")
.each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
.attr("dy", "0.35em")
.attr("transform", d => `
rotate(${(d.angle * 180 / Math.PI - 90)})
translate(${outerRadius + 5})
${d.angle > Math.PI ? "rotate(180)" : ""}
`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text(d => names_4[d.index])
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;});
group.append("title")
.text(d => `${names_4[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);
svg.append("g")
.attr("fill-opacity", 0.75)
.selectAll("path")
.data(chords)
.join("path")
.style("mix-blend-mode", "multiply")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
else { return "#28336C" }
;})
.attr("d", ribbon_4)
.append("title")
.text(d => `${names_4[d.source.index]} --> ${names_4[d.target.index]} ${d.source.value}`);
return svg.node();
}
chord_5 = d3.chordDirected()
.padAngle(1 / innerRadius)
.sortSubgroups(d3.ascending)
.sortChords(d3.ascending)
matrix_5 = {
const index = new Map(names_5.map((name, i) => [name, i]));
const matrix_5 = Array.from(index, () => new Array(names_5.length).fill(0));
for (const {source, target, value} of data_5) matrix_5[index.get(source)][index.get(target)] += value;
return matrix_5;
}
chart_5 = {
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 3, width, height]);
const chords = chord_5(matrix_5);
const group = svg.append("g")
.attr("font-size", 2)
.attr("font-family", "Century Gothic")
.attr("font-weight", "bold")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;})
.attr("d", arc);
group.append("text")
.each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
.attr("dy", "0.35em")
.attr("transform", d => `
rotate(${(d.angle * 180 / Math.PI - 90)})
translate(${outerRadius + 5})
${d.angle > Math.PI ? "rotate(180)" : ""}
`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text(d => names_5[d.index])
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;});
group.append("title")
.text(d => `${names_5[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);
svg.append("g")
.attr("fill-opacity", 0.75)
.selectAll("path")
.data(chords)
.join("path")
.style("mix-blend-mode", "multiply")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
else { return "#28336C" }
;})
.attr("d", ribbon_5)
.append("title")
.text(d => `${names_5[d.source.index]} --> ${names_5[d.target.index]} ${d.source.value}`);
return svg.node();
}
chord_6 = d3.chordDirected()
.padAngle(1 / innerRadius)
.sortSubgroups(d3.ascending)
.sortChords(d3.ascending)
matrix_6 = {
const index = new Map(names_6.map((name, i) => [name, i]));
const matrix_6 = Array.from(index, () => new Array(names_6.length).fill(0));
for (const {source, target, value} of data_6) matrix_6[index.get(source)][index.get(target)] += value;
return matrix_6;
}
chart_6 = {
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 3, width, height]);
const chords = chord_6(matrix_6);
const group = svg.append("g")
.attr("font-size", 2)
.attr("font-family", "Century Gothic")
.attr("font-weight", "bold")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;})
.attr("d", arc);
group.append("text")
.each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
.attr("dy", "0.35em")
.attr("transform", d => `
rotate(${(d.angle * 180 / Math.PI - 90)})
translate(${outerRadius + 5})
${d.angle > Math.PI ? "rotate(180)" : ""}
`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text(d => names_6[d.index])
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;});
group.append("title")
.text(d => `${names_6[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);
svg.append("g")
.attr("fill-opacity", 0.75)
.selectAll("path")
.data(chords)
.join("path")
.style("mix-blend-mode", "multiply")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
else { return "#28336C" }
;})
.attr("d", ribbon_6)
.append("title")
.text(d => `${names_6[d.source.index]} --> ${names_6[d.target.index]} ${d.source.value}`);
return svg.node();
}
chord_7 = d3.chordDirected()
.padAngle(1 / innerRadius)
.sortSubgroups(d3.ascending)
.sortChords(d3.ascending)
matrix_7 = {
const index = new Map(names_7.map((name, i) => [name, i]));
const matrix_7 = Array.from(index, () => new Array(names_7.length).fill(0));
for (const {source, target, value} of data_7) matrix_7[index.get(source)][index.get(target)] += value;
return matrix_7;
}
chart_7 = {
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 3, width, height]);
const chords = chord_7(matrix_7);
const group = svg.append("g")
.attr("font-size", 2)
.attr("font-family", "Century Gothic")
.attr("font-weight", "bold")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;})
.attr("d", arc);
group.append("text")
.each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
.attr("dy", "0.35em")
.attr("transform", d => `
rotate(${(d.angle * 180 / Math.PI - 90)})
translate(${outerRadius + 5})
${d.angle > Math.PI ? "rotate(180)" : ""}
`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text(d => names_7[d.index])
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;});
group.append("title")
.text(d => `${names_7[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);
svg.append("g")
.attr("fill-opacity", 0.75)
.selectAll("path")
.data(chords)
.join("path")
.style("mix-blend-mode", "multiply")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
else { return "#28336C" }
;})
.attr("d", ribbon_7)
.append("title")
.text(d => `${names_7[d.source.index]} --> ${names_7[d.target.index]} ${d.source.value}`);
return svg.node();
}
chord_8 = d3.chordDirected()
.padAngle(1 / innerRadius)
.sortSubgroups(d3.ascending)
.sortChords(d3.ascending)
matrix_8 = {
const index = new Map(names_8.map((name, i) => [name, i]));
const matrix_8 = Array.from(index, () => new Array(names_8.length).fill(0));
for (const {source, target, value} of data_8) matrix_8[index.get(source)][index.get(target)] += value;
return matrix_8;
}
chart_8 = {
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 3, width, height]);
const chords = chord_8(matrix_8);
const group = svg.append("g")
.attr("font-size", 2)
.attr("font-family", "Century Gothic")
.attr("font-weight", "bold")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;})
.attr("d", arc);
group.append("text")
.each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
.attr("dy", "0.35em")
.attr("transform", d => `
rotate(${(d.angle * 180 / Math.PI - 90)})
translate(${outerRadius + 5})
${d.angle > Math.PI ? "rotate(180)" : ""}
`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text(d => names_8[d.index])
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;});
group.append("title")
.text(d => `${names_8[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);
svg.append("g")
.attr("fill-opacity", 0.75)
.selectAll("path")
.data(chords)
.join("path")
.style("mix-blend-mode", "multiply")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
else { return "#28336C" }
;})
.attr("d", ribbon_8)
.append("title")
.text(d => `${names_8[d.source.index]} --> ${names_8[d.target.index]} ${d.source.value}`);
return svg.node();
}
chord_9 = d3.chordDirected()
.padAngle(1 / innerRadius)
.sortSubgroups(d3.ascending)
.sortChords(d3.ascending)
matrix_9 = {
const index = new Map(names_9.map((name, i) => [name, i]));
const matrix_9 = Array.from(index, () => new Array(names_9.length).fill(0));
for (const {source, target, value} of data_9) matrix_9[index.get(source)][index.get(target)] += value;
return matrix_9;
}
chart_9 = {
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 3, width, height]);
const chords = chord_9(matrix_9);
const group = svg.append("g")
.attr("font-size", 2)
.attr("font-family", "Century Gothic")
.attr("font-weight", "bold")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;})
.attr("d", arc);
group.append("text")
.each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
.attr("dy", "0.35em")
.attr("transform", d => `
rotate(${(d.angle * 180 / Math.PI - 90)})
translate(${outerRadius + 5})
${d.angle > Math.PI ? "rotate(180)" : ""}
`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text(d => names_9[d.index])
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;});
group.append("title")
.text(d => `${names_9[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);
svg.append("g")
.attr("fill-opacity", 0.75)
.selectAll("path")
.data(chords)
.join("path")
.style("mix-blend-mode", "multiply")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
else { return "#28336C" }
;})
.attr("d", ribbon_9)
.append("title")
.text(d => `${names_9[d.source.index]} --> ${names_9[d.target.index]} ${d.source.value}`);
return svg.node();
}
chord_10 = d3.chordDirected()
.padAngle(1 / innerRadius)
.sortSubgroups(d3.ascending)
.sortChords(d3.ascending)
matrix_10 = {
const index = new Map(names_10.map((name, i) => [name, i]));
const matrix_10 = Array.from(index, () => new Array(names_10.length).fill(0));
for (const {source, target, value} of data_10) matrix_10[index.get(source)][index.get(target)] += value;
return matrix_10;
}
chart_10 = {
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 3, width, height]);
const chords = chord_10(matrix_10);
const group = svg.append("g")
.attr("font-size", 2)
.attr("font-family", "Century Gothic")
.attr("font-weight", "bold")
.selectAll("g")
.data(chords.groups)
.join("g");
group.append("path")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;})
.attr("d", arc);
group.append("text")
.each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
.attr("dy", "0.35em")
.attr("transform", d => `
rotate(${(d.angle * 180 / Math.PI - 90)})
translate(${outerRadius + 5})
${d.angle > Math.PI ? "rotate(180)" : ""}
`)
.attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
.text(d => names_10[d.index])
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
else { return "#DE232F" }
;});
group.append("title")
.text(d => `${names_10[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);
svg.append("g")
.attr("fill-opacity", 0.75)
.selectAll("path")
.data(chords)
.join("path")
.style("mix-blend-mode", "multiply")
.attr("fill", d => {
if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
else { return "#28336C" }
;})
.attr("d", ribbon_10)
.append("title")
.text(d => `${names_10[d.source.index]} --> ${names_10[d.target.index]} ${d.source.value}`);
return svg.node();
}
Copyright 2023 Kangasalan kaupunki, LGPL 2.1