You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

D3.js热力图布局异常求助:单元格过小与标签显示问题

热力图开发问题求助(D3.js + React)

我正在使用D3.js开发热力图,目前遇到两个关键问题:

  • 当数据条目较多时,热力图的单元格会变得过小;尝试调大单元格尺寸时,又会因边距设置导致大量单元格被截断无法显示。
  • 我希望将X轴标签置于顶部,但边距设置总是导致X轴标签显示异常。

以下是相关代码、React容器代码、示例数据及数据转换函数,附问题截图说明:

D3热力图创建函数

function createHeatmap(data) {
        d3.select("#my_dataviz svg").remove();
        const margin = {top: 80, right: 25, bottom: 30, left: 300},
            width = 1000 - margin.left - margin.right,
            height = 600 - margin.top - margin.bottom;
    
        const svg = d3.select("#my_dataviz")
            .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", `translate(${margin.left}, ${margin.top})`);
    
        const xLabels = ["accessibility", "completeness", "consistency", "retrieval", "currency"];
    
        const x = d3.scaleBand()
            .range([0, width])
            .domain(xLabels)
            .padding(0.05);
    
        const y = d3.scaleBand()
            .range([ height, 0 ])
            .domain(data.map(d => d.group))
            .padding(0.05);
    
        svg.append("g")
            .style("font-size", 40)
            .attr("transform", `translate(0, -20)`)
            .call(d3.axisBottom(x).tickSize(0))
            .selectAll("text")
            .text(d => firstLetterUppercase(d))
            .style("cursor", "pointer")
            .classed("x-axis-label", true)
            .on("click", (_, d) => {
                toggleLabel(d);
            });
        
        svg.append("g")
            .style("font-size", 15)
            .call(d3.axisLeft(y).tickSize(0))
            .selectAll("text");
                
        svg.select(".domain") // Removes x axis border line
            .remove();
    
        svg.select(".domain") // Removes y axis border line
            .remove();
    
        // Add the squares
        svg.selectAll()
            .data(data, function(d) { return d.group; })
            .join("rect")
            .attr("x", function(d) { return x(d.variable); })
            .attr("y", function(d) { return y(d.group); })
            .attr("rx", 4)
            .attr("ry", 4)
            .attr("width", x.bandwidth())
            .attr("height", y.bandwidth())
            .style("fill", function(d) { return getColor(d.value, d.variable) })
            .style("stroke-width", 4)
            .style("stroke", "none")
            .style("opacity", 0.8)
            .each(function(d) {
                svg.append("text")
                .attr("x", x(d.variable) + x.bandwidth() / 2)
                .attr("y", y(d.group) + y.bandwidth() / 2)
                .attr("text-anchor", "middle")
                .attr("alignment-baseline", "middle")
                .style("font-size", "12px")
                .text(projectData(d.value, d.variable));
            });
    }

React容器代码

<div style={{
        width: '1000px',
        height: '600px',
        overflow: 'auto' 
    }}>
        {children}
    </div>
<Col span={18} style={{ overflow: 'auto' }}>
                    <PlotCard>
                        {!scatterPlot && !bubblePlot && 
                            <HeatMap 
                                data={plotFilteredData} 
                                sortKey={sortKey}
                                selectedLabels={selectedLabels}
                                setSelectedLabels={setSelectedLabels}
                            />
                        }
                    </PlotCard>
                </Col>

示例数据

// const originalData = [
    //     { file: 'File 1', completeness: 0.91, consistency: 0.99, accessibility: 5, retrieval: 5, currency: 1, lol: "test" },
    //     { file: 'File 2', completeness: 0.03, consistency: 0.13, accessibility: 3, retrieval: 4, currency: 0.2, fuck: "test" },
    //     { file: 'File 3', completeness: 1, consistency: 1, accessibility: 1, retrieval: 3, currency: 1 },
    //     { file: 'File 4', completeness: 0.99, consistency: 1, accessibility: 5, retrieval: 5, currency: 0.8 },
    //     { file: 'File 5', completeness: 0.33, consistency: 0.98, accessibility: 5, retrieval: 2, currency: 0.2 },
    //     { file: 'File 6', completeness: 0.04, consistency: 0, accessibility: 4, retrieval: 2, currency: 0.2 },
    //     { file: 'File 7', completeness: 0.05, consistency: 0.04, accessibility: 3, retrieval: 2, currency: 0.2 },
    //     { file: 'File 8', completeness: 0.8, consistency: 0.8, accessibility: 4, retrieval: 4, currency: 0.2 },
    //     { file: 'File 9', completeness: 0.77, consistency: 0.77, accessibility: 5, retrieval: 2, currency: 0.2 },
    //     { file: 'File 10', completeness: 0.56, consistency: 0.55, accessibility: 1, retrieval: 1, currency: 0.4 },
    //     { file: 'File 11', completeness: 0.94, consistency: 0.02, accessibility: 1, retrieval: 3, currency: 0 },
    //     { file: 'File 12', completeness: 0.44, consistency: 0.44, accessibility: 2, retrieval: 1, currency: 0.02 },
    // ];

数据转换函数

export const fixHeatmapData = (originalData, variable) => {
    
    let data = [];
    for (const pData of originalData){
        let originalKey = pData.file
        for (const key in pData) {
            if (key === 'file') continue;
        
            const newDataPoint = {
                group: originalKey,
                variable: key,
                value: pData[key]
            };
        
            data.push(newDataPoint);
        }
    }

    return data;
}

问题截图

热力图单元格过小示意图

内容的提问来源于stack exchange,提问作者Konstantinos Loukaidis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 21:52:01