Ios 设置贝塞尔曲线动画,就像在iPhone屏幕上继续绘制一样
我想画一条泰姬陵轮廓的贝塞尔路径 问题1。我如何用XCode绘制它?我可以在PS中轻松地做到这一点,但我发现在XCode中编程很难做到,尤其是获取控制点的坐标 问题2。此外,当屏幕尺寸变化时,如何固定点的坐标Ios 设置贝塞尔曲线动画,就像在iPhone屏幕上继续绘制一样,ios,objective-c,animation,uibezierpath,Ios,Objective C,Animation,Uibezierpath,我想画一条泰姬陵轮廓的贝塞尔路径 问题1。我如何用XCode绘制它?我可以在PS中轻松地做到这一点,但我发现在XCode中编程很难做到,尤其是获取控制点的坐标 问题2。此外,当屏幕尺寸变化时,如何固定点的坐标 第三季度。我怎么能把它当作一支看不见的铅笔在屏幕上画呢?我在2010年写了一篇博客 其要点如下: 使用要绘制的形状创建UIBezierPath或CGPath。使用方法moveToPoint:,addLineToPoint:, 添加CurveToPoint:controlPoint1:co
第三季度。我怎么能把它当作一支看不见的铅笔在屏幕上画呢?我在2010年写了一篇博客 其要点如下:
- 使用要绘制的形状创建
或UIBezierPath
。使用方法CGPath
,moveToPoint:
,addLineToPoint:
等以创建形状添加CurveToPoint:controlPoint1:controlPoint2:
- 创建一个
并将路径指定给层的CGShapeLayer
属性path
- 将图层添加到视图/图层层次结构中(例如,在视图控制器中:
)。您还必须为层提供有效的大小和位置([self.view.layer addSublayer:shapeLayer];
)frame
- 将层的
属性从0设置为1strokeEnd
UIKit
中绘制贝塞尔路径?
创建一个UIBezierPath
对象,然后使用
我想你最感兴趣的方法是:
- (相当自我解释,将当前点移动到给定点)
- (添加一条直线,从当前点开始,到给定点结束)
- (添加贝塞尔曲线,从当前点开始,带有设定的终点和控制点)
- 添加一条二次曲线,从当前点开始,具有设定的终点和控制点
UIBezierPath* yourPath = [UIBezierPath bezierPath]; // create the bezier path
[yourPath moveToPoint:CGPointMake(100, 100)]; // move to your starting point
[yourPath addQuadCurveToPoint:CGPointMake(300, 500) controlPoint:CGPointMake(500, 350)]; // add a new quad curve to the point
yourShapeLayer.strokeStart = 0.0; // reset stroke start before animating
CABasicAnimation* strokeAnim = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; // create animation that changes the strokeEnd property
strokeAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; // give it a nice timing function
strokeAnim.duration = 2.0; // duration of the animation
strokeAnim.fromValue = @(0.0); // provide the start value for the animation, wrapped in an NSNumber literal.
strokeAnim.toValue = @(1.0); // provide the end value for the animation, wrapped in an NSNumber literal.
[yourShapeLayer addAnimation:strokeAnim forKey:@"strokeAnim"]; // add animation to layer
但是,如果您习惯于使用Photoshop之类的工具来创建路径,您可以使用“所见即所得”的方法创建贝塞尔路径
您可以将此UIBezierPath
添加到CAShapeLayer
的path
属性中,以便在屏幕上显示它。
CAShapeLayer* yourShapeLayer = [CAShapeLayer layer]; // create your shape layer
yourShapeLayer.frame = CGRectMake(0, 0, 300, 500); // assign it's frame
yourShapeLayer.path = yourPath.CGPath; // add your path to the shape layer
yourShapeLayer.fillColor = [UIColor clearColor].CGColor; // prevent the shape layer from filling
[self.view.layer addSublayer:yourShapeLayer]; // add the shape layer to the view
yourShapeLayer.strokeColor = [UIColor redColor].CGColor; // red stroke color
yourShapeLayer.lineWidth = 5.0; // 5 point stroke width
然后,您可以轻松设置形状层上的strokeColor
和lineWidth
属性,以自定义路径的笔划方式。
CAShapeLayer* yourShapeLayer = [CAShapeLayer layer]; // create your shape layer
yourShapeLayer.frame = CGRectMake(0, 0, 300, 500); // assign it's frame
yourShapeLayer.path = yourPath.CGPath; // add your path to the shape layer
yourShapeLayer.fillColor = [UIColor clearColor].CGColor; // prevent the shape layer from filling
[self.view.layer addSublayer:yourShapeLayer]; // add the shape layer to the view
yourShapeLayer.strokeColor = [UIColor redColor].CGColor; // red stroke color
yourShapeLayer.lineWidth = 5.0; // 5 point stroke width
你应该以这样的方式结束:
我怎么能像一支看不见的铅笔在屏幕上画一样给它设置动画呢? 您可以轻松创建一个
cabasicanition
,它可以为CAShapeLayer
的strokeStart
或strokeEnd
属性设置动画,以实现所需的动画效果
这可能会导致线“绘制”到屏幕上的动画效果
yourShapeLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.width);
例如,此代码将导致strokeEnd
属性从0.0
动画化为1.0
,创建所需效果:
UIBezierPath* yourPath = [UIBezierPath bezierPath]; // create the bezier path
[yourPath moveToPoint:CGPointMake(100, 100)]; // move to your starting point
[yourPath addQuadCurveToPoint:CGPointMake(300, 500) controlPoint:CGPointMake(500, 350)]; // add a new quad curve to the point
yourShapeLayer.strokeStart = 0.0; // reset stroke start before animating
CABasicAnimation* strokeAnim = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; // create animation that changes the strokeEnd property
strokeAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; // give it a nice timing function
strokeAnim.duration = 2.0; // duration of the animation
strokeAnim.fromValue = @(0.0); // provide the start value for the animation, wrapped in an NSNumber literal.
strokeAnim.toValue = @(1.0); // provide the end value for the animation, wrapped in an NSNumber literal.
[yourShapeLayer addAnimation:strokeAnim forKey:@"strokeAnim"]; // add animation to layer
如何缩放此路径以使用不同大小的屏幕? 我通常喜欢解决这个问题的方法是在给定的固定帧中定义路径的点(比方说500 x 500点),然后根据屏幕的大小生成一个比例因子(在您的情况下,您希望缩放到屏幕的宽度) 所以我们所要做的就是生成我们的比例因子
CGFloat sf = self.view.frame.size.width/500.0; // The factor to scale the path by
然后,我们只需将UIBezierPath
中的所有点乘以该比例因子即可。例如,以我们前面的路径为例:
UIBezierPath* yourPath = [UIBezierPath bezierPath]; // create the bezier path
[yourPath moveToPoint:CGPointMake(100.0*sf, 100.0*sf)]; // move to your starting point
[yourPath addQuadCurveToPoint:CGPointMake(300.0*sf, 500.0*sf) controlPoint:CGPointMake(500.0*sf, 350.0*sf)];
现在,我们所要做的就是在贝塞尔路径点中编程,就好像我们总是在500 x 500的框架中绘制它一样(我的点已经很好地融入其中)。
CAShapeLayer* yourShapeLayer = [CAShapeLayer layer]; // create your shape layer
yourShapeLayer.frame = CGRectMake(0, 0, 300, 500); // assign it's frame
yourShapeLayer.path = yourPath.CGPath; // add your path to the shape layer
yourShapeLayer.fillColor = [UIColor clearColor].CGColor; // prevent the shape layer from filling
[self.view.layer addSublayer:yourShapeLayer]; // add the shape layer to the view
yourShapeLayer.strokeColor = [UIColor redColor].CGColor; // red stroke color
yourShapeLayer.lineWidth = 5.0; // 5 point stroke width
您还需要更改CAShapeLayer
的大小,使其成为正方形并占据整个屏幕宽度
yourShapeLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.width);
最后,您需要将CAShapeLayer
定位到屏幕中央。通过将图层的位置
属性设置为视图的中心
,可以轻松完成此操作
yourShapeLayer.position = self.view.center;
现在,您的路径应始终缩放以占据屏幕宽度。
CAShapeLayer* yourShapeLayer = [CAShapeLayer layer]; // create your shape layer
yourShapeLayer.frame = CGRectMake(0, 0, 300, 500); // assign it's frame
yourShapeLayer.path = yourPath.CGPath; // add your path to the shape layer
yourShapeLayer.fillColor = [UIColor clearColor].CGColor; // prevent the shape layer from filling
[self.view.layer addSublayer:yourShapeLayer]; // add the shape layer to the view
yourShapeLayer.strokeColor = [UIColor redColor].CGColor; // red stroke color
yourShapeLayer.lineWidth = 5.0; // 5 point stroke width
(我在图层上添加了一个灰色背景,只是为了说明缩放效果)
完整项目(为了您的方便):由originaluser2发布的答案解决了所有问题。如果要调整不同设备屏幕的bezier路径,也可以尝试这种方法: 您只需将UIView子类化并自定义其drawRect方法:
- (void)drawRect: (CGRect)frame
{
//// Bezier Drawing
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.23370 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.65441 * CGRectGetHeight(frame))];
[bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.49457 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.33088 * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 0.23370 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.65441 * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 0.35870 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.33088 * CGRectGetHeight(frame))];
[bezierPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.77717 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.65441 * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 0.63043 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.33088 * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 0.77717 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.65441 * CGRectGetHeight(frame))];
[UIColor.blackColor setStroke];
bezierPath.lineWidth = 1;
[bezierPath stroke];
}
机架50x50:
机架100x100:
机架100x50
如果发送大小为50x50的帧,则在大小为50x50的帧中绘制贝塞尔曲线。此外,此代码会根据收到的帧大小自动调整大小。我添加了一个额外的问题,当屏幕大小变化时,如何固定点的坐标?您所说的固定是什么意思?你的意思是当屏幕放大时它们会放大吗?或者说,你的意思是它们实际上是固定不变的?比如说,如果我想让动画在一个正方形的框架中,无论设备大小,它总是以屏幕为中心。那么我该如何使用坐标来做到这一点呢?@Viki你只需要保持
CAShapeLayer
的大小不变,只需将其位置调整到屏幕中央即可。您不必更改路径本身。虽然你是说你也希望路径在正方形框架内缩放?是的,我希望动画根据设备的大小进行缩放,其相对位置固定,就像自动布局一样。像在imageview中一样,图像会根据设备的大小进行缩小或扩展。但是视图本身的相对位置是恒定的。我们添加了一个额外的问题,当t