D3使用path绘制正弦曲线fill填充出现异常倾斜结果问题咨询
问题原因
这个异常倾斜的填充效果既不是数值精度问题,也不是D3的fill实现存在故障,核心问题是你使用d3.line生成填充路径的逻辑不符合SVG填充规则:
- SVG的
fill属性会自动将路径的起点和终点连接,形成闭合区域后再填充 - 你当前的实现中,正/负半周的路径都是由「曲线点+零点」交替拼接而成:当正弦值从正转负时,路径会直接从最后一个正半周的曲线点
(x1, sin(x1))连接到下一个零点(x2, 0);当正弦值从负转正时,路径又会直接从前一个零点(x3, 0)跳连到下一个正半周的曲线点(x4, sin(x4)),这些跨状态的斜向连线就是你看到的异常填充边界。 - 采样点越多效果越好的原因也很简单:采样密度越高,相邻两个点的x坐标差越小,斜向连线的斜率就越接近垂直,视觉上的异常感就越弱,但本质问题并没有被解决。
修复方案
推荐使用d3.area而非d3.line生成填充路径,它天生支持指定上下边界生成闭合填充区域,不需要你手动拆分零点和曲线点:
// 先生成原始的所有采样点数组,不需要提前拆分xy_values和xy_values2 let all_values = []; let len = 99; let dt = 8*Math.PI/len; for (var i =0; i<len; i++){ let valx = i*dt; let valy = Math.sin(valx); all_values.push( {key: valx, value: valy} ); } // 正半周填充(绿色) svg.append("path") .datum(all_values) .attr("fill", "#BFB") .attr("d", d3.area() .x(d => walkX(d.key)) .y0(walkY(0)) // 下边界固定为y=0的坐标 .y1(d => walkY(Math.max(d.value, 0))) // 上边界取sin值和0的最大值,负半周自动贴0轴 ); // 负半周填充(红色) svg.append("path") .datum(all_values) .attr("fill", "#FBB") .attr("d", d3.area() .x(d => walkX(d.key)) .y0(walkY(0)) // 上边界固定为y=0的坐标 .y1(d => walkY(Math.min(d.value, 0))) // 下边界取sin值和0的最小值,正半周自动贴0轴 );
按这个方案修改后,不管采样点多少,都不会出现斜向的异常填充。
内容的提问来源于stack exchange,提问作者vyi
相关产品推荐
相关产品推荐

