在 xamarin ios 中沿圆形路径绘制文本
Posted
技术标签:
【中文标题】在 xamarin ios 中沿圆形路径绘制文本【英文标题】:Draw text along circular path in xamarin ios 【发布时间】:2017-10-17 14:03:51 【问题描述】:我在以下链接中找到了答案: Draw text along circular path in Swift for ios
这对我来说似乎很好。现在,我只是想在 xamarin ios 中转换相同的代码,但还没有成功。
public class CircularText : UIView
public override void Draw(CoreGraphics.CGRect rect)
base.Draw(rect);
this.BackgroundColor = UIColor.Clear;
var context = UIGraphics.GetCurrentContext();
var size = this.Bounds.Size;
context.TranslateCTM(size.Width / 2, size.Height / 2);
context.ScaleCTM(1, -1);
CentreArcPerpendicular(str: "Hello round world", context: context, radius: 100, angle: 0, color: UIColor.Red, font: UIFont.SystemFontOfSize(16), clockwise: true);
CentreArcPerpendicular(str: "Anticlockwise", context: context, radius: 100, angle: (System.nfloat)(-Math.PI / 2), color: UIColor.Red, font: UIFont.SystemFontOfSize(16), clockwise: false);
centre(str: "Hello flat world", context: context, radius: 0, angle: 0, color: UIColor.Yellow, font: UIFont.SystemFontOfSize(16), slantAngle: (System.nfloat)(Math.PI / 4));
void CentreArcPerpendicular(String str, CGContext context, nfloat radius, nfloat angle, UIColor color, UIFont font, bool clockwise)
var l = str.Length;
char[] characters = str.ToCharArray();
nfloat[] arcs = new nfloat[l];
nfloat totalArc = 0;
for (int i = 0; i < l; i++)
arcs[i] = chordToArc(1, radius);
var direction = clockwise ? -1 : 1;
var slantCorrection = clockwise ? -Math.PI / 2 : Math.PI;
var thetaI = angle - direction * totalArc / 2;
for (int i = 0; i < l; i++)
thetaI += direction * arcs[i] / 2;
centre(str: characters[i].ToString(), context: context, radius: radius, angle: angle, color: color, font: font, slantAngle: (System.nfloat)(angle + slantCorrection));
thetaI += direction * arcs[i] / 2;
nfloat chordToArc(nfloat chord, nfloat radius)
return (nfloat)(2 * Math.Asin(chord / (2 * radius)));
void centre(String str, CGContext context, nfloat radius, nfloat angle, UIColor color, UIFont font, nfloat slantAngle)
//var attributes = [NSForegroundColorAttributeName: color,
//NSFontAttributeName: font]
context.SaveState();
// // Undo the inversion of the Y-axis (or the text goes backwards!)
context.ScaleCTM(1, -1);
// Move the origin to the centre of the text (negating the y-axis manually)
context.TranslateCTM((System.nfloat)(radius * Math.Cos(angle)), (System.nfloat)(-(radius * Math.Sin(angle))));
// Rotate the coordinate system
context.RotateCTM(-slantAngle);
// Calculate the width of the text
var offset = str.Length;
// Move the origin by half the size of the text
//CGContextTranslateCTM(context, -offset.width / 2, -offset.height / 2)
context.TranslateCTM(-20 / 2, 20 / 2); // Move the origin to the centre of the text (negating the y-axis manually)
// Draw the text
str.DrawString(new CGPoint(x: 0, y: 0), font);
// Restore the context
context.RestoreState();
一些 cmets 显示原始行,它可能没有正确翻译...它对我来说只显示黑色视图
【问题讨论】:
【参考方案1】:将swift代码转换为C#时有几个错误,我在下面的代码sn-p中更正了它们。它是黑色的原因是您没有为文本设置颜色。您可以改用NSString.DrawString
来实现。
应该是这样的:
public override void Draw(CoreGraphics.CGRect rect)
base.Draw(rect);
this.BackgroundColor = UIColor.Clear;
var context = UIGraphics.GetCurrentContext();
var size = this.Bounds.Size;
context.TranslateCTM(size.Width / 2, size.Height / 2);
context.ScaleCTM(1, -1);
CentreArcPerpendicular(str: "Hello round world", context: context, radius: 100, angle: 0, color: UIColor.Red, font: UIFont.SystemFontOfSize(16), clockwise: true);
CentreArcPerpendicular(str: "Anticlockwise", context: context, radius: 100, angle: (System.nfloat)(-Math.PI / 2), color: UIColor.Red, font: UIFont.SystemFontOfSize(16), clockwise: false);
centre(str: "Hello flat world", context: context, radius: 0, angle: 0, color: UIColor.Yellow, font: UIFont.SystemFontOfSize(16), slantAngle: (System.nfloat)(Math.PI / 4));
void CentreArcPerpendicular(String str, CGContext context, nfloat radius, nfloat angle, UIColor color, UIFont font, bool clockwise)
var l = str.Length;
char[] characters = str.ToCharArray();
nfloat[] arcs = new nfloat[l];
nfloat totalArc = 0;
for (int i = 0; i < l; i++)
//Get the Size of the Char(Transfer to string to get the width)
NSString s = new NSString(Char.ToString(characters[i]));
CGSize size = s.GetSizeUsingAttributes(new UIStringAttributes(new NSDictionary(UIStringAttributeKey.Font, font)));
arcs[i] = chordToArc(size.Width, radius);
totalArc += arcs[i];
var direction = clockwise ? -1 : 1;
var slantCorrection = clockwise ? -Math.PI / 2 : Math.PI / 2 ; //You lose the /2
var thetaI = angle - direction * totalArc / 2;
for (int i = 0; i < l; i++)
thetaI += direction * arcs[i] / 2;
centre(str: characters[i].ToString(), context: context, radius: radius, angle: thetaI, color: color, font: font, slantAngle: (System.nfloat)(thetaI + slantCorrection)); // USe thetaI not angle !
thetaI += direction * arcs[i] / 2;
nfloat chordToArc(nfloat chord, nfloat radius)
return (nfloat)(2 * Math.Asin(chord / (2 * radius)));
void centre(String str, CGContext context, nfloat radius, nfloat angle, UIColor color, UIFont font, nfloat slantAngle)
// Set the text attributes
UIStringAttributes attribute = new UIStringAttributes()
Font = font,
ForegroundColor = color
;
NSString s = new NSString(str);
// Save the context
context.SaveState();
// Undo the inversion of the Y-axis (or the text goes backwards!)
context.ScaleCTM(1, -1);
// Move the origin to the centre of the text (negating the y-axis manually)
context.TranslateCTM((System.nfloat)(radius * Math.Cos(angle)), (System.nfloat)(-(radius * Math.Sin(angle))));
// Rotate the coordinate system
context.RotateCTM(-slantAngle);
// Calculate the width of the text
var offset = s.GetSizeUsingAttributes(attribute);
// Move the origin by half the size of the text
context.TranslateCTM(-offset.Width / 2, -offset.Height / 2); // Move the origin to the centre of the text (negating the y-axis manually)
// Draw the text
s.DrawString(new CGPoint(0, 0), attribute);//use NSString.DrawString, then it can add attribute parameter.
// Restore the context
context.RestoreState();
它可以像这样正常工作:
【讨论】:
以上是关于在 xamarin ios 中沿圆形路径绘制文本的主要内容,如果未能解决你的问题,请参考以下文章