我能够使用任何选定的字体和大小生成UIBezierPath
个字符。现在我想在bezier路径之间做一条蚀刻线。我可以获得bezier路径的中心点吗?或者我可以制作中心虚线并沿着那条路走的任何其他方式?
以下是我这样做的代码
Reference Link. I want something like this.:
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 568, 568) cornerRadius:0];
UIBezierPath *circlePath = [self createArcPath];
[path appendPath:circlePath];
[path setUsesEvenOddFillRule:YES];
shapeView = [CAShapeLayer layer];
shapeView.geometryFlipped = false;
shapeView.path = path.CGPath;
shapeView.fillRule = kCAFillRuleEvenOdd;
shapeView.fillColor = [UIColor grayColor].CGColor;
shapeView.opacity = 1.0;
shapeView.lineDashPattern = @[@2, @3];
[self.view.layer addSublayer:shapeView];
CGFloat dashes[] = {2, 3};
[path setLineDash:dashes count:2 phase:0];
- (UIBezierPath *)createArcPath
{
// Create path from text
// See: http://www.codeproject.com/KB/iPhone/Glyph.aspx
// License: The Code Project Open License (CPOL) 1.02 http://www.codeproject.com/info/cpol10.aspx
letters = CGPathCreateMutable();
CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica-Bold"),80, NULL);
NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
(__bridge id)font, kCTFontAttributeName,//د
nil];//ج
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"H"
attributes:attrs];
CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)attrString);
CFArrayRef runArray = CTLineGetGlyphRuns(line);
// for each RUN
for (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runArray); runIndex++)
{
// Get FONT for this run
CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runArray, runIndex);
CTFontRef runFont = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName);
// for each GLYPH in run
for (CFIndex runGlyphIndex = 0; runGlyphIndex < CTRunGetGlyphCount(run); runGlyphIndex++)
{
// get Glyph & Glyph-data
CFRange thisGlyphRange = CFRangeMake(runGlyphIndex, 1);
CGGlyph glyph;
CGPoint position;
CTRunGetGlyphs(run, thisGlyphRange, &glyph);
CTRunGetPositions(run, thisGlyphRange, &position);
// Get PATH of outline
{
CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyph, NULL);
CGAffineTransform t = CGAffineTransformMakeTranslation(position.x+200, position.y+80);
CGPathAddPath(letters, &t, letter);
CGPathRelease(letter);
}
}
}
CFRelease(line);
self.path = [UIBezierPath bezierPath];
[self.path appendPath:[UIBezierPath bezierPathWithCGPath:letters]];
return self.path;
}
答案 0 :(得分:3)
我可以获得bezier路径的中心点吗?或任何其他方式 我可以制作中心虚线并沿着那条路走?
要知道用户的手指是否沿着路径行进,您必须路径上的点击检测。
确定是否在a的填充部分上发生了触摸事件 路径,您可以使用UIBezierPath的containsPoint:方法。这个 method针对所有关闭的子路径测试指定的点 如果路径对象位于其中任何一个上面或内部,则返回YES 子路径。
如果你想对路径的描边部分进行命中测试 (而不是填充区域),您必须使用核心图形。该 CGContextPathContainsPoint函数允许您测试任何一个点 填充或描边当前分配给图形的路径部分 上下文。
下面的方法测试以查看指定的点是否与指定的路径相交。 inFill参数允许调用者指定是否应针对路径的填充或描边部分测试该点。调用者传入的路径必须包含一个或多个已关闭的子路径,以使命中检测成功。
针对路径对象测试点。
- (BOOL)containsPoint:(CGPoint)point onPath:(UIBezierPath *)path inFillArea:(BOOL)inFill
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGPathRef cgPath = path.CGPath;
BOOL isHit = NO;
// Determine the drawing mode to use. Default to
// detecting hits on the stroked portion of the path.
CGPathDrawingMode mode = kCGPathStroke;
if (inFill)
{
// Look for hits in the fill area of the path instead.
if (path.usesEvenOddFillRule)
mode = kCGPathEOFill;
else
mode = kCGPathFill;
}
// Save the graphics state so that the path can be removed later.
CGContextSaveGState(context);
CGContextAddPath(context, cgPath);
// Do the hit detection.
isHit = CGContextPathContainsPoint(context, point, mode);
CGContextRestoreGState(context);
return isHit;
}
点击此链接了解有关Hit-Detection on a Path
的更多信息获取路径中心
您可以将路径的宽度设为myPath.bounds.size.width;
,并获取路径的中心,将宽度除以2。
要绘制虚线,请检查此answer
在任何UIBezierPath
上将虚线设为:
CGFloat dashes[] = {2, 3};
//passing an array with the values {2,3} sets a dash pattern that alternates between a 2 space-unit-long painted segment and a 3 space-unit-long unpainted segment.
UIBezierPath *path = [UIBezierPath bezierPath];
[path setLineDash:dashes count:2 phase:0];
并点击CAShapeLayer
使用属性lineDashPattern
作为:
shapeView.lineDashPattern = @[@2, @3];
答案 1 :(得分:2)
虽然贝塞尔路径是简单绘图的便利选择,但它们是复杂的计算,因此将它们用于此目的将非常昂贵且复杂。那是因为你需要能够计算沿路径的任意点并知道先前的点以便知道当前的方向。
您需要对字符进行其他描述,以便您更轻松地了解这些详细信息。这意味着使用字体的简单向量(或笔划)描述(如评论中的rob mayoff所述)。该描述将字符分解为许多易于使用的直线段。它们都受y=mx+c
计算的控制,你总是知道每个线段上有2个点,因此很容易在它们之间进行插值并知道移动的方向。
如果rob(here)提供的链接上的描述对于您想要显示字符的大小而言不够“准确”,则可以创建具有更多点的新版本以实现更接近贝塞尔曲线选项。
现在,通过这个描述你有很多选择......
对于沿着路径拖动手指,您可以在点之间进行插值,以找到当前触摸点的路径上的最近点,并确定触摸点何时偏离路径太远或已经与路径相交。此交叉处理也是您确定覆盖百分比的方法。您只需要选择插值间隙距离(选择合适的分辨率而不创建太多非常靠近的点)以及距离“下一个”路径点的触摸点的容差。
这也允许您链接的视频中的其他内容,例如沿(插值)路径的每个点放下图像并为这些图像设置动画。
答案 2 :(得分:2)
您可以使用此开源代码库中的代码计算UIBezierPath
的点数:
https://github.com/ImJCabus/UIBezierPath-Length
如果你有&#39; a&#39;如果字符表示为bezier路径,则可以通过编写如下内容来计算上图中的红点:
UIBezierPath *path = /* ... */;
NSUInteger subdivisions = 100;//however precise you want to be
for(NSUInteger i = 0; i < subdivisions; i++) {
CGFloat percent = (CGFloat)i/subdivisions;
CGPoint point = [path pointAtPercentOfLength:percent];
//draw a dot at this point, or trace it, or whatever you want to do
}
答案 3 :(得分:0)
尝试使用此代码绘制红点线:
CAShapeLayer* dotLayer = [CAShapeLayer layer];
dotLayer.path = path.CGPath;
dotLayer.strokeColor = [UIColor redColor].CGColor;
dotLayer.lineWidth = 2;//or the diameter of the dots
dotLayer.lineDashPattern = @[@0, @10];//change 10 to the distance between dots
dotLayer.lineJoin = kCALineJoinRound;
dotLayer.lineCap = kCALineCapRound;
答案 4 :(得分:0)
你想要的是相当复杂的,但我相信它可以通过以下步骤来实现:
1)使用您的方法
获取字母轮廓路径 2)使用CGPathCreateCopyByStrokingPath
创建一个新路径,lineWidth
等于1
3)get all segments of the new path
4)find all intersection points of all segments
5)确定哪些相交线相邻并使用它们的交叉点形成中心线
6)重复步骤2-6,增加步骤2中的lineWidth
值