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

如何解决d3-contour绘制中图表与坐标轴重叠的问题?

问题分析与解决方案

你的contour图表和坐标轴重叠,核心问题出在contour的投影未适配容器高度,且坐标系统与SVG的y轴方向不匹配,导致contour元素没有正确填充到预留的绘图区域内,进而和坐标轴重叠。以下是具体修改方案:

关键修改点

  1. 修正contour的投影逻辑:
    原代码只对contour做了宽度缩放,未处理高度缩放,且没有适配SVG的y轴方向(SVG y轴向下,而你的y轴向上)。需要同时缩放x/y方向,并翻转y轴坐标。
  2. 修复SVG属性大小写问题:SVG属性区分大小写,原代码中attr("Stroke", "black")应改为小写的stroke。
  3. 简化y轴定义域:d3.extent([1, m])等价于直接写[1, m],无需调用extent。

修改后的完整代码

function daysChart() {
    const data = {width:87, height:61, values:[102, 103, ...]}

    const margin = { top: 20, right: 20, bottom: 40, left: 50 };
    const fullWidth = 960;
    const fullHeight = 500;
    const contourWidth = fullWidth - margin.left - margin.right;
    const contourHeight = fullHeight - margin.top - margin.bottom;

    const n = data.width;
    const m = data.height;
    // 分别计算x/y方向的缩放比例
    const xScale = contourWidth / n;
    const yScale = contourHeight / m;
    // 调整投影:适配宽高缩放,翻转y轴并对齐坐标原点
    const path = d3.geoPath().projection(
        d3.geoIdentity()
            .scale(xScale)
            .translate([0, contourHeight])
            .scaleY(-yScale)
    );
    const contours = d3.contours().size([n, m]);
    const color = d3.scaleSequential(d3.interpolateTurbo).domain(d3.extent(data.values)).nice();
    
    const startDateStr = "2023-08-13";
    const dates = generateDateArray(startDateStr, n); 
    const x = d3.scaleTime()
        .domain(d3.extent(dates))
        .range([0, contourWidth]);

    const y = d3.scaleLinear()
        .domain([1, m]) // 简化定义域写法
        .range([contourHeight, 0]);

    // full plot
    const svg = d3.select("#smps-chart")
        .attr("style", "display: flex; justify-content: center; align-items: center;")
        .append("svg")
        .attr("width", fullWidth)
        .attr("height", fullHeight)
        .append("g")
        .attr("transform", `translate(${margin.left}, ${margin.top})`);

    // contour
    svg.append("g")
        .attr("stroke", "black") // 修正属性大小写
        .selectAll()
        .data(color.ticks(20))
        .join("path")
        .attr("d", d => path(contours.contour(data.values, d)))
        .attr("fill", color);

    // x axis
    svg.append("g")
        .attr("transform", `translate(0, ${contourHeight})`)
        .call(d3.axisBottom(x));

    // y axis
    svg.append("g")
        .call(d3.axisLeft(y));
}

为什么之前调整margin无效?

你之前调整margin或尺寸时,只是改变了容器的预留空间,但contour本身的坐标系统没有和容器的绘图区域(contourWidth/contourHeight)对齐,导致contour元素要么超出区域被截断,要么和坐标轴重叠。修改投影后,contour会完全填充到margin预留出的绘图区域内,自然不会和坐标轴重叠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 15:03:20