iOS 中的极坐标变换
Polar transformation in iOS
谁能帮我通过Core Graphics实现这种动画转换。看草图:
这是一个简单的图表图形,我需要将直方图样式的条形图(左图)转换为饼图(右图)。
从字面上看,任务是用 流畅的动画 将一个矩形滚动成一个环。我几乎找到了用一系列棘手的绘图、蒙版剪裁和仿射变换来做到这一点的方法,但这看起来并不是我想要的样子。
歪斜、扭曲和弯曲是 none 物体上的微不足道的变形。
这些都做不到Core Graphics
。
最好自己在core graphic
中用CGContextAddArcToPoint
绘制图表,并遮住内圈。
另一种(硬核)方法是使用 3d 引擎 - 即场景套件 - 并将图表作为纹理应用到它。
这是一个有趣的挑战,尤其是当您想要维护不同的细分市场时。我不会给你一个完整的答案(即实现这个的完整示例代码),但我会解释我认为需要做什么才能达到你想要的效果。
路径
首先,我将这两个图表视为一条被描边的直线(让我们暂时忽略线段),所以挑战是从直线到封闭的圆。
我建议以下两条路径,您可以在它们之间设置动画以实现漂亮的环绕效果。
// As we render a circle as a chain of straight line segments
// changing the count of said segments makes the circle more or less smooth
// Try this with other values, such as 8 or 32
let segments = 72
// With this segment count, the angle of each segment in the circle is
let angle = (2 * CGFloat(M_PI)) / CGFloat(segments)
// First path (straight)
let length = CGFloat(300.0)
let segmentLength = length / CGFloat(segments)
let straightPath = CGPathCreateMutable()
CGPathMoveToPoint(straightPath, nil, 0.0, 0.0)
for i in 0...segments {
CGPathAddLineToPoint(straightPath, nil, 0.0, CGFloat(i) * segmentLength)
}
// Second path (circle)
let radius = CGFloat(100.0)
let center = CGPoint(x: 104.0, y: 104.0)
let space = (x: 2.0, y: 2.0)
var circlePath = CGPathCreateMutable()
CGPathMoveToPoint(circlePath, nil, center.x + radius, center.y)
for i in 0...segments {
let x = cos(-CGFloat(i) * angle)
let y = sin(-CGFloat(i) * angle)
CGPathAddLineToPoint(circlePath, nil, center.x + radius * x, center.y + radius * y)
}
我还上传了一个 Swift 的平台供你试验,你可以找到 here
细分
现在,处理段可能有点棘手,但我提出了一个可能有效的相对简单的实现。 CAShapeLayer
主要有以下两个属性 - strokeStart
和 strokeEnd
,它们允许控制实际描边的路径部分。
考虑到这一点,您可以创建与段一样多的图层,为它们分配相同的路径并调整它们各自的 strokeStart
和 strokeEnd
属性以使其看起来你期望的方式。与他们在 this post.
中所做的有点相似
动画
假设您已经征服了前两个方面,动画方面应该相对简单,使用您拥有的两种类型的路径,您可以创建一个从一个到另一个的简单 CABasicAnimation
。我假设您熟悉 CoreAnimation 及其用法(即如何正确更改模型值以匹配显示的值等)。
我将以一个快速动画结束我的回答,展示最终结果的样子(减去片段),我已经冻结了动画并正在操纵层的 timeOffset
属性手动擦洗它。
希望我的回答能帮助您更接近您想要的解决方案。同样重要的是要强调我的代码示例只是一个开始,您可能需要对值进行相当多的调整才能获得令人满意的动画(例如,线的长度应该与圆周的长度相似)圆圈)。
谁能帮我通过Core Graphics实现这种动画转换。看草图:
这是一个简单的图表图形,我需要将直方图样式的条形图(左图)转换为饼图(右图)。 从字面上看,任务是用 流畅的动画 将一个矩形滚动成一个环。我几乎找到了用一系列棘手的绘图、蒙版剪裁和仿射变换来做到这一点的方法,但这看起来并不是我想要的样子。
歪斜、扭曲和弯曲是 none 物体上的微不足道的变形。
这些都做不到Core Graphics
。
最好自己在core graphic
中用CGContextAddArcToPoint
绘制图表,并遮住内圈。
另一种(硬核)方法是使用 3d 引擎 - 即场景套件 - 并将图表作为纹理应用到它。
这是一个有趣的挑战,尤其是当您想要维护不同的细分市场时。我不会给你一个完整的答案(即实现这个的完整示例代码),但我会解释我认为需要做什么才能达到你想要的效果。
路径
首先,我将这两个图表视为一条被描边的直线(让我们暂时忽略线段),所以挑战是从直线到封闭的圆。
我建议以下两条路径,您可以在它们之间设置动画以实现漂亮的环绕效果。
// As we render a circle as a chain of straight line segments
// changing the count of said segments makes the circle more or less smooth
// Try this with other values, such as 8 or 32
let segments = 72
// With this segment count, the angle of each segment in the circle is
let angle = (2 * CGFloat(M_PI)) / CGFloat(segments)
// First path (straight)
let length = CGFloat(300.0)
let segmentLength = length / CGFloat(segments)
let straightPath = CGPathCreateMutable()
CGPathMoveToPoint(straightPath, nil, 0.0, 0.0)
for i in 0...segments {
CGPathAddLineToPoint(straightPath, nil, 0.0, CGFloat(i) * segmentLength)
}
// Second path (circle)
let radius = CGFloat(100.0)
let center = CGPoint(x: 104.0, y: 104.0)
let space = (x: 2.0, y: 2.0)
var circlePath = CGPathCreateMutable()
CGPathMoveToPoint(circlePath, nil, center.x + radius, center.y)
for i in 0...segments {
let x = cos(-CGFloat(i) * angle)
let y = sin(-CGFloat(i) * angle)
CGPathAddLineToPoint(circlePath, nil, center.x + radius * x, center.y + radius * y)
}
我还上传了一个 Swift 的平台供你试验,你可以找到 here
细分
现在,处理段可能有点棘手,但我提出了一个可能有效的相对简单的实现。 CAShapeLayer
主要有以下两个属性 - strokeStart
和 strokeEnd
,它们允许控制实际描边的路径部分。
考虑到这一点,您可以创建与段一样多的图层,为它们分配相同的路径并调整它们各自的 strokeStart
和 strokeEnd
属性以使其看起来你期望的方式。与他们在 this post.
动画
假设您已经征服了前两个方面,动画方面应该相对简单,使用您拥有的两种类型的路径,您可以创建一个从一个到另一个的简单 CABasicAnimation
。我假设您熟悉 CoreAnimation 及其用法(即如何正确更改模型值以匹配显示的值等)。
我将以一个快速动画结束我的回答,展示最终结果的样子(减去片段),我已经冻结了动画并正在操纵层的 timeOffset
属性手动擦洗它。
希望我的回答能帮助您更接近您想要的解决方案。同样重要的是要强调我的代码示例只是一个开始,您可能需要对值进行相当多的调整才能获得令人满意的动画(例如,线的长度应该与圆周的长度相似)圆圈)。