- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在创建带条形动画的条形图。我将它们绘制在 View 下划线层中(这是我的自定义 BarChartLayer
)。该层负责所有绘图。
对于动画图表栏,我使用名为 procentAnimation
的可动画属性.在该值的动画变化期间,在绘制方法中,我计算两个数组的值之间的步长( oldValues
, newValues
)。
从 oldValues 到 newValues 的第一个动画效果很好。在动画委托中执行动画之后,我交换两个数组的值。
第二个动画应该看起来像反向动画。但是在动画开始后,条形图跳到第一个动画开始位置,然后动画像第一个动画一样连续,完成后图表条形图跳回到第二个动画的最终位置。
在 Debug模式下,我发现,当我添加第二个动画时,属性值 oldValues
和 newValues
保持正确,但是当动画在方法 draw(in:)
中开始时oldValues
的值和 newValues
跳回第一个动画期间的情况。
这是一个错误还是有一些我不明白的机制?如何解决这个问题?
class BarChartLayer: CALayer {
var oldValues: [CGFloat] = [45, 34, 12, 88, 17, 77, 88, 10] {
didSet {
debugPrint("oldValues set")
}
}
var newValues: [CGFloat] = [92, 72, 64, 32, 28, 15, 11, 33] {
didSet {
debugPrint("newValues set")
}
}
var numberOfBars: CGFloat = 8
var space: CGFloat = 10
@objc var procentAnimation : CGFloat = 0
override class func needsDisplay(forKey key: String) -> Bool {
if key == #keyPath(procentAnimation) {
return true
}
return super.needsDisplay(forKey:key)
}
func animateBarsChange() {
let ba = CABasicAnimation(keyPath:#keyPath(BarChartLayer.procentAnimation))
procentAnimation = 100
ba.duration = 4.0
ba.fromValue = 0
ba.delegate = self
add(ba, forKey:nil)
}
func barWidth(rect: CGRect) -> CGFloat {
return (rect.width - CGFloat(space * (numberOfBars - 1))) / CGFloat(numberOfBars)
}
func procentRanndomizer(rect: CGRect) -> CGFloat {
return CGFloat.random(in: 1...100) * rect.height / 100
}
func makeProcentFor(value: CGFloat, rect: CGRect) -> CGFloat {
return value * rect.height / 100
}
func additionalHeight(index: Int) -> CGFloat {
return (newValues[index] - oldValues[index]) / 100
}
func makeRandomArr() -> [CGFloat] {
var arr = [CGFloat]()
for _ in 0..<8 {
arr.append(CGFloat.random(in: 1...100))
}
return arr
}
override func draw(in ctx: CGContext) {
UIGraphicsPushContext(ctx)
let con = ctx
let rect = self.bounds
con.addRect(rect)
con.setFillColor(UIColor.gray.cgColor)
con.fillPath()
var px:CGFloat = 0
let bw = barWidth(rect: rect)
debugPrint("OLD - \(oldValues)")
debugPrint("NEW - \(newValues)")
let oldValues = self.oldValues
for i in 0..<Int(numberOfBars) {
px = CGFloat(i) * (bw + space)
let h = oldValues[i] + procentAnimation * additionalHeight(index: i)
con.addRect(CGRect(x: px, y: 0, width: bw, height: makeProcentFor(value: h, rect: rect)))
}
con.setFillColor(UIColor.green.cgColor)
con.fillPath()
UIGraphicsPopContext()
}
}
extension BarChartLayer: CAAnimationDelegate {
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
if flag {
let temp = self.oldValues
self.oldValues = self.newValues
self.newValues = temp//makeRandomArr()
self.procentAnimation = 0
debugPrint("------------------------------------")
setNeedsDisplay()
}
}
}
最佳答案
您应该使用 @NSManaged
标记自定义可动画属性,因为 Core Animation 会创建模型层的副本以进行渲染。 @NSManaged
不允许使用默认值。所以你应该重写 defaultValue(forKey:)
。
@NSManaged var procentAnimation : CGFloat
override class func defaultValue(forKey inKey: String) -> Any? {
return inKey == "procentAnimation" ? 0.0 : super.defaultValue(forKey: inKey)
}
您也不应该在 CALayer 实现中使用 UIKit 函数。因此,您应该将 UIGraphicsPushContext
和 UIGraphicsPopContext
替换为 Core Graphics 对应项:
override func draw(in ctx: CGContext) {
ctx.saveGState()
...
ctx.restoreGState()
}
关于ios - CALayer (CAAnimation) 可动画属性绘制错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59185344/
我有一个带有 5 个 subview 的旋转圆形,我正在对其填充颜色进行动画更改以匹配当前位于顶部的 subview 。因此,当我必须更改颜色时,我会从该层中删除动画,然后添加新的动画,如下所示: [
我正在使用一对 CALayer 作为图像 mask ,让我能够以设定的速度制作灯泡填充或排空的动画,同时还可以跟随当前的触摸位置。也就是说,一个 mask 会随着触摸而跳动,而另一个会滑动到该位置。由
在我的应用程序中,我有一个 CALayer 数组,我已经沿着 bezierPath 设置了动画。当我关闭并重新打开应用程序时,我的图层没有动画,并且与关闭应用程序之前的位置不同。我已经实现了两种方法,
是否可以在开始时定义所有 CAAnimations 并在不使用委托(delegate)的情况下依次播放它们,就像我们在 CAAnimationGroup 中所做的那样,其中动画同时播放。相反,我只想让
我有一个重复动画,需要与其他一些 transient 动画同步。重复动画是一条在屏幕上移动 4 秒的扫描线。当它经过下面的图像时,这些图像需要“闪烁”。 闪烁的图像可以根据用户的意愿来来去去和移动。它
假设我想要制作一个向右滚动 1000 像素的球的动画,并在此过程中指定一个计时函数 - 如下所示: UIView *ball = [[UIView alloc] initWithFrame:CGRec
我正在为 UIView(或者更确切地说它的 CALayer)设置动画,并且在动画结束时它不再可见(我进行 3D 变换,使其围绕 y 旋转 90°,想象一扇门朝你打开),虽然它是技术上“可见”,因为它的
我想在CALayer上捕获动画的每一帧以生成mp4电影文件。 所以,我在下面编写了代码。 frames 是动画中的总帧数,frameTime 是 1/60 秒,animationLayer 已经添加到
我已将 CAAnimation 添加到某个 View 的层,它会为 View 的 position 设置动画。当动画运行时,我想在 OpenGL 窗口中为一个对象设置动画。为此,我必须以某种方式从我设
这个苹果文档 https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreAnimation_guide/C
我使用它来沿着路径为对象设置动画。我想知道如何在动画过程中的任意时刻获取对象的位置,以检查与另一个对象的碰撞。任何想法如何去做这个?谢谢。 - (void) animateCicleAlongPath
我正在尝试为 View 图层在任意点上的旋转设置动画。动画的开始位置将从结束和最终位置旋转 90º。该 View 占据了除状态栏之外的所有屏幕。 我正在尝试使用以下代码(带有平移,然后是旋转和反平移)
我有一个无限旋转的 UIImageView 形式的自定义事件指示器。这个惊人的事件指示器被放置在一个表格单元格中。 动画是这样实现的: CABasicAnimation* animation = [C
我正在尝试创建一个将具有动画功能的新 ImageView 。但是,我的动画有问题,让我们看看; 在这里,我只需要让这个动画看起来是连续的。我的意思是,在每个循环的开始都没有那个故障。就在左上角的右边缘
我只想通过圆心 C 和半径 R 的圆弧从 A 点到 B 点对图层的 position 属性进行动画处理。如此简单,但我觉得我在尝试弯曲 Core Animation一半做这个。 看起来理想的方法是简单
我正在尝试使用 CAAnimation,并且像许多新来者一样使用 CAAnimation;完成后,图层将恢复到其原始状态。 关于如何解决这个问题已经在这里问过几次了,答案是将以下代码添加到您的 CAA
//卡片类的头文件 #import "OWCardView.h" @implementation OWCardView; - (id)initWithFrame:(CGRect)frame {
我正在尝试制作一个简单的复选标记控件,其中仅包含一个正方形和一个复选标记。我想在点击控件时为复选标记的绘制和删除设置动画。这是我目前所拥有的: let path = UIBezierPath() pa
是否可以使用 CAAnimation 实现图像的动画序列?而且我不想使用 UIImageView... 我需要类似于 UIImageView 的东西,我们可以在其中设置 imageView.anima
如何使我的 CAKeyframeAnimation 具有永无止境的重复计数? 我尝试了 animation.repeatCount = -1; 但它只重复一次。 最佳答案 您还可以使用 animati
我是一名优秀的程序员,十分优秀!