我还在学习D3v7和创建热图的过程中,我会用更多的功能来扩展它.
现在,当窗口大小更改时,我在设置SVG元素的高度和宽度时遇到了问题.
通过论坛上的几篇帖子,我设法让我的SVG元素动态调整其高度和宽度.
.attr(
"viewBox",
`0 0 ${i_width + margin.right} ${i_height + margin.top + margin.bottom}`
)
但是现在我希望我的SVG元素有一个滚动条,当窗口太小时,SVG元素中的字体不再可读.我想要一个最小宽度到哪里的宽度是可变的,然后在它上面创建一个滚动条.
const data = [
{ group: "A", variable: "v1", value: 98 }, { group: "A", variable: "v2", value: 95 },
{ group: "A", variable: "v3", value: 22 }, { group: "A", variable: "v4", value: 14 },
{ group: "A", variable: "v5", value: 59 }, { group: "A", variable: "v6", value: 52 },
{ group: "A", variable: "v7", value: 88 }, { group: "A", variable: "v8", value: 20 },
{ group: "A", variable: "v9", value: 99 }, { group: "A", variable: "v10", value: 66 },
{ group: "B", variable: "v1", value: 37 }, { group: "B", variable: "v2", value: 50 },
{ group: "B", variable: "v3", value: 81 }, { group: "B", variable: "v4", value: 79 },
{ group: "B", variable: "v5", value: 84 }, { group: "B", variable: "v6", value: 91 },
{ group: "B", variable: "v7", value: 82 }, { group: "B", variable: "v8", value: 89 },
{ group: "B", variable: "v9", value: 6 }, { group: "B", variable: "v10", value: 67 },
{ group: "C", variable: "v1", value: 96 }, { group: "C", variable: "v2", value: 13 },
{ group: "C", variable: "v3", value: 98 }, { group: "C", variable: "v4", value: 10 },
{ group: "C", variable: "v5", value: 86 }, { group: "C", variable: "v6", value: 23 },
{ group: "C", variable: "v7", value: 74 }, { group: "C", variable: "v8", value: 47 },
{ group: "C", variable: "v9", value: 73 }, { group: "C", variable: "v10", value: 40 },
{ group: "D", variable: "v1", value: 75 }, { group: "D", variable: "v2", value: 18 },
{ group: "D", variable: "v3", value: 92 }, { group: "D", variable: "v4", value: 43 },
{ group: "D", variable: "v5", value: 16 }, { group: "D", variable: "v6", value: 27 },
{ group: "D", variable: "v7", value: 76 }, { group: "D", variable: "v8", value: 24 },
{ group: "D", variable: "v9", value: 1 }, { group: "D", variable: "v10", value: 87 },
{ group: "E", variable: "v1", value: 44 }, { group: "E", variable: "v2", value: 29 },
{ group: "E", variable: "v3", value: 58 }, { group: "E", variable: "v4", value: 55 },
{ group: "E", variable: "v5", value: 65 }, { group: "E", variable: "v6", value: 56 },
{ group: "E", variable: "v7", value: 9 }, { group: "E", variable: "v8", value: 78 },
{ group: "E", variable: "v9", value: 49 }, { group: "E", variable: "v10", value: 36 },
{ group: "F", variable: "v1", value: 35 }, { group: "F", variable: "v2", value: 80 },
{ group: "F", variable: "v3", value: 8 }, { group: "F", variable: "v4", value: 46 },
{ group: "F", variable: "v5", value: 48 }, { group: "F", variable: "v6", value: 102 }
];
// Setze Dimension und Größe
var parentDiv = document.getElementById("heatmap")
var i_width = parentDiv.clientWidth;
var i_height = 450;
//const margin = {top: 40, right: 60, bottom: 40, left: 50};
const margin = { top: 0, right: 50, bottom: 30, left: 100 };
const width = i_width - margin.left - margin.right;
const height = i_height - margin.top - margin.bottom;
const extent = d3.extent(data, d => d.value);
const max = d3.max(data, function (d) { return d.value })
// Holt mir die Unique Group und Variables von der Datenquelle für die X- und Y-Achse
// d[value] ist wenn value eine Variable ist
// d['value'] ist das gleiche wie d.value um den Key aus dem Array zu erhalten
const myGroups = data.map(function (d) { return d.group })
const myVars = data.map(function (d) { return d.variable })
// Anfügen von svg Elementen zu #heatmap
const svg = d3.select("#heatmap")
.append("svg") //Anfügen von svg an #heatmap
.attr("id", "hm_svg")
//.attr("width", width + margin.left + margin.right)
//.attr("height", height + margin.top + margin.bottom)
.attr("viewBox", `0 0 ${i_width + margin.right} ${i_height + margin.top + margin.bottom}`)
const g_area = d3.select("svg")
// Anfügen einer Gruppe an das SVG Element
.append("g") //Anfügen von g (Groups) an svg
.attr("id", "hm_area")
.attr("transform", `translate(${margin.left},${margin.top})`);
// Color Skalierung
const myColor = d3.scaleLinear()
.range(["#f9f9f9", "#6e69b3", /*"#69b3a2"*/])
.domain([extent[0], (Math.ceil(extent[1] / 50) * 50)])
// X-Skalierung
const x_scale = d3.scaleBand()
.range([0, width])
.domain(myGroups)
.padding(0.01);
// X-Achse erstellen
const xAxis = g_area
.append("g")
.attr("id", "hm_x_axis")
xAxis.append("g")
.attr("id", "hm_x_axis_value")
.attr("transform", `translate(0, ${height})`)
.style("color", "rgba(0, 0, 0, 0.65)")
.style("font-size", "16px")
.style("font-family", "arial")
.call(d3.axisBottom(x_scale));
// Einfügen xAxis Label
xAxis.append("text")
.attr("id", "hm_x_axis_label")
.attr("x", width / 2)
.attr("y", height + 40)
.style("fill", "rgba(0, 0, 0, 0.65)")
.style("font-size", "18px")
.style("font-family", "sans-serif")
.attr("text-anchor", "middle")
.text("Label X");
// Y-Skalierung
const y_scale = d3.scaleBand()
.range([height, 0])
.domain(myVars)
.padding(0.03);
// Y-Achse erstellen
const yAxis = g_area
.append("g")
.attr("id", "hm_y_axis")
yAxis.append("g")
.attr("id", "hm_y_axis_value")
.style("color", "rgba(0, 0, 0, 0.65)")
.style("font-size", "16px")
.style("font-family", "arial")
.call(d3.axisLeft(y_scale));
// Einfügen yAxis Label
yAxis.append("text")
.attr("id", "hm_y_axis_label")
.attr("y", - 35) //Y ist hierbei die horizontale ausrichtung
.attr("x", - height / 2) //X ist hierbei die vertikale ausrichtung
.attr("transform", "rotate(-90)")
.style("fill", "rgba(0, 0, 0, 0.65)")
.style("font-size", "18px")
.style("font-family", "sans-serif")
.attr("text-anchor", "middle")
.text("Label Y");
// ColorScale Legend
const GradColors = [myColor(Math.ceil(extent[1] / 50) * 50), myColor(extent[0])];
const g_colorScale = g_area
.append("g")
.attr("id", "colorLegend")
//console.log(Math.ceil(extent[1] / 100) * 100)
// Erstelle yColorscale
var yColorscale = d3.scaleLinear()
// Mit Math.ceil zum nächsten 100er Runden
.domain([0, Math.ceil(extent[1] / 50) * 50])
.range([height - 70, 0]);
// Add scales to axis
var y_axis_color = d3.axisRight(yColorscale)
.ticks(1);
//Append group and insert axis
g_colorScale.append("g")
.attr("transform", `translate(${width + 35},${(height / 2) - 150})`)
.call(y_axis_color);
//defs Element sind zum speichern von Opbjekten, die zu einem späteren zeitpunkt gebraucht werden
const g_def = g_colorScale.append("defs")
.append("linearGradient")
.attr("id", "grad")
.attr("x1", "0%")
.attr("x2", "0%")
.attr("y1", "0%")
.attr("y2", "100%");
g_def.selectAll("stop")
.data(GradColors)
.enter()
.append("stop")
.style("stop-color", function (d) { return d; })
.attr("offset", function (d, i) {
return 100 * (i / (GradColors.length - 1)) + "%";
})
g_colorScale.append("rect")
.attr("id", "hm_colorScale_legend")
.attr("x", width + 20)
.attr("y", (height / 2) - 150)
.attr("rx", "4px")
.attr("width", 15)
.attr("height", height - 70)
.attr("stroke", "black")
.attr("stroke-width", "0.5px")
.attr("text-anchor", "middle")
.style("fill", "url(#grad)");
// Erstellen eines Tooltip
const tooltip = d3.select("#heatmap")
.append("div")
.attr("id", "tooltip")
.style("position", "absolute")
.style("opacity", 0)
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
const mouseover = function (event, d) {
tooltip
.style("opacity", 1)
d3.select(this).select("#hm_node")
.style("stroke", "black")
.style("stroke-width", "2px")
};
const mousemove = function (event, d) {
tooltip
.text("Wert: " + d.value)
.style("left", (event.x) + 20 + "px")
.style("top", (event.y) - 10 + "px")
};
const mouseleave = function (d) {
tooltip.style("opacity", 0)
d3.select(this).select("#hm_node")
.style("stroke", "none")
};
// Erstellen von Rechtecken
// Wird erstellt um den node sowie sein Label in eine gruppe (g) zu packen
const g_nodes = g_area
.append("g")
.attr("id", "hm_nodes")
.selectAll("rect")
.data(data)
.enter()
//FÜr jeden Datensatz ein "g" Element erstellen
.append("g")
.attr("class", "hm_node_grp")
.attr("group", function (d) { return d.group })
.attr("variable", function (d) { return d.variable })
.attr("value", function (d) { return d.value })
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave)
.on("click", function (d, i) { console.log(i) });
const rect_node = g_nodes
.append("rect") //Anfügen von RECT-Elementen
.attr("x", function (d) { return x_scale(d.group) })
.attr("y", function (d) { return y_scale(d.variable) })
.attr("id", "hm_node")
// "Bandwidth" ist über die Methode "BandScale" verfügbar
.attr("width", x_scale.bandwidth())
.attr("height", y_scale.bandwidth())
.style("fill", function (d) { return myColor(d.value) })
// Einfügen der Labels zu den Rechtecken
const rect_label = g_nodes
.append("text")
.attr("class", "hm_label")
.attr("x", (d) => x_scale(d.group))
.attr("y", (d) => y_scale(d.variable))
.attr("dx", x_scale.bandwidth() / 2)
.attr("dy", y_scale.bandwidth() / 2)
.attr("text-anchor", "middle")
.attr("dominant-baseline", "central")
.style("font-size", "12px")
.style("font-family", "sans-serif")
.text((d) => d.value);
<!DOCTYPE html>
<html>
<!-- Code Vorschlage mit STRG+Leertaste aktivieren-->
<head>
<meta charset="utf-8" /> <!-- Welche Sonderzeichen verwendet werden können -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <!-- Wie sollte sich die Seite auf einem Handy verhalten -->
<title> 1.Grundgerüst </title> <!-- title als Tag -->
<style>
</style>
</head>
<body>
<div id="heatmap"></div>
<script src="https://d3js.org/d3.v7.js" charset="utf-8"></script>
</body> <!-- HTML schließender Tag-->
</html> <!-- HTML schließender Tag-->
有人能帮我这个忙吗?