如何使用d3.js的area()方法正确绘制正方形?
问题解答
- 用d3.js的
area区域生成器完全可以画出正方形,原有代码出不来预期效果,是三个地方存在错误。
原代码的错误点
- 数据点顺序混乱:
d3.area是严格按照数组顺序连点生成路径的,原有数据点顺序为(0,0) → (5,0) → (0,5) → (5,5),连起来本身就是交叉折线,无法围成闭合正方形。 - 生成器配置逻辑偏差:代码中把
y0固定为yScale(0),等于区域下边界永远贴在y=0的水平线上,只有上边界跟随数据变化,这种配置是为常规沿x轴展开的面积图设计的,无法围出方形轮廓。 - 比例尺存在拉伸变形:x比例尺0-6的数值范围对应150像素长度,y比例尺0-20的数值范围才对应150像素长度,x、y方向相同数值差对应的像素长度不一致,即便路径正确,画出来的也是拉长的矩形,不是正正方形。
正确实现代码
area生成器的工作逻辑很简单:按数组顺序连接所有(x, y1)点作为上轮廓,再倒序连接所有(x, y0)点作为下轮廓,最后自动把两段轮廓的首尾连起来,形成闭合区域。只要把上下轮廓的点设置成正方形的对应边,就能直接生成正方形:
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <svg id="demo1" width="200" height="200"></svg> <script> // 两个点分别对应正方形左右两条边的位置 var data = [ {x: 0, yTop: 5, yBottom: 0}, {x: 5, yTop: 5, yBottom: 0} ]; // 修正比例尺,x、y单位数值对应相同像素长度,避免图形拉伸 var xScale = d3.scaleLinear().domain([0, 6]).range([25, 175]); var yScale = d3.scaleLinear().domain([0, 6]).range([175, 25]); var area = d3.area() .x(d => xScale(d.x)) .y0(d => yScale(d.yBottom)) // 下轮廓连接(0,0)→(5,0),对应正方形下边 .y1(d => yScale(d.yTop)); // 上轮廓连接(0,5)→(5,5),对应正方形上边 // 生成器会自动补全左右两条边:(5,5)连(5,0)、(0,0)连(0,5),刚好围成闭合正方形 d3.select("#demo1") .append("path") .attr("d", area(data)) .attr("fill", "red") .attr("stroke", "black"); </script>
运行后就会在画布中间得到一个带黑色描边的红色正方形。如果要画任意角度、任意位置的正方形,只要对应调整x0/x1、y0/y1的取值,匹配正方形的轮廓点即可——area本质就是闭合路径生成工具,只要点的坐标和顺序正确,任何闭合多边形都能绘制,正方形当然也可以实现。
内容的提问来源于stack exchange,提问作者senior_script
相关产品推荐
相关产品推荐

