我猜它是用单个 CATextLayers 制作一个字符串,然后根据需要沿着曲线定位它们,然后制作动画。因为这就是我现在正在做的事情,但它失去了字距。方法如下:
Why isn't my curved text centering itself?
但 Core Text 是否更高效并且能够避免整个“绘制到上下文中”的废话,这种废话与精益、平均的 Core Animation 做事方式相比会减慢一切,并尊重字距调整?即避免 drawRect: 以及所有其他会大大减慢速度的方面,例如这种绘制到屏幕的方式:
https://github.com/darcyliu/CocoaSampleCode/tree/master/CoreTextArcCocoa
想象一个由 200 个字符组成的字符串,绕着一个圆圈弯曲,能够为字符之间的间距设置动画,希望稳定在 60fps。这可以通过 Core Animation 实现,但这是通过将字符串分解成单个字符并将它们以相等的间距围绕圆圈放置,这会导致字距调整信息完全丢失。
我希望有一种方法可以在不丢失字距调整信息的情况下执行此操作,并且仍然能够以 60fps 的速度动态调整间距。
最佳答案
当然可以。不过,在 iOS 7 中,您无需一直使用 Core Text。 NSLayoutManager 可以处理很多情况。查看CurvyText我为 iOS:PTL 编写的演示.您可以拖动所有控制点并查看沿曲线的文本布局。
要了解此布局在纯 Core Text 和 Core Animation 中的速度有多快,请参阅 PinchText来自 Rich Text, Core Text 的演示.这展示了如何调整 Core Text 布局以响应多点触控,因此文本似乎向您的手指弯曲。它包括如何使用 Core Animation 制作动画以获得平滑调整的示例(甚至在您移开手指时出现小的“飞溅”效果)。
我不太明白您所说的“将整个图画成一个上下文废话,这会减慢一切”是什么意思。我非常非常快地将它们绘制到上下文中(Core Animation 也做了很多绘制到上下文中)。
围绕圆圈弯曲文本比这两个演示中的任何一个都容易。诀窍是计算沿圆的点,并在要求布局管理器绘制字形之前使用这些点平移和旋转上下文。这是 CurvyTextView 中的 drawText 示例(沿着贝塞尔曲线绘制)。
- (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 中完成的: 。与通用贝塞尔曲线相比,为圆编写这些例程要简单得多,因此这可能是一个很好的起点。请注意,这段代码没有特别优化。它的设计目的是提高可读性而不是速度,但它在 iPad 3 上仍然非常快。如果您需要它更快,there are several techniques ,包括很多可以完成的预计算。
PinchText 演示是在纯 Core Text 和 Core Animation 中进行的,并且要复杂得多,因为它在 Accelerate 中完成了所有数学运算(并且确实需要这样做)。我怀疑你是否需要它,因为你的布局问题并不那么复杂。一些简单明了的 C 可能可以在充足的时间内计算出您需要的一切。但是 PinchText 演示确实展示了如何让 Core Animation 更漂亮地管理过渡。查看 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];
}
}
这里发生的事情是它正在为 模型 数据设置动画(这里的“比例”是“这种触摸对布局的影响有多大;”它与变换无关)。 needsDisplayForKey: 表示当该模型数据结构被修改时,该层需要重新绘制自身。它会在每一帧完全重新计算并将自己重新绘制到它的上下文中。如果操作得当,速度会非常快。
此代码有望帮助您入门。不要过分推销这本书,但在 iOS Pushing the Limits 中广泛讨论了 CurvyText 演示。第 21 章。
关于ios - 在曲线上绘制文本并为其设置动画的最高效方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25556257/
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
这是针对我无法破坏的现有公共(public)API,但我确实希望对其进行扩展。目前,该方法采用字符串或符号或任何其他在作为第一个参数传递给send时有意义的内容我想添加发送字符串、符号等列表的功能。我可以只使用is_a吗?数组,但还有其他发送列表的方法,这不是很像ruby。我将调用列表中的map,所以第一个倾向是使用respond_to?:map。但是字符串也会响应:map,所以这行不通。 最佳答案 如何将它们全部视为数组?String的行为与仅包含String的Array相同:deffoo(obj,arg)[*arg].eac