Visual apperance

This commit is contained in:
Adrian Rumpold
2025-07-09 11:51:32 +02:00
parent 5dc583e387
commit 86688519f5
11 changed files with 310 additions and 147 deletions

View File

@@ -2,6 +2,8 @@ import * as d3 from "d3";
import { useEffect, useRef } from "react";
import { colorScheme, config } from "../config";
import "./Chart.css";
interface QuestionGroupChartProps {
question: string;
groupData: { response: string }[];
@@ -9,6 +11,31 @@ interface QuestionGroupChartProps {
xScale: d3.ScaleBand<string>;
}
function makeDot(
shape: "rect" | "circle",
g: d3.Selection<SVGGElement, unknown, null, undefined>,
dotX: number,
dotY: number
) {
if (shape === "circle") {
return g
.append("circle")
.attr("class", "dot")
.attr("cx", dotX)
.attr("cy", dotY)
.attr("r", config.dotRadius);
} else if (shape === "rect") {
return g
.append("rect")
.attr("class", "dot")
.attr("x", dotX - config.dotRadius)
.attr("y", dotY - config.dotRadius)
.attr("width", config.dotRadius * 2)
.attr("height", config.dotRadius * 2);
}
throw new Error(`Unsupported shape: ${shape}`);
}
export function QuestionGroupChart({
question,
groupData,
@@ -23,27 +50,14 @@ export function QuestionGroupChart({
// Group responses by category (within this group only)
const responseGroups = d3.group(groupData, (d) => d.response);
const maxCount =
d3.max(Array.from(responseGroups.values(), (values) => values.length)) ||
0;
const maxRows = Math.ceil(maxCount / config.columnsPerGroup);
const chartHeight =
maxRows * (config.dotRadius * 2 + config.dotSpacing) +
config.margin.bottom;
const chartWidth =
xScale.range()[1] + config.margin.left + config.margin.right;
const chartHeight = 200;
const chartWidth = xScale.range()[1];
const svg = d3
.select(svgRef.current)
.attr("width", chartWidth)
.attr("height", chartHeight);
const g = svg
.append("g")
.attr(
"transform",
`translate(${config.margin.left},${config.margin.top})`
);
const g = svg.append("g");
// Dots
responses.forEach((response) => {
@@ -58,36 +72,25 @@ export function QuestionGroupChart({
(col - (config.columnsPerGroup - 1) / 2) *
(config.dotRadius * 2 + config.dotSpacing);
const dotY =
chartHeight -
config.margin.top -
config.margin.bottom -
(row + 1) * (config.dotRadius * 2 + config.dotSpacing);
chartHeight - (row + 1) * (config.dotRadius * 2 + config.dotSpacing);
g.append("circle")
.attr("class", "dot")
.attr("cx", dotX)
.attr("cy", dotY)
.attr("r", config.dotRadius)
.attr("fill", colorScheme[response] || "#666");
makeDot("rect", g, dotX, dotY).attr(
"fill",
colorScheme[response] || "#666"
);
});
});
}, [groupData, responses, xScale, question]);
/*
// Calculate height for container
const responseGroups = d3.group(groupData, (d) => d.response);
const maxCount =
d3.max(Array.from(responseGroups.values(), (values) => values.length)) || 0;
const maxRows = Math.ceil(maxCount / config.columnsPerGroup);
const chartHeight =
maxRows * (config.dotRadius * 2 + config.dotSpacing) +
config.margin.top +
config.margin.bottom;
*/
return (
<div className="question-group">
<div className="question-title">{question}</div>
<svg ref={svgRef}></svg>
<div className="question-title">{question}</div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo.
</p>
</div>
);
}