Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/105.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 设置贝塞尔曲线动画,就像在iPhone屏幕上继续绘制一样_Ios_Objective C_Animation_Uibezierpath - Fatal编程技术网

Ios 设置贝塞尔曲线动画,就像在iPhone屏幕上继续绘制一样

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

我想画一条泰姬陵轮廓的贝塞尔路径

问题1。我如何用XCode绘制它?我可以在PS中轻松地做到这一点,但我发现在XCode中编程很难做到,尤其是获取控制点的坐标

问题2。此外,当屏幕尺寸变化时,如何固定点的坐标


第三季度。我怎么能把它当作一支看不见的铅笔在屏幕上画呢?

我在2010年写了一篇博客

其要点如下:

  • 使用要绘制的形状创建
    UIBezierPath
    CGPath
    。使用方法
    moveToPoint:
    addLineToPoint:
    
    添加CurveToPoint:controlPoint1:controlPoint2:
    等以创建形状
  • 创建一个
    CGShapeLayer
    并将路径指定给层的
    path
    属性
  • 将图层添加到视图/图层层次结构中(例如,在视图控制器中:
    [self.view.layer addSublayer:shapeLayer];
    )。您还必须为层提供有效的大小和位置(
    frame
  • 将层的
    strokeEnd
    属性从0设置为1
如何在
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