gpt4 book ai didi

ios - 如何在 UIBezierPath 上绘制文本?

转载 作者:行者123 更新时间:2023-11-29 01:29:06 26 4
gpt4 key购买 nike

我不知道这是否可行。到目前为止,我的研究没有给出任何提示。

我有一个 UIBezierPath 并且喜欢在它上面绘制一个文本,所以文本是弯曲的。

我这可能吗?从哪里开始有任何提示吗?

最佳答案

参见 CurvyText来自 iOS Programming Pushing the Limits 的简单版本,它沿着一条三次贝塞尔曲线绘制。该技术可以扩展到更复杂的曲线,但它确实变得更加复杂,尤其是在交叉点。

您需要几种基本技术。首先,您需要一个函数来计算曲线上点的位置。然后,您需要计算函数的一阶导数(斜率)。然后,您需要一种将线性距离转换为偏移量的方法。最后,您需要布局文本。

计算曲线上的点可能是最简单的部分。您只需要计算该函数即可。例如,这是三次贝塞尔函数:

static double Bezier(double t, double P0, double P1, double P2,
double P3) {
return
(1-t)*(1-t)*(1-t) * P0
+ 3 * (1-t)*(1-t) * t * P1
+ 3 * (1-t) * t*t * P2
+ t*t*t * P3;
}

其他可能的 UIBezierPath 函数通常更简单。

然后您需要计算曲线的斜率。这只是一阶导数,希望你能从第一级微积分的内存中找出来。

static double BezierPrime(double t, double P0, double P1,
double P2, double P3) {
return
- 3 * (1-t)*(1-t) * P0
+ (3 * (1-t)*(1-t) * P1) - (6 * t * (1-t) * P1)
- (3 * t*t * P2) + (6 * t * (1-t) * P2)
+ 3 * t*t * P3;
}

如果这是一条更复杂的曲线,则交汇处的斜率未定义。因此,如果您遇到该问题,您可能希望将偏移量稍微增加或减少,以避免尝试在过渡处准确布置字母。

顺便说一句,你会注意到我做的事情像 (1-t)*(1-t)*(1-t) 而不是 pow(1-t,3) 。前者比后者快得多。参见 Introduction to Fast Bezier对此进行更多讨论。编译器足够智能,只计算一次 1-t,因此通常不需要创建临时变量,除非它有助于提高可读性。

一旦你有了积分,你仍然有一个小问题。贝塞尔曲线是根据参数t定义的,它是插值比。它不会映射到沿曲线的距离(这是您真正想要的)。如果你看Constructing Bézier curves中的动画在维基百科上,希望大家能更清楚地了解为什么这是真的。

没有简单的封闭式函数来计算沿贝塞尔曲线的距离。 Moving Along a Curve with Specified Speed中有一些很好的数值方法。 ,但我发现对于这个特定问题,只需非常缓慢地沿着曲线移动,直到找到一个与原点成所需线性距离的点。这并没有真正计算沿曲线的距离,但它很简单、快速,并且提供了良好的文本布局,特别是对于“合理”的曲线。

// Simplistic routine to find the offset along Bezier that is
// aDistance away from aPoint. anOffset is the offset used to
// generate aPoint, and saves us the trouble of recalculating it
// This routine just walks forward until it finds a point at least
// aDistance away. Good optimizations here would reduce the number
// of guesses, but this is tricky since if we go too far out, the
// curve might loop back on leading to incorrect results. Tuning
// kStep is good start.
- (double)offsetAtDistance:(double)aDistance
fromPoint:(CGPoint)aPoint
andOffset:(double)anOffset {
const double kStep = 0.001; // 0.0001 - 0.001 work well
double newDistance = 0;
double newOffset = anOffset + kStep;
while (newDistance <= aDistance && newOffset < 1.0) {
newOffset += kStep;
newDistance = Distance(aPoint,
[self pointForOffset:newOffset]);
}
return newOffset;
}

有了这些,你就必须布置文本。这需要要求 Core Text 对文本进行线性布局,然后调整布局以将其沿曲线放置。我在 Most performant way to draw text on a curve, and animate it? 中介绍了这部分问题(这个问题不需要介绍计算位置)。

关于ios - 如何在 UIBezierPath 上绘制文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33652153/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com