为图层属性设置动画以简单地更改其他属性?

2023-11-21

想象一个CAGradientLayer.

制作动画非常容易.startPoint and .endPoint.

现在想象一个漂浮物spinLike这只是同时设置它们.

{因此,您可以简单地制作动画,而不是使用两个不同的动画spinLike.}

所以像..

class CustomGradientLayer: CAGradientLayer {
    
    @objc var spinLike: CGFloat = 0 {
        
        didSet {
            
            startPoint = CGPoint( ... )
            endPoint = CGPoint( ... )
            setNeedsDisplay()
        }
    }
}

制作动画spinLike...

class Test: UIView {

     ...
     g = CustomGradientLayer()
     a = CABasicAnimation(keyPath: "spinLike")
     ...
     g.add(a, forKey: nil)
     ...

But.

这不起作用,startPoint and endPoint一点也不感动。

怎么了?


注意-不幸的是你似乎不能@NSManaged具有 didSet 的属性...

enter image description here


注意 - 自己制作很容易自定义动画仅仅通过覆盖绘制循环.

周围有很多这样的例子。您可以这样做:

class CircleProgressLayer: CALayer {
     
    @NSManaged var progress: CGFloat

    override class func needsDisplayForKey(key: String) -> Bool {
         
        if key == "progress" {
            return true
        }
        return super.needsDisplayForKey(key)
    }
    
    override func draw(in ctx: CGContext) {
        
        path.fill() etc etc... your usual drawing code
    }
}

不幸的是我的问题是

与实际绘图无关:

通过动画属性spinLike,

我只是想更改每个帧现有的普通动画属性(在示例中,.startPoint and .endPoint )

你怎么做到这一点?

笔记!你无法改变.startPoint and .endPoint in drawInContext-你会的attempting to modify read-only layer


要为自定义属性设置动画,您应该将它们标记为@NSManaged。当您分配新值时,不应强制重绘。相反,你应该覆盖需要显示(forKey:).

class CustomedGradLayer: CAGradientLayer {
    @NSManaged var spinLike: CGFloat

    class func needsDisplay(forKey key: String) -> Bool {
        return key == "spinLike" || super.needsDisplay(forKey: key)
    }

    class func defaultValue(forKey key: String) -> Any? {
        return key == "spinLike" ? CGFloat(0) : super.defaultValue(forKey: key)
    }
}

最后,您应该根据以下内容实现图层的绘制苹果文档.

几个月前我用 Swift 写了一个小项目。它演示了具有科赫曲线深度的自定义图层动画。

这是图层类的代码:

class KochLayer: CALayer {
    fileprivate let kPI = CGFloat(Double.pi)
    @NSManaged var depth : CGFloat
    var midPoint: CGPoint {
        get {
            let theBounds = self.bounds

            return CGPoint(x: theBounds.midX, y: theBounds.midY)
        }
    }
    var color: CGColor!

    override class func defaultValue(forKey inKey: String) -> Any? {
        return inKey == kDepthKey ? 0.0 : super.defaultValue(forKey: inKey)
    }

    override class func needsDisplay(forKey inKey: String) -> Bool {
        if inKey == kDepthKey {
            return true
        }
        else {
            return super.needsDisplay(forKey: inKey)
        }
    }

    override init() {
        super.init()
    }

    override init(layer inLayer: Any) {
        super.init(layer: inLayer)
        if let theLayer = inLayer as? KochLayer {
            depth = theLayer.depth
            color = theLayer.color
        }
    }

