目的
我试图使用从字形生成的UIBezierPath创建人类书写的动画近似.我理解并且我已经阅读了许多与我的相似的UIBezierPath问题(但不一样).我的目标是创建一个近似于执行字符和字母书写的人的外观的动画.
背景
我创建了一个游乐场,用于更好地理解用于动画字形的路径,就好像它们是手工绘制的一样.
Apple CAShapeLayer中的一些概念(strokeStart和strokeEnd)在动画时似乎并没有按预期运行.我认为通常人们倾向于将中风想象成使用书写工具(基本上是直线或曲线).我们认为笔划和填充是一条线,因为我们的书写工具不区分笔画和填充.
但是当动画时,路径的轮廓由线段构成(填充是单独处理的,不清楚如何设置填充位置的动画?).我想要实现的是一个自然的人类书写线/曲线,它显示了一个笔划的开始和结束,以及当动画从头到尾移动时添加的部分.最初看起来很简单,但我认为它可能需要设置填充位置的动画(不确定如何执行此操作),笔划开始/结束(不确定是否需要根据上面提到的动画执行方式的意外警告),以及使用子路径(如何从已知路径重建).
方法1
所以,我考虑过Path(CGPath/UIBezierPath)的想法.每个路径实际上包含构造字形所需的所有子路径,因此可能递归这些子路径并使用CAKeyframeAnimation/CABasicAnimations和显示部分构造的子路径的动画组将是一个很好的方法(尽管每个子路径的填充位置和笔划仍然是需要从头到尾动画?).
这种方法导致了一个精炼的问题:
如果有一个完整的UIBezierPath/CGPath,如何访问和创建UIBezierPath/CGPath(子路径)?
如何使用路径/子路径信息用书写工具绘制填充和描边的动画?(似乎这意味着需要同时为CALayer的strokeStart/strokeEnd,position和path属性设置动画)
注意:
正如人们可以在代码中观察到的那样,我确实拥有从字形获得的完成路径.我可以看到路径描述给了我类似路径的信息.如何获取该信息并将其重新编排为一组数据子路径 人类可写的笔画?
(这里的想法是将点信息转换为人类笔画的新数据类型.这意味着要求算法识别每个填充的起点,斜率,端点和边界)
提示
我在Pleco(一个成功实现类似算法的iOS应用程序)中注意到,每个笔划都由描述人类可写笔画的闭合路径组成.UIBezierPath具有基于连续填充填充的封闭路径.需要一种算法来细化重叠填充以为每个笔画类型创建不同的闭合路径.
Erica Sadun 在github上提供了一组路径实用程序.我没有完全探索这些文件,但它们可能在确定离散笔划时非常有用.
UIBezierPath结构似乎基于连续线段/曲线的概念.在填充的交叉点处出现汇合点,其表示有向路径变化.可以计算曲线/线段的行程/填充角度,并搜索相应汇流点的其他曲线/线吗?(即将一条线段连接在相交填充的间隙上,以产生两条独立的路径 - 假设一条线路拾取了点,并使用新的线段/曲线重新创建了路径)
内省:是否有更简单的方法?我错过了一个关键的API,一本书或更好的方法来解决这个问题吗?
一些替代方法(无用 - 需要加载GIF或闪存)以产生所需的结果:
良好的示例(使用Flash),其中一个表示层显示书写笔划的进展.(如果可能的话,这就是我想要在Swift/iOS中近似的东西) - (alt链接 - 请参阅左边的动画图像)
一个不太好的例子,显示使用渐进路径和填充来近似书写笔划特征(动画不流畅且需要外部资源):
一个Flash版本 - 我熟悉创建Flash动画,但我不愿意在1000版本中实现这些功能(不要太提及它在iOS上不受支持,尽管我可能还可以转换算法以利用带有css动画的HTML5画布).但是这个思路似乎有点远,毕竟,我想要的路径信息存储在我从提供的字体/字符串中提取的字形中.
方法2
我正在考虑使用基于笔划的字体而不是基于轮廓的字体来获取正确的路径信息(即填充表示为路径的信息).如果成功,这种方法比近似笔画,笔画类型,交叉点和笔画顺序更清晰.我已经向Apple提交了雷达,建议将基于笔划的字体添加到iOS(#20426819).尽管有这些努力,我仍然没有放弃形成一种算法,该算法解决了贝塞尔曲线上的线段和曲线的部分笔划,全笔画,交叉点和汇合点.
基于讨论/答案的最新想法
根据以下任何正在进行的对话和答案,提供以下附加信息.
笔划顺序很重要,大多数语言(本例中为中文)都有明确定义的笔划类型和笔划顺序规则,它们似乎提供了一种机制,可根据每个CGPathElement提供的点信息确定类型和顺序.
CGPathApply和CGPathApplierFunction看起来很有希望作为枚举子路径的方法(保存到数组并应用填充动画)
可以将一个蒙版应用于图层以显示子图层的一部分(我之前没有使用过此属性,但看起来如果我可以在子路径上移动可能有助于填充动画的蒙版图层?)
为每个路径定义了大量的点.好像仅使用字形轮廓定义BezierPath.这一事实使得理解交叉填充的开始,结束和结合是消除特定填充的歧义的重要因素.
可以使用其他外部库,以便更好地解决笔划行为.其他技术如Saffron Type System或其衍生产品之一可能适用于此问题域.
仅仅为动画设置动画的最简单解决方案的基本问题是可用的iOS字体是轮廓字体而不是基于笔划的字体.一些商业制造商确实生产基于笔划的字体.如果你有其中一个用于测试,请随意使用操场文件的链接.
我认为这是一个常见问题,随着我向解决方案迈进,我将继续更新帖子.如果需要进一步的信息或者我可能遗漏了一些必要的概念,请在评论中告诉我.
可能解决方案
我一直在寻找最简单的解决方案.问题源于字体的结构是轮廓字体而不是基于笔画的字体.我发现了一个基于笔划的字体样本进行测试,并使用它来评估概念证明(见视频).我现在正在寻找扩展的单笔划字体(包括中文字符)以进一步评估.一个不太简单的解决方案可能是找到一种方法来创建一个跟随填充的笔划,然后使用简单的二维几何来评估首先设置动画的笔划(例如中文规则在笔划顺序上非常清晰). …
试图创建一个CGMutablePath()
这样的:
let path = CGMutablePath()
CGPathMoveToPoint(path, nil, 30, 0)
Run Code Online (Sandbox Code Playgroud)
但编译器继续给我以下错误:'nil' not compatible with expected argument type 'UnsafePointer<CGAffineTransform>'
.我究竟做错了什么?我似乎无法在网上找到任何其他内容.(是的,我尝试将Ints转换为CGFloats,但它似乎没有什么区别.)
我需要__bridge
在iOS 上提供一些建议.
希望在SSCCE 1下面会解释这个问题比我的话比较好,但我需要知道我可以转换void*
成NSMutableArray*
; __bridge
应该使用哪种变体(参见代码中的注释).
阅读不同的桥梁,我推断出我需要,__bridge_transfer
但后来我收到了一个EXC_BAD_ACCESSaddObject:
最终,我想CGPoints
在CGPath
之后CGPathApply
调用一个数组.
#import <Foundation/Foundation.h>
void _processPathElement(void* info, const CGPathElement* element)
{
NSMutableArray *array = (/* WHAT BRIDGE HERE */ NSMutableArray*) info;
switch (element->type)
{
case kCGPathElementMoveToPoint:
case kCGPathElementAddLineToPoint:
{
CGPoint point = element->points[0];
[array addObject:[NSValue valueWithCGPoint:point]];
break;
}
default:
break;
}
}
int main(int argc, char *argv[])
{
@autoreleasepool
{
//Create path
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint( path, …
Run Code Online (Sandbox Code Playgroud) 我怎样才能转换NSBezierPath
为CGPath
.
谢谢.
我一直在钻研Apple的新Sprite Kit,并且已经使用了一段时间了.然而,当我试图为一个弯曲的路径绘制时,我遇到了一个问题SKShapeNode
.它似乎只是绘制一条直线.
这是我遇到的一个非常简单的例子 - 试图绘制CGPath
一个SKShapeNode
:
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 0, 0);
CGPathAddQuadCurveToPoint(path, NULL, 50, 100, 100, 0);
CGPathAddLineToPoint(path, NULL, 50, -100);
CGPathCloseSubpath(path);
SKShapeNode *shape = [[SKShapeNode alloc]init];
shape.path = path;
[self addChild:shape];
CGPathRelease(path);
Run Code Online (Sandbox Code Playgroud)
这是我的ASCII艺术,它正在做什么(抱歉,我没有足够的声誉发布实际图像):
---------------------------------------------------------------------------------
| EXPECTED RESULT | ACTUAL RESULT |
---------------------------------------------------------------------------------
| | |
| __----__ | |
| / \ <- Curve | ? |
| / \ | ____________ |
| \ / | \ / |
| …
Run Code Online (Sandbox Code Playgroud) 我想将矩形的UIBezierPath设置为三角形的动画,而不是为路径上的视图设置动画,而是为路径本身设置动画,使其从一种形状变为另一种形状.路径将添加到CALayer
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.fillColor = [[UIColor whiteColor] CGColor];
maskLayer.path = [self getRectPath];
-(CGPathRef)getTrianglePath
{
UIBezierPath* triangle = [UIBezierPath bezierPath];
[triangle moveToPoint:CGPointZero];
[triangle addLineToPoint:CGPointMake(width(self.view),0)];
[triangle addLineToPoint:CGPointMake(0, height(self.view))];
[triangle closePath];
return [triangle CGPath];
}
-(CGPathRef)getRectPath
{
UIBezierPath*rect = [UIBezierPath bezierPathWithRect:self.view.frame];
return [rect CGPath];
}
Run Code Online (Sandbox Code Playgroud) 我正试图找到一种方法,使用核心图形以编程方式绘制iOS 7风格的图标'squircle'形状.我不是问如何绘制圆角矩形.一个松鼠是一个超级椭圆:
这与常规的圆角矩形略有不同:
它的确切公式随时可用.但是,我无法弄清楚如何使用例如CGPath绘制它,更不用说填充它,并且能够相当容易地调整它.所有这一切,同时完全符合公式.
我想知道是否有一个工具可以用来在SpriteKit中轻松生成复杂的物理实体.我想有一个基于体积的物理实体与多边形类型的形状.SpriteKit允许使用该方法创建此类主体:
+ (SKPhysicsBody *)bodyWithPolygonFromPath:(CGPathRef)path
Run Code Online (Sandbox Code Playgroud)
不幸的是,手动生成这样的路径是耗时的任务,并且在测试时可能会有问题.SpriteHelper应用程序允许您在易于使用的可视化编辑器中定义体形,但此应用程序无法导出可在此处使用的路径.它是为cocos2d制作的,它做了很多像纹理包装等我不需要的东西,我也不能用SpriteKit.有没有人知道一个解决方案,可以很容易地定义CGPath,甚至可以通过alpha通道从png图像自动生成它们?虽然我的经验中的自动生成功能需要优化,因为当纹理可能具有更复杂的形状时,身体形状应该尽可能简单.
我在iOS 5中使用Core Graphics绘制了一个简单的路径:
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint( path, NULL, center.x , topMargin );
CGPathAddLineToPoint(path, NULL, center.x+20, topMargin+50);
CGPathAddLineToPoint(path, NULL, center.x , topMargin+40);
CGPathAddLineToPoint(path, NULL, center.x-20, topMargin+50);
CGPathAddLineToPoint(path, NULL, center.x , topMargin );
Run Code Online (Sandbox Code Playgroud)
现在我想填写Overlay模式,如下所示:
[[UIColor colorWithRed:0 green:0 blue:0 alpha:0.4] setFill];
CGContextAddPath(context, path);
CGContextSetBlendMode (context, kCGBlendModeOverlay);
CGContextFillPath(context);
Run Code Online (Sandbox Code Playgroud)
这给了我完全预期的结果.但接下来,我想创造一个浮雕效果.我想过使用白色和黑色阴影来实现这样的效果:
[[UIColor colorWithRed:0 green:0 blue:0 alpha:0] setFill];
CGContextAddPath(context, path);
CGContextSetShadowWithColor(context, CGSizeMake(1, 1), 1.0, highlightColor);
CGContextSetBlendMode (context, kCGBlendModeNormal);
CGContextFillPath(context);
[[UIColor colorWithRed:0 green:0 blue:0 alpha:0] setFill];
CGContextAddPath(context, path);
CGContextSetShadowWithColor(context, CGSizeMake(-1, -1), 1.0, shadowColor);
CGContextSetBlendMode (context, kCGBlendModeNormal); …
Run Code Online (Sandbox Code Playgroud) 目前,我正在尝试设计如何设置一个自定义按钮的动画,我有一个图像并具有坐标,但我发现你可以通过使用CGPath类或UIBezierPath创建一个按钮/对象类.有人可以告诉我两者之间有什么区别吗?
cgpath ×10
ios ×6
objective-c ×3
swift ×3
uibezierpath ×3
sprite-kit ×2
animation ×1
calayer ×1
cocoa ×1
game-physics ×1
math ×1
nsbezierpath ×1
shadow ×1
skshapenode ×1
sprite ×1
swift3 ×1