SuzukiChart = (data) => {
const height = 500;
const margin = { top: 100, right: 200, bottom: 110, left: 200 };
const xScale = d3
.scaleUtc()
.domain([0, 24 * 60 * 60 * 1000])
.range([margin.left, width - margin.right]);
const yScale = d3
.scaleBand()
.domain([...dataOfDates.keys()])
.range([margin.top, height - margin.bottom]);
const drinks = d3.group(dataOfPerson, (d) => d.drink);
const color = d3
.scaleOrdinal()
.domain(["緑茶", "水", "麦茶", "スムージー", "コーヒー", "ジュース", "酒"])
.range([
"#90ee90",
"#b0e0e6",
"olive",
"#db7093",
"#daa520",
"#f0e68c",
"#6a5acd"
]);
const vessels = d3.group(dataOfPerson, (d) => d.vessel);
const color2 = d3
.scaleOrdinal()
.domain([
"水筒",
"グラス",
"ペットボトル",
"マグカップ",
"コップ(樹脂)",
"湯呑み",
"プラスチックコップ",
"プラカップ",
"コップ",
"紙パック",
"プラコップ"
])
.range([
"#0000ff",
"#008080",
"#000080",
"#800080",
"#4682b4",
"#4682b4",
"#4682b4",
"#4682b4",
"#4682b4",
"#4682b4",
"#4682b4"
]);
const vesselPaths = {
水筒: "M0,-15 L12.99,7.5 -12.99,7.5 Z", //三角形
グラス: "M0,-15 A7.5,12.99 0 1,0 0,15 A7.5,12.99 0 1,0 0,-15 Z", // 楕円
ペットボトル: "M0,-15 L10,0 L0,15 L-10,0 Z M0,-15 L0,15", // ひし形
マグカップ: "M15,0 L0,10 L-15,0 L0,-10 Z M15,0 L-15,0", // 例として三角形のパス
"コップ(樹脂)": "M15,0 L0,10 L-15,0 L0,-10 Z M15,0 L-15,0", //横向きのひしがた
湯呑み: "M15,0 L0,10 L-15,0 L0,-10 Z M15,0 L-15,0",
プラスチックコップ: "M15,0 L0,10 L-15,0 L0,-10 Z M15,0 L-15,0",
プラカップ: "M15,0 L0,10 L-15,0 L0,-10 Z M15,0 L-15,0",
コップ: "M15,0 L0,10 L-15,0 L0,-10 Z M15,0 L-15,0",
紙パック: "M15,0 L0,10 L-15,0 L0,-10 Z M15,0 L-15,0",
プラコップ: "M15,0 L0,10 L-15,0 L0,-10 Z M15,0 L-15,0"
};
const temperature = d3.group(dataOfPerson, (d) => d.temperature);
const color3 = d3
.scaleOrdinal()
.domain(["あたたかい", "つめたい", "常温"])
.range(["#ff4500", "#000080", "#ffd700"]);
//(赤、紺、黄色)
const dow = (d) => "日月火水木金土".at(new Date(d).getDay());
const xAxis = d3
.axisBottom()
.scale(xScale)
.ticks(5)
.tickFormat(d3.utcFormat("%H:%M"))
.tickSize(-(height - margin.top - margin.bottom));
const yAxis = d3
.axisLeft()
.scale(yScale)
.ticks(7)
.tickFormat((d) => d3.utcFormat(`%m月%d日`)(d) + ` (${dow(d)})`)
.tickSize(-(width - margin.left - margin.right));
const svg = d3.create("svg").attr("width", width).attr("height", height);
svg
.append("g")
.attr("class", "xAxis")
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(xAxis)
.selectAll("text") // x軸の文字を選択
.remove(); // 選択した文字を削除
svg
.append("g")
.attr("class", "yAxis")
.attr("transform", `translate(${margin.left}, 0)`)
.call(yAxis)
.selectAll("text") // y軸の文字を選択
.remove(); // 選択した文字を削除
// 円(飲み物の種類)
const dayG = svg
.append("g")
.selectAll("g")
.data(dataOfDates)
.join("g")
.attr("class", "day")
.attr(
"transform",
(d) => `translate(0, ${yScale(d[0]) + yScale.bandwidth() / 2})`
);
dayG
.selectAll("circle")
.data((d) => d[1])
.join("circle")
.attr("cx", (d) => xScale(d.msec))
.attr("r", 12)
.attr("fill", (d) => color(d.drink))
.attr("opacity", 0.4);
// 形(容器)
const newDayG = svg
.append("g")
.selectAll("g")
.data(dataOfDates)
.join("g")
.attr("class", "newDay")
.attr(
"transform",
(d) => `translate(0, ${yScale(d[0]) + yScale.bandwidth() / 2})`
);
newDayG
.selectAll("path")
.data((d) => d[1])
.join("path")
.attr("transform", (d) => `translate(${xScale(d.msec)}, 0)`) // 必要に応じて位置を調整
.attr("d", (d) => vesselPaths[d.vessel]) // 対応するパスを設定
.attr("fill", (d) => color2(d.vessel))
.attr("fill", "none") // 塗りつぶしをなしに設定
.attr("stroke", (d) => color2(d.vessel)) // 縁の色を設定
.attr("stroke-width", 1) // 縁の太さを設定
.attr("opacity", 0.5);
// 小さい点(温度)
const new1DayG = svg
.append("g")
.selectAll("g")
.data(dataOfDates)
.join("g")
.attr("class", "new1Day")
.attr(
"transform",
(d) => `translate(0, ${yScale(d[0]) + yScale.bandwidth() / 2})`
);
new1DayG
.selectAll("circle")
.data((d) => d[1])
.join("circle")
.attr("cx", (d) => xScale(d.msec) + 5)
.attr("r", 2)
.attr("fill", (d) => color3(d.temperature))
.attr("opacity", 0.7);
// えだ
const xCenter = (xScale.range()[1] + xScale.range()[0]) / 2;
svg
.append("line")
.attr("x1", xCenter)
.attr("y1", margin.top - 50)
.attr("x2", xCenter)
.attr("y2", height - margin.bottom + 100)
.attr("stroke", "darkolivegreen")
.attr("stroke-width", 3);
const additionalLines = [
{
x1: xCenter - 250,
y1: margin.top + 200,
x2: xCenter,
y2: height - margin.bottom,
stroke: "darkolivegreen",
strokeWidth: 2
},
{
x1: xCenter + 250,
y1: margin.top + 160,
x2: xCenter,
y2: height - margin.bottom - 40,
stroke: "darkolivegreen",
strokeWidth: 2
},
{
x1: xCenter - 250,
y1: margin.top + 120,
x2: xCenter,
y2: height - margin.bottom - 80,
stroke: "darkolivegreen",
strokeWidth: 2
},
{
x1: xCenter + 220,
y1: margin.top + 80,
x2: xCenter,
y2: height - margin.bottom - 120,
stroke: "darkolivegreen",
strokeWidth: 2
},
{
x1: xCenter - 220,
y1: margin.top + 40,
x2: xCenter,
y2: height - margin.bottom - 160,
stroke: "darkolivegreen",
strokeWidth: 2
},
{
x1: xCenter + 200,
y1: margin.top,
x2: xCenter,
y2: height - margin.bottom - 200,
stroke: "darkolivegreen",
strokeWidth: 2
},
{
x1: xCenter - 200,
y1: margin.top - 40,
x2: xCenter,
y2: height - margin.bottom - 240,
stroke: "darkolivegreen",
strokeWidth: 2
}
];
additionalLines.forEach((line) => {
svg
.append("line")
.attr("x1", line.x1)
.attr("y1", line.y1)
.attr("x2", line.x2)
.attr("y2", line.y2)
.attr("stroke", line.stroke)
.attr("stroke-width", line.strokeWidth);
});
svg
.selectAll("g.xAxis, g.yAxis")
.selectAll("line, path")
.attr("stroke", "white")
.attr("opacity", 0.5);
svg.selectAll("g.xAxis, g.yAxis").selectAll("text").attr("font-size", 16);
return svg.node();
}