    required init(coder inCoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func pointWithRadius(_ inRadius: CGFloat, angle inAngle: CGFloat) -> CGPoint {
        let theCenter = midPoint

        return CGPoint(x: theCenter.x + inRadius * sin(inAngle),
            y: theCenter.y - inRadius * cos(inAngle));
    }

    override func draw(in inContext: CGContext) {
        let theBounds = self.bounds
        let theRadius = fmin(theBounds.width, theBounds.height) / 2.0
        let thePoints: [CGPoint] = [
            pointWithRadius(theRadius, angle:0.0),
            pointWithRadius(theRadius, angle:2 * kPI / 3.0),
            pointWithRadius(theRadius, angle:4 * kPI / 3.0)
        ]
        let thePath = CGMutablePath()

        inContext.setLineWidth(0.5)
        inContext.setLineCap(.round)
        inContext.setLineJoin(.round)
        inContext.setFillColor(color)
        thePath.move(to: thePoints[0])
        for i in 0..<3 {
            addPointsToPath(thePath, fromPoint:thePoints[i], toPoint:thePoints[(i + 1) % 3], withDepth:self.depth)
        }
        inContext.addPath(thePath)
        inContext.fillPath()
    }

    func addPointsToPath(_ inoutPath: CGMutablePath, fromPoint inFromPoint: CGPoint, toPoint inToPoint: CGPoint, withDepth inDepth: CGFloat) {
        var thePoints = Array<CGPoint>(repeating: inFromPoint, count: 5)

        thePoints[4] = inToPoint;
        if inDepth <= 1.0 {
            curveWithWeight(inDepth, points:&thePoints)
            for i in 1..<5 {
                inoutPath.addLine(to: thePoints[i])
            }
        }
        else {
            let theDepth = inDepth - 1;

            curveWithWeight(1.0, points:&thePoints)
            for i in 0..<4  {
                addPointsToPath(inoutPath, fromPoint:thePoints[i], toPoint:thePoints[i + 1], withDepth:theDepth)
            }
        }
    }

    func curveWithWeight(_ inWeight: CGFloat, points inoutPoints: inout [CGPoint]) {
        let theFromPoint = inoutPoints[0]
        let theToPoint = inoutPoints[4]
        let theFactor = inWeight / (2 * sqrt(3))
        let theDelta = CGSize(width: theToPoint.x - theFromPoint.x, height: theToPoint.y - theFromPoint.y);

        inoutPoints[1] = CGPoint(x: theFromPoint.x + theDelta.width / 3,
            y: theFromPoint.y + theDelta.height / 3)
        inoutPoints[2] = CGPoint(x: theFromPoint.x + theDelta.width / 2 + theFactor * theDelta.height,
            y: theFromPoint.y + theDelta.height / 2 - theFactor * theDelta.width);
        inoutPoints[3] = CGPoint(x: theToPoint.x - theDelta.width / 3,
            y: theToPoint.y - theDelta.height / 3)
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为图层属性设置动画以简单地更改其他属性? 的相关文章

  • 从 NSArray 为 UITableView 创建索引

    我读过创建索引 uitableview 旁边的 a z 的最佳方法是设置一个 nsdictionaries 数组 其中每个字典对应一个部分 并且 rowValue 键包含一个行数组 NSDictionary headerTitle gt A
  • 协议扩展,不符合协议

    我正在创建一个名为MyFramework含有LoginProtocol swift它有一些默认行为 import UIKit public protocol LoginProtocol func appBannerImage gt UIIm
  • Swift - 集成 GameCenter 以使用排行榜

    我正在用 Swift 制作一个游戏 我希望能够使用 GameCenter 发布用户的分数 以便可以看到所有用户的分数 然而 我花了一天的时间试图弄清楚如何做到这一点 但我没有找到任何有用的说明 我对 iOS 编程和 Swift 还很陌生 关
  • 迭代 NSDictionary 时保持顺序

    我有一个 NSDictionary 它正在迭代并将数据保存到核心数据 如下所示 NSDictionary details valueDict objectForKey shipment master for NSDictionary res
  • Objective-c 截断字符串并在末尾添加省略号

    如何在 Objective C 中截断字符串 然后在末尾添加省略号 NSString origString A very long string blah blah blah const int clipLength 18 if origS
  • Phonegap Cordova Statusbar 插件创建双栏

    我正在开发一个使用phonegap 的应用程序 通过 CLI 构建 而不是 PhoneGap 构建 我的 cordova plugin statusbar 插件有问题 打开时它将增加额外的条高度 这是它的样子 双高菜单栏 我通过两种方式实现
  • Android 是否可以使用并发插值器?

    我有一组两个动画 两个动画使用过冲插值器一起运行
  • Objective C 中最好的多线程方法?

    我正在开发一个 iPad 应用程序 目前正在努力寻找多线程的最佳方法 让我用一个简化的例子来说明这一点 我有一个包含 2 个子视图的视图 一个目录选择器和一个包含所选目录中所有图像缩略图的图库 由于 下载 和生成这些缩略图可能需要相当长的时
  • SVG - 可以在一侧添加笔画破折号渐变或透明形式

    我创建了一个 SVG 动画 在其中允许中风虚线阵列移动 我是否可以在中风破折号数组的尾部添加渐变并保持一侧透明 如示例中所示 svg main width 700px margin 30px auto position relative s
  • iOS 4.2 - 打电话后返回应用程序

    我可以使用以下命令在我的应用程序中成功发起电话呼叫 UIApplication sharedApplication openURL NSURL URLWithString tel 123456789 但是 通话结束后是否可以自动返回应用程序
  • 影响 UINavigationBar 的后退按钮方法 (iOS)

    我有一个推送到详细视图控制器的表视图 从详细视图控制器中 当我按下 后退 按钮时 我希望更改一个整数值 如何以编程方式编辑导航栏后退按钮的操作 后退按钮会自动放置在我的应用程序中 因为我使用的是表视图 所以我实际上没有创建按钮 所以我不知道
  • WatchOS 应用程序未检测到配套的 iOS 应用程序

    我正在制作一个独立的Apple Watch应用程序 但有一个配套的iPhone应用程序 这对于手表应用程序的运行来说不是必需的 该应用程序使用手表连接如果安装了 iPhone 配套应用程序 则可以在设备之间同步数据 我可以打电话sessio
  • Objective c 中的 UIButton 虚线下划线

    正常下划线有效 但点下划线似乎不起作用 UIButton btn UIButton buttonWithType UIButtonTypeCustom btn frame CGRectMake 100 10 300 300 NSMutabl
  • 如何设置 NSUserDefault Key 的初始值?

    我想为 NSUserDefault 键设置一些初始值 以便应用程序的第一次运行具有一些合理的初始设置 我以为我在应用程序包 plist 中遇到了一种简单的方法来执行此操作 但现在我找不到它 有任何想法吗 您应该使用registerDefau
  • 如何捕获 UITableView / UIScrollView 完整内容的 UIImage 并使其在 ios 设备上工作

    我正在使用这段非常优雅的代码获取 UIScrollView 的屏幕截图 包括屏幕外部分 https stackoverflow com questions 3539717 getting a screenshot of a uiscroll
  • 调用 popToRootViewControllerAnimated 时未调用 viewWillDisappear

    我从事遗留应用程序的工作 并发现我的view Will Did Disappear方法并不总是被正确触发 情况是 我有一个 自定义 UIViewController在 AppDelegate 中设置为 rootViewController
  • 如何让 CAAnimation 在每个动画周期调用一个块?

    我可以以某种方式在 CAAnimation 的每个 tick 上执行一个块吗 它可能像下面的代码一样工作 如果有办法用选择器来做到这一点 那也是可行的 NSString keyPath position x CGFloat endValue
  • Xcode 8 - 删除了一些按钮边框

    我刚刚将 Xcode 版本从 7 3 更新到 8 0 一些按钮边框消失了 代码看起来很好 所以我真的不知道各层发生了什么 顺便说一句 在其他一些控制器中我可以看到图层边框 self button layer borderColor bord
  • Xcode 6 Launchscreen.xib 具有适用于 iPad 横向和纵​​向的不同资源

    使用 Xcode 6 中引入的 LaunchScreen 我可以定义用于 iPad 横向和纵 向的不同资源吗 由于两个 iPad 方向的特征是相同的 遗憾的是 顺便说一句 我无法区分两者 这是否意味着 要么对 iPad 横向和纵 向使用相同
  • 标签栏不显示图标?

    我读了一堆相关的问题 我尝试了他们所说的 但没有任何效果 不知道为什么 所以 我有3个不同的UIStoryboards 第一个是处理登录 注册的 Auth Storyboard 并且有一个对第二个 Storyboard 选项卡栏 Story

随机推荐

  • C# 将字符串“0”解析为整数

    我有一台新笔记本电脑在工作 本周早些时候运行的代码今天不起作用 之前工作的代码经过简化 while dr Read int i int Parse dr GetString 1 现在 当数据库值为 0 时 它会失败 有时 但不可靠 这会起作
  • 使用 pandas 创建矩阵结构

    我已将包含代码和系数数据的以下 CSV 文件加载到以下数据框 df 中 CODE COEFFICIENT A 0 5 B 0 4 C 0 3 import pandas as pd import numpy as np df pd read
  • PHP 中的 A* 搜索算法 [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 有没有人有实施A 算法在 PHP 中 我知道维基百科有一个伪代码和一个 C 伪代码的链接 但我似乎找不到已经用 PHP 编写的伪代码 我也在寻找一种高效的书面 A 算法 None
  • 理解java 8流的过滤方法

    我最近了解到StreamJava 8 中的 s 并看到了这个示例 IntStream stream IntStream range 1 20 现在 假设我们想要找到第一个既能被 3 又能被 5 整除的数字 我们可能会filter两次并且fi
  • 具有特定类型的 Backbone.Js 集合

    我有一个名为 History 的 BackboneJS 集合 它可以包含多个 Backbone JS 模型之一 从 HistoryItem 扩展 而 HistoryItem 又从 Backbone Model 扩展 我试图找到一种在加载时重
  • 身份“iPhone Developer”与钥匙串中任何有效、未过期的证书/私钥对不匹配

    我想在设备中测试我的应用程序 但我被这个错误困扰了几个小时 身份 iPhone Developer 与钥匙串中任何有效 未过期的证书 私钥对不匹配 我已经关注了本指南 我在 stackoverflow 上搜索了类似的问题 这可能会有所帮助
  • 检查颜色是否为蓝色(ish)、红色(ish)、绿色(ish)、

    我想实现一个可以按颜色过滤图像的搜索 我的图像模型最多包含该特定图像中出现的 10 个 UIColor 现在我想要一个过滤器 例如蓝色 绿色 红色 黄色 如何检查 使用指定的容差 该特定图像是否包含蓝色 绿色 我尝试使用 CIE94 差异
  • 如何破译 boost asio ssl 错误代码?

    我在 boost asio ssl 实现中偶尔会出现通信失败 boost 返回的超级有用的错误消息是 asio ssl 336458004 我怀疑数字是由 SSL 标志组成的某种聚合构造 我说因为 linux 错误代码 boost asio
  • 从 FileSystemWatcher 错误中恢复的最佳实践是什么?

    After a FileSystemWatcher Error事件被提出 我不知道下一步该做什么 该例外可以是 相对 较小的例外 例如 目录中一次更改太多 这不会影响观察者的观看过程 但它也可能是一个大问题 例如观看的目录被删除 在这种情况
  • 如何以编程方式设置可发现时间而无需用户确认?

    我通常用这个 private void ensureDiscoverable if D Log d TAG ensure discoverable if mBluetoothAdapter getScanMode BluetoothAdap
  • 不使用 Android 导航抽屉显示叠加层

    我想知道是否可以删除最近实现的导航抽屉所做的自动覆盖 第二张图的灰色层 你只需要设置setScrimColor int color 给你的DrawerLayout mDrawerLayout setScrimColor Color WHIT
  • postgresql:共享内存不足?

    我正在使用 Python 和 psycopg2 运行大量查询 我创建了一个包含约 200 万行的大型临时表 然后使用以下命令一次从中获取 1000 行cur fetchmany 1000 并运行涉及这些行的更广泛的查询 不过 广泛的查询是自
  • 如何使用 StoreKit 2 进行恢复?

    iOS 15 引入了 StoreKit 2 我正在研究它 看看是否可以在我现有的应用程序中采用它 但我不知道该怎么做 特别是 我不知道如何实现所需的恢复功能 例如 如果用户删除了我的应用程序 我想我们应该使用Transaction late
  • 当我向 Firebase 实时数据库添加新值时如何保存当前日期/时间

    当我通过控制面板向 Firebase 实时数据库添加新值时 我想将当前日期 时间保存在特定字段中 我怎样才能做到这一点 请帮我 Answer recommended by Google Cloud Collective 最佳实践是将数据保存
  • JSP/JSTL 中的嵌套表达式

    我使用 JSP 作为视图 使用 Spring MVC 3 0 作为控制器 在我的 JSP 中 我想显示当前的日期时间 为此我有以下代码
  • Linux 内核模块字符设备权限

    是否可以在以 mod 666 启动的 Linux 内核模块中创建字符设备 现在它总是 600 由 root 拥有 我必须 chmod 它 我可以创建 udev 条目来解决它 但我真的宁愿模块自动执行它 是否可以 我在 cdev init 或
  • 异步/等待返回 Promise { } [重复]

    这个问题在这里已经有答案了 我的问题是 尽管我使用了 async await 为什么这个日志还是 promise pending 我检查了类似的问题和答案 看起来应该没问题 但事实并非如此 我该如何改变它才能得到结果 为什么 谢谢 cons
  • 带有 CloudFront 的区域 API 网关

    亚马逊发布新功能 支持区域 API 端点 这是否意味着我可以在两个区域部署相同的 API 代码 并向 Lambda 微服务发送请求 这将是两个不同的 Https 端点 CloudFront 是否为我分配流量 有代码片段吗 这是否意味着我可以
  • DART HTTP 服务器中带有 SSL 证书的 HTTPS

    Dart HTTP 服务器支持 HTTPS 吗 如果是这样 您如何指定证书 如果没有 是否有其他替代方案 例如社区创建的包 是的 Dart 支持 https 查看文档here和一个测试here 相关线路 HttpServer bindSec
  • 为图层属性设置动画以简单地更改其他属性?

    想象一个CAGradientLayer 制作动画非常容易 startPoint and endPoint 现在想象一个漂浮物spinLike这只是同时设置它们 因此 您可以简单地制作动画 而不是使用两个不同的动画spinLike 所以像 c