在曲线上绘制文本的最高效方法,并对其进行animation处理?

我猜测是从单独的CATextLayers中创build一个string,然后根据需要将它们定位在曲线上,然后进行animation处理。 因为这就是我现在正在做的事情,但是它失去了克宁。 就是这样:

为什么我的曲线文本本身不对?

但核心文本是否更高性能,能够避免整个“拉近上下文”的废话,与精益,平均的核心animation处事方式相比,减less了一切下降,并尊重字距? 即避免drawRect:以及所有其他方面,大大放慢速度,就像在屏幕上绘制的方式一样:

https://github.com/darcyliu/CocoaSampleCode/tree/master/CoreTextArcCocoa

设想一串200个字符,绕着一个圆圈弯曲,能够为字符之间的间距设置animation,希望能达到稳定的60fps。 核心animation可以实现这个function,但这是通过将string分成单独的字符并以相同的间距放置在圆周上,导致字距信息完全丢失。

我希望能够做到这一点,而不会失去字距信息,仍然可以dynamic调整60fps的间距。

当然,你可以做到这一点。 不过,使用iOS 7,您不需要一直到核心文本。 NSLayoutManager可以在很多情况下处理它。 查看我为iOS编写的CurvyText演示:PTL 。 您可以拖动所有控制点,并沿曲线查看文本布局。

要查看这种布局在纯文本和核心animation中的速度有多快,请参阅Rich Text核心文本中的PinchText演示。 这一个显示如何调整核心文本布局,以响应多点触摸,所以文字似乎弯曲你的手指。 它包括如何使用Core Animation进行animation处理以获得平滑调整(甚至在移除手指时出现小的“飞溅”效果)的示例。

我不太清楚你的意思是什么“整个图画变成一个无关紧要的东西,会减慢一切。” 我非常快速地将它们绘制到上下文中(Core Animation也对上下文进行了大量绘制)。

围绕圆圈弯曲文本比这些演示中的任何一个都容易。 诀窍是计算你的圆周上的点,并使用这些点来翻译和旋转你的上下文,然后要求布局pipe理器绘制字形。 下面是一个CurvyTextView的drawText示例(沿Bézier曲线绘制)。

 - (void)drawText { if ([self.attributedString length] == 0) { return; } NSLayoutManager *layoutManager = self.layoutManager; CGContextRef context = UIGraphicsGetCurrentContext(); NSRange glyphRange; CGRect lineRect = [layoutManager lineFragmentRectForGlyphAtIndex:0 effectiveRange:&glyphRange]; double offset = 0; CGPoint lastGlyphPoint = self.P0; CGFloat lastX = 0; for (NSUInteger glyphIndex = glyphRange.location; glyphIndex < NSMaxRange(glyphRange); ++glyphIndex) { CGContextSaveGState(context); CGPoint location = [layoutManager locationForGlyphAtIndex:glyphIndex]; CGFloat distance = location.x - lastX; // Assume single line offset = [self offsetAtDistance:distance fromPoint:lastGlyphPoint andOffset:offset]; CGPoint glyphPoint = [self pointForOffset:offset]; double angle = [self angleForOffset:offset]; lastGlyphPoint = glyphPoint; lastX = location.x; CGContextTranslateCTM(context, glyphPoint.x, glyphPoint.y); CGContextRotateCTM(context, angle); [layoutManager drawGlyphsForGlyphRange:NSMakeRange(glyphIndex, 1) atPoint:CGPointMake(-(lineRect.origin.x + location.x), -(lineRect.origin.y + location.y))]; CGContextRestoreGState(context); } } 

这个“魔术”就是计算你需要的变换,这是在offsetAtDistance:fromPoint:andOffset:pointForOffset:angleForOffset: 。 这些例程比一般的Bézier曲线要简单得多,所以这可能是一个非常好的起点。 请注意,此代码不是特别优化。 它的devise不仅速度可读,而且在iPad 3上的速度还是非常快。如果你需要更快的速度, 有几种技术 ,包括许多可以预先计算的技术 。

PinchText演示版是纯粹的核心文本和核心animation,并且相当复杂一些,因为它在加速(而且真的需要)中完成了所有的math运算。 我怀疑你需要,因为你的布局问题并不复杂。 一些简单的C可能可以在很多时间内计算出你需要的一切。 但PinchText演示确实展示了如何让Core Animation更好地pipe理转换。 看看addTouches:inView:scale: ::

 - (void)addTouches:(NSSet *)touches inView:(UIView *)view scale:(CGFloat)scale { for (UITouch *touch in touches) { TouchPoint *touchPoint = [TouchPoint touchPointForTouch:touch inView:view scale:scale]; NSString *keyPath = [self touchPointScaleKeyPathForTouchPoint:touchPoint]; CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:keyPath]; anim.duration = kStartTouchAnimationDuration; anim.fromValue = @0; anim.toValue = @(touchPoint.scale); anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; [self addAnimation:anim forKey:keyPath]; [self.touchPointForIdentifier setObject:touchPoint forKey:touchPoint.identifier]; } } 

这里发生的是animation模型数据(这里的“缩放”是“这个接触对布局有多大的影响”,它与变换没有关系)。 needsDisplayForKey:表示当该模型数据结构被修改时,该层需要重绘本身。 它完全重新计算和重新绘制在每个框架的上下文中。 做得正确,这可以非常快。

这个代码应该让你开始。 不要过度推动本书,但CurvyText演示在iOS推动极限第21章中进行了广泛的讨论。

Interesting Posts