使用System.Drawing2D LinearGradientBrush填充椭圆出现异常结果
问题分析与修复方案
你的核心问题出在椭圆边缘点的计算逻辑,以及对LinearGradientBrush渐变范围的匹配上,以下是具体问题和修复步骤:
1. 椭圆边缘点计算错误
你当前用单位向量u直接乘以ovalRect.Width/2来计算边缘偏移量,这只适用于正圆(宽高相等的情况)。如果是椭圆,X轴和Y轴的半径分别是ovalRect.Width/2和ovalRect.Height/2,需要分别对单位向量的X、Y分量进行缩放,才能得到真正的椭圆边缘点:
修正后的边缘点计算代码:
Vector3 u = FBody.Unit(ovalCenter); // 分别按椭圆X/Y轴半径计算边缘偏移 Vector3 fromBodyCenterToEdge = new Vector3( u.X * ovalRect.Width / 2.0f, u.Y * ovalRect.Height / 2.0f, u.Z // 2D渲染可忽略Z分量 ); Vector3 darkSidePoint = ovalCenter + fromBodyCenterToEdge; Vector3 sunSidePoint = ovalCenter - fromBodyCenterToEdge;
2. 确保渐变与椭圆边界匹配
LinearGradientBrush的渐变范围是从darkSide到sunSide的直线,但填充椭圆时,渐变会覆盖整个ovalRect区域。可以添加一行代码禁用渐变平铺,避免边缘出现重复渐变的异常效果:
bl.WrapMode = WrapMode.Clamp;
3. 验证坐标投影正确性
确认ovalCenter的3D向量转2D平面时,Z轴的投影逻辑正确(比如是否用了透视投影或正交投影),如果Z分量处理不当,会导致darkSidePoint和sunSidePoint的2D坐标偏移,进而影响渐变方向。
修复后的完整代码片段
Vector3 u = FBody.Unit(ovalCenter); Vector3 fromBodyCenterToEdge = new Vector3( u.X * ovalRect.Width / 2.0f, u.Y * ovalRect.Height / 2.0f, u.Z ); Vector3 darkSidePoint = ovalCenter + fromBodyCenterToEdge; Vector3 sunSidePoint = ovalCenter - fromBodyCenterToEdge; PointF darkSide = new PointF(darkSidePoint.X, darkSidePoint.Y); PointF sunSide = new PointF(sunSidePoint.X, sunSidePoint.Y); Color darkSideColor = Color.Black; Color sunSideColor = penBody.Color; LinearGradientBrush bl = new LinearGradientBrush(darkSide, sunSide, darkSideColor, sunSideColor); bl.WrapMode = WrapMode.Clamp; // 禁用平铺,避免多余渐变 g.FillEllipse(bl, ovalRect);
内容的提问来源于stack exchange,提问作者DMP
相关产品推荐
相关产品推荐

