function createBarChart() {
const margin = { top: 50, right: 50, bottom: 100, left: 100 };
const width = 700 - margin.left - margin.right;
const height = 700 - margin.top - margin.bottom;
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);
const tooltip = d3
.select("body")
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("visibility", "hidden")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "1px")
.style("border-radius", "5px")
.style("padding", "10px");
const regions = Array.from(new Set(datasetWithArea.map((d) => d.area)));
const numChartsPerRow = 1;
const paddingFactor = 1;
regions.forEach((region, i) => {
const row = Math.floor(i / numChartsPerRow);
const col = i % numChartsPerRow;
const chartWidth = width / numChartsPerRow;
const chartHeight = height / Math.ceil(regions.length / numChartsPerRow);
const barWidth = chartWidth / 2;
const regionData = datasetWithArea.filter((d) => d.area === region);
// 各言語の合計数を計算
const totalLanguages = regionData.length;
const languageCounts = d3.rollup(
regionData,
(v) => v.length / totalLanguages, // 各言語の割合を計算
(d) => d.original
);
const languageCountsArray = Array.from(
languageCounts,
([original, count]) => ({ original, count })
);
languageCountsArray.sort((a, b) => d3.descending(a.count, b.count));
// 積み上げ横棒グラフ用のデータを作成
let cumulative = 0;
for (const d of languageCountsArray) {
d.start = cumulative;
cumulative += d.count;
d.end = cumulative;
}
const yScale = d3
.scaleBand()
.domain(languageCountsArray.map((d) => d.original))
.range([0, chartHeight])
.padding(0.1);
const xScale = d3.scaleLinear().domain([0, 1]).range([0, chartWidth]);
const chartGroup = svg
.append("g")
.attr(
"transform",
`translate(${col * chartWidth * paddingFactor},${
row * chartHeight * paddingFactor
})`
);
// 地域名を表示
chartGroup
.append("circle")
.attr("cx", margin.left - 80)
.attr("cy", margin.top - 16)
.attr("r", 5) // 円の半径
.attr("fill", (d) => colorScale(region)); // 各地域に対応する色を設定
chartGroup
.append("text")
.attr("x", margin.left - 70) // テキストのx座標をmargin.leftに設定
.attr("y", margin.top - 13) // 上部に配置するため、y座標をmargin.topに設定
.attr("text-anchor", "start")
.attr("fill", "black")
.text(region)
.attr("font-size", "10px");
// 積み上げ横棒グラフを描画
chartGroup
.selectAll("rect")
.data(languageCountsArray)
.enter()
.append("rect")
.attr("x", (d) => xScale(d.start))
.attr("width", (d) => xScale(d.end) - xScale(d.start))
.attr("height", 20) // すべての帯の高さを20に設定する
.attr("fill", (d) => colorScale2(d.original))
// ツールチップを表示するイベントを追加
.on("mouseover", function (event, d) {
tooltip
.style("visibility", "visible")
.html(
`<div>${d.original}<br>割合:${d3.format(".1%")(d.count)}</div>`
);
})
.on("mousemove", function (event) {
var tooltipWidth = tooltip.node().offsetWidth;
// マウスのX座標によって条件分岐
var tooltipX =
event.pageX < window.innerWidth / 2
? event.pageX + 10
: event.pageX - tooltipWidth - 10;
// ツールチップをマウスの位置に移動
tooltip
.style("top", event.pageY + 10 + "px")
.style("left", tooltipX + "px")
.style("width", "200px");
})
.on("mouseout", function () {
tooltip.style("visibility", "hidden");
});
// 棒の上に数値を表示
chartGroup
.selectAll(".label")
.data(languageCountsArray)
.enter()
.append("text")
.attr("class", "label")
.attr("x", (d) => xScale(d.start))
.attr("dy", "1em")
.attr("dx", 5)
.attr("text-anchor", "start")
.text((d) => {
if (xScale(d.end) - xScale(d.start) > 60) {
return d.original;
} else {
return "";
}
})
.attr("font-size", "8px")
.attr("font-family", "sans-serif")
// .attr("font-size", 10)
.attr("font-weight", 600)
.attr("stroke", "#fff")
.attr("stroke-width", 2)
.attr("paint-order", "stroke fill");
});
return svg.node();
}