我正在尝试创建一个在自定义 UIView
子类中绘制多边形的类。我已经可以正常工作了,但现在我想通过将角圆化来平滑角,但我不知道该怎么做。这是我到目前为止所拥有的:
public class MyView : UIView
{
private List<CGPoint> points;
public MyView(CGRect frame, List<CGPoint> points) : base (frame)
{
this.points = points;
}
public override Draw (CGRect rect)
{
CGContext context = UIGraphics.GetCurrentContext();
context.SetLineWidth(2);
UIColor.Black.SetStroke();
UIColor.Green.SetFill();
CGPath path = new CGPath();
path.AddLines(points.ToArray());
path.CloseSubpath();
context.AddPath(path);
context.Clip();
using (CGColorSpace rgb = CGColorSpace.CreateDeviceRGB())
{
CGGradient gradient = new CGGradient (rgb, new CGColor[]
{
new CGColor(0, 1, 0),
new CGColor(0, 0.5f, 0),
new CGColor(0, 1, 0),
new CGColor(0, 0.5f, 0)
});
context.DrawLinearGradient(gradient,
new CGPoint (path.BoundingBox.Left, path.BoundingBox.Top),
new CGPoint (path.BoundingBox.Right, path.BoundingBox.Bottom),
CGGradientDrawingOptions.DrawsBeforeStartLocation);
}
}
}
根据我提出的观点,我得到了:
我尝试过使用 path.AddCurveToPoint
和 path.AddArc
但我似乎无法让它们按照我想要的方式工作。任何帮助将不胜感激。
编辑
我尝试了 path.AddCurveToPoint
,现在它看起来像这样:
一开始是正确的,但后来就完全疯了。不确定我在这里做错了什么。这是我更新的 Draw
覆盖:
public override Draw (CGRect rect)
{
CGContext context = UIGraphics.GetCurrentContext();
context.SetLineWidth(2);
UIColor.Black.SetStroke();
UIColor.Green.SetFill();
CGPath path = new CGPath();
path.AddLines(points.ToArray());
path.CloseSubpath();
// updated section
int count = points.Count;
for (int x = 1; x < count; x++)
{
var p = points[x];
if (x != 0)
{
var prev = points[x - 1];
if (prev.Y != p.Y)
{
if (prev.Y > p.Y)
{
path.AddCurveToPoint(prev, new CGPoint(p.X - prev.X, p.Y), p);
}
else
{
//???
}
}
}
}
// end updated section
context.AddPath(path);
context.Clip();
using (CGColorSpace rgb = CGColorSpace.CreateDeviceRGB())
{
CGGradient gradient = new CGGradient (rgb, new CGColor[]
{
new CGColor(0, 1, 0),
new CGColor(0, 0.5f, 0),
new CGColor(0, 1, 0),
new CGColor(0, 0.5f, 0)
});
context.DrawLinearGradient(gradient,
new CGPoint (path.BoundingBox.Left, path.BoundingBox.Top),
new CGPoint (path.BoundingBox.Right, path.BoundingBox.Bottom),
CGGradientDrawingOptions.DrawsBeforeStartLocation);
}
}
最佳答案
更新:
根据您的更新,我现在看到了您的问题。您尝试使用点列表作为贝塞尔曲线控制点和多边形角的绘制点,但这是行不通的。
“最简单”方式是使用现有的点列表作为控制点,并在每个控制点之间创建中途结,并向每个线段添加四边形曲线。
注意:更难的方法是使用点列表作为结,并为每个贝塞尔曲线段创建控制点。我不会在这里讨论它,但许多图表系统都使用这个 article作为它们的引用,getControlPoints
的返回值将用作 AddCurveToPoint
方法的控制点。
简单的方法示例:
var color = UIColor.Red;
var color2 = UIColor.White;
var points = new List<CGPoint>() {
new CGPoint(136.49f, 134.6f),
new CGPoint(197.04f, 20.0f),
new CGPoint(257.59f, 20.0f),
new CGPoint(303.0f, 134.6f),
new CGPoint(303.0f, 252.0f),
new CGPoint(28.0f, 252.0f),
new CGPoint(28.0f, 134.6f),
new CGPoint(136.49f, 134.6f)
};
UIBezierPath polygonPath = new UIBezierPath();
polygonPath.MoveTo(points[0]);
polygonPath.AddLineTo(points[1]);
polygonPath.AddLineTo(points[2]);
polygonPath.AddLineTo(points[3]);
polygonPath.AddLineTo(points[4]);
polygonPath.AddLineTo(points[5]);
polygonPath.AddLineTo(points[6]);
polygonPath.ClosePath();
polygonPath.Fill();
color2.SetStroke();
polygonPath.LineWidth = 10.0f;
polygonPath.Stroke();
UIBezierPath smoothedPath = new UIBezierPath();
var m0 = MidPoint(points[0], points[1]);
smoothedPath.MoveTo(m0);
smoothedPath.AddQuadCurveToPoint(m0, points[0]);
var m1 = MidPoint(points[1], points[2]);
smoothedPath.AddQuadCurveToPoint(m1, points[1]);
var m2 = MidPoint(points[2], points[3]);
smoothedPath.AddQuadCurveToPoint(m2, points[2]);
var m3 = MidPoint(points[3], points[4]);
smoothedPath.AddQuadCurveToPoint(m3, points[3]);
var m4 = MidPoint(points[4], points[5]);
smoothedPath.AddQuadCurveToPoint(m4, points[4]);
var m5 = MidPoint(points[5], points[6]);
smoothedPath.AddQuadCurveToPoint(m5, points[5]);
var m6 = MidPoint(points[6], points[0]);
smoothedPath.AddQuadCurveToPoint(m6, points[6]);
smoothedPath.AddQuadCurveToPoint(m0, points[0]);
smoothedPath.ClosePath();
color.SetStroke();
smoothedPath.LineWidth = 5.0f;
smoothedPath.Stroke();
原文:
1) 我不确定您正在寻找多少联合平滑,但是 CGLineJoin.Round
对于 上的
将创建微妙的外观。LineJoinStyle
UIBezierPath
2) 如果需要重度拐角平滑,可以手动计算每条线的起点/终点,并添加 ArcWithCenter 来连接每条线段。
3) 或者,无需手动角弧计算,您可以在使用 CGLineJoin.Round 时设置非常粗的线宽,并将绘图尺寸稍微缩小以弥补增加的线宽。
示例:
var color = UIColor.FromRGBA(0.129f, 0.467f, 0.874f, 1.000f);
UIBezierPath polygonPath = new UIBezierPath();
polygonPath.MoveTo(new CGPoint(136.49f, 134.6f));
polygonPath.AddLineTo(new CGPoint(197.04f, 20.0f));
polygonPath.AddLineTo(new CGPoint(257.59f, 20.0f));
polygonPath.AddLineTo(new CGPoint(303.0f, 134.6f));
polygonPath.AddLineTo(new CGPoint(303.0f, 252.0f));
polygonPath.AddLineTo(new CGPoint(28.0f, 252.0f));
polygonPath.AddLineTo(new CGPoint(28.0f, 134.6f));
polygonPath.AddLineTo(new CGPoint(136.49f, 134.6f));
polygonPath.ClosePath();
polygonPath.LineJoinStyle = CGLineJoin.Round;
color.SetFill();
polygonPath.Fill();
color.SetStroke();
polygonPath.LineWidth = 30.0f;
polygonPath.Stroke();
:中点法
protected CGPoint MidPoint(CGPoint first, CGPoint second)
{
var x = (first.X + second.X) / 2;
var y = (first.Y + second.Y) / 2;
return new CGPoint(x: x, y: y);
}
关于c# - Xamarin iOS CGPath 绘制带有弯角/圆角的多边形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37753737/