如何解决d3-contour绘制中图表与坐标轴重叠的问题?
问题分析与解决方案
你的contour图表和坐标轴重叠,核心问题出在contour的投影未适配容器高度,且坐标系统与SVG的y轴方向不匹配,导致contour元素没有正确填充到预留的绘图区域内,进而和坐标轴重叠。以下是具体修改方案:
关键修改点
- 修正contour的投影逻辑:
原代码只对contour做了宽度缩放,未处理高度缩放,且没有适配SVG的y轴方向(SVG y轴向下,而你的y轴向上)。需要同时缩放x/y方向,并翻转y轴坐标。 - 修复SVG属性大小写问题:SVG属性区分大小写,原代码中
attr("Stroke", "black")应改为小写的stroke。 - 简化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
相关产品推荐
相关产品推荐

