sha*_*oga 14 cgpath ios uibezierpath
我有许多UIBezierPath,我用CALyerAnimation @"StrokeStart"和@"strokeEnd"进行动画制作.
我希望动画对所有路径都具有相同的速度,所以我想我可以使用路径的长度:
距离/时间=速度
有没有办法计算路径"长度"?
谢谢
沙尼
虽然您可以通过数值积分来计算Bezier路径的长度,但通过将路径划分为线性段可以更轻松地完成.如果片段足够小,则可以忽略近似误差,尤其是您只是想要对其进行动画处理.
我将向您展示四条曲线的功能,但您也可以轻松地将立方曲线的解决方案合并到:
- (float) bezierCurveLengthFromStartPoint: (CGPoint) start toEndPoint: (CGPoint) end withControlPoint: (CGPoint) control
{
const int kSubdivisions = 50;
const float step = 1.0f/(float)kSubdivisions;
float totalLength = 0.0f;
CGPoint prevPoint = start;
// starting from i = 1, since for i = 0 calulated point is equal to start point
for (int i = 1; i <= kSubdivisions; i++)
{
float t = i*step;
float x = (1.0 - t)*(1.0 - t)*start.x + 2.0*(1.0 - t)*t*control.x + t*t*end.x;
float y = (1.0 - t)*(1.0 - t)*start.y + 2.0*(1.0 - t)*t*control.y + t*t*end.y;
CGPoint diff = CGPointMake(x - prevPoint.x, y - prevPoint.y);
totalLength += sqrtf(diff.x*diff.x + diff.y*diff.y); // Pythagorean
prevPoint = CGPointMake(x, y);
}
return totalLength;
}
Run Code Online (Sandbox Code Playgroud)
编辑
如果您无法访问路径控制点(例如,您使用弧创建路径),则始终可以使用CGPathApply函数访问基础贝塞尔曲线:
- (void) testPath
{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointZero];
[path addQuadCurveToPoint:CGPointMake(1, 1) controlPoint:CGPointMake(-2, 2)];
CGPathRef p = path.CGPath;
CGPathApply(p, nil, pathFunction);
}
void pathFunction(void *info, const CGPathElement *element)
{
if (element->type == kCGPathElementAddQuadCurveToPoint)
{
CGPoint p;
p = element->points[0]; // control point
NSLog(@"%lg %lg", p.x, p.y);
p = element->points[1]; // end point
NSLog(@"%lg %lg", p.x, p.y);
}
// check other cases as well!
}
Run Code Online (Sandbox Code Playgroud)
请注意,它不提供路径的起点,但您可以轻松地自行跟踪它.
| 归档时间: |
|
| 查看次数: |
5851 次 |
| 最近记录: |