SwiftUI 极简实现文本摆动弹性动画

news2024/12/22 23:02:53

在这里插入图片描述

概览

SwiftUI 为我们来了界面设计和调试上的便利,只需几行代码我们就能实现一个不错的文本动画效果:

在这里插入图片描述

如上图所示,我们在 SwiftUI 中基本还没发力,就实现了文本摆动弹性动画。

这究竟是怎么做到的呢?

无需等待,Let‘s go!!! 😉


小小的推动

SwiftUI 中实现如上动画效果有很多种方法,比如:我们可以用状态改变驱动视图修改器的不同实参去产生动画效果。

我们也可以用文本的变体去实现类似的动画。

这里,我们混合使用它们来共同完成动画!

基本原则是:我们用 AttributedString 来设置文本的通用动画属性,而用 SwiftUI 视图修改器来实现文本的其它动画特性。

从 iOS 15.0(SwiftUI 3.0) 开始,Text 构造器开始支持 AttributedString 形参,我们可以直接创建 AttributedString 值并传入 Text 视图:

在这里插入图片描述

首先,在主视图加入动画所需的状态:

struct ContentView: View {
    // 动画的启动状态
    @State var anim = false
    // 摆动的幅度
    @State var range = 5.0

    var body: some View {...}
}

接着,在主视图中构建一个 message 计算属性,不出意外它的类型是 AttributedString:

var message: AttributedString {
    let string = "The letters go up and down"
    var result = AttributedString()

    for (index, letter) in string.enumerated() {
        var letterString = AttributedString(String(letter))
        // 利用一丢丢数学知识来计算文字上下偏移的位置
        letterString.baselineOffset = sin(Double(index)) * range * (anim ? -1 : 1)
        result += letterString
    }

    result.font = anim ? .largeTitle.weight(.black) : .largeTitle
    result.foregroundColor = anim ? .red : .orange

    return result
}

现在,我们可以把 message 放入 body 中的文本视图中了:

var body: some View {
        
    VStack(spacing: 50) {
        
        Spacer()
        
        Text(message)
        
        Spacer()
        
        HStack {
            Text(verbatim: "幅度:\(String(format: "%.1f", range))")
                .font(.title.weight(.bold))
            Slider(value: $range, in: 1.0...50)
        }
        .padding(.horizontal)
        
        Button("动画吧!"){
            withAnimation(.easeInOut.repeatForever(autoreverses: true)) {
                anim.toggle()
            }
        }
        // 省略无关外观代码...
    }
}

运行看一下效果:

在这里插入图片描述

还不错,不是吗?😃

美化

欲穷千里目,更上一层楼,我们还可以在 SwiftUI 环境中进一步来优化动画显示。

别忘了,任何状态的改变在 SwiftUI 中都可以获得免费的动画效果,所以结合 message 已有的动画属性,我们可以利用修改器让文本动画更加生动:

Text(message)
    .rotationEffect(anim ? .degrees(11) : .degrees(-11))
    .fixedSize(horizontal: false, vertical: true)
    .kerning(anim ? 1.7 : 0)
    .brightness(anim ? 0.1 : 0.0)
    .shadow(radius: 3.0)

如上代码所示,我们为 message 文本增加了诸多可动画修改器。最后,让我们再来观赏一下最终的成果吧:

在这里插入图片描述

至此,我们仅用很少的努力就实现了博文开头的动画效果,是不是觉得很赞呢?👍🏻💯

全部源代码

struct ContentView: View {
    
    @State var anim = false
    @State var range = 5.0
    
    var message: AttributedString {
        let string = "The letters go up and down"
        var result = AttributedString()

        for (index, letter) in string.enumerated() {
            var letterString = AttributedString(String(letter))
            letterString.baselineOffset = sin(Double(index)) * range * (anim ? -1 : 1)
            result += letterString
        }

        result.font = anim ? .largeTitle.weight(.black) : .largeTitle
        result.foregroundColor = anim ? .red : .orange

        return result
    }

    var body: some View {
        
        VStack(spacing: 50) {
            
            Spacer()
            
            Text(message)
                .rotationEffect(anim ? .degrees(11) : .degrees(-11))
                .fixedSize(horizontal: false, vertical: true)
                .kerning(anim ? 1.7 : 0)
                .brightness(anim ? 0.1 : 0.0)
                .foregroundStyle(.thickMaterial)
                .shadow(radius: anim ? 5.0 : 3.0)
    
            Spacer()
            
            HStack {
                Text(verbatim: "幅度:\(String(format: "%.1f", range))")
                    .font(.title.weight(.bold))
                Slider(value: $range, in: 1.0...50)
            }
            .padding(.horizontal)
            
            Button("动画吧!"){
                withAnimation(.easeInOut.repeatForever(autoreverses: true)) {
                    anim.toggle()
                }
            }
            .font(.largeTitle.weight(.bold))
            .foregroundStyle(.white.gradient)
            .padding()
            .padding(.horizontal)
            .background(.blue.gradient)
            .cornerRadius(7.0)
        }
    }
}

总结

在本篇博文中,我们充分发挥了 SwiftUI 框架简洁、富有描述性的威力,仅用几行代码就实现了一个不错的文本摆动弹性动画,而且可以自由调整参数实现各种变化。

更多 SwiftUI 中文本属性的操作和动画效果,请轻点如下链接观赏:

超详细:SwiftUI文本排版布局和动态字体缩放的奥秘

感谢观赏,再会!😎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/491186.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

英文论文(sci)解读复现【NO.7】基于注意机制的改进YOLOv5s目标检测算法

此前出了目标检测算法改进专栏,但是对于应用于什么场景,需要什么改进方法对应与自己的应用场景有效果,并且多少改进点能发什么水平的文章,为解决大家的困惑,此系列文章旨在给大家解读发表高水平学术期刊中的 SCI论文&a…

Loadrunner性能测试(一)

备注:电脑最好安装有IE浏览器 一、下载安装包 链接:https://pan.baidu.com/s/1f5Sw0QK5zrLCU1EbN01evg?pwdbite 提取码:bite 包含的文件有: 二、安装loadrunner 注意,以下教程仅展示需要特别注意的步骤&#x…

PHP学习笔记第一天

前言 作者简介:不知名白帽,网络安全学习者。 博客主页:不知名白帽的博客_CSDN博客-网络安全,CTF,内网渗透领域博主 网络安全交流社区:https://bbs.csdn.net/forums/angluoanquan 目录 PHP语法 基本的PHP语法 PHP的数据类型 PH…

Kubernetes 集群中某个节点出现 Error querying BIRD: unable to connect to BIRDv4 socket

1. 问题描述 Readiness probe failed: calico/node is not ready: BIRD is not ready: Error querying BIRD: unable to connect to BIRDv4 socket: dial unix /var/run/calico/bird.ctl: connect: connection refusedReadiness probe failed: 2023-05-04 22:13:23.706 [INFO]…

LiangGaRy-学习笔记-Day10

1、知识回顾 1.1、rpm依赖报错问题 rpm安装的时候,会有依赖报错rpm安装httpd服务,体现报错 #rpm安装httpd [rootNode1 ~]# rpm -ivh /mnt/cdrom/Packages/httpd-2.4.6-88.el7.centos.x86_64.rpm warning: /mnt/cdrom/Packages/httpd-2.4.6-88.el7.ce…

自己组装的电脑怎么用U盘安装系统操作教学

自己组装的电脑怎么用U盘安装系统操作教学分享。有的用户使用台式机的时候,会自己去进行硬件的组装,但是这样的电脑在安装好了之后,里面还没有系统,需要进行安装。如果你不知道怎么去安装,可以来看看以下的操作方法。 …

HummerRisk 使用教程:源码检测

HummerRisk 是开源的云原生安全平台,以非侵入的方式解决云原生环境的安全和治理问题。核心能力包括混合云的安全治理和云原生安全检测。 本文将介绍HummerRisk中「源码检测模块」的功能,包括如何配置项目源码,以及使用源码检测规则进行安全检…

香港top5功能完善炒期货投资app软件排名(最新评测)

选择一款合适的炒期货投资软件对于投资者来说至关重要。考虑软件稳定、交易流畅度、交易品种、数据可靠性、而且还要考虑费用等多方面因素。 首先,软件的稳定性很重要。选用稳定性高的软件可以避免如断电、手机或电脑死机等突发状况,保证交易安全顺畅。…

FreeRTOS 低功耗 Tickless 模式

文章目录 一、低功耗模式1. 睡眠(Sleep)模式2. 停止(Stop)模式3. 待机(Standby)模式 二、Tickless 模式详解1. 如何降低功耗?2. Tickless 具体实现 一、低功耗模式 STM32 本身就支持低功耗模式,有三种低功耗模式: ● 睡眠(Sleep)模式。 ● 停…

5_服务编排_docker-compose

服务编排之Docker Compose 微服务架构的应用系统中一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,维护的工作量会很大。 要从Dockerfile build image 或者去dockerhub拉取image 要创建多个container 要…

GB/T25915.1法规基本标准-洁净室按粒子浓度划分洁净

《GB/T25915.1-2021洁净室及相关受控环境 第一部分:按粒子浓度划分空气洁净度等级》等4部国家标准。 今天小编跟大家分享一下参编的GB/T25915.1-2021相关法规文件内容,帮助大家更好的了解相关法规知识。 1 范围 本文件规定了按空气中悬浮粒子浓度划分洁…

9:00进去,9:05就出来了,这问的也太···

从外包出来,没想到死在另一家厂子了。 自从加入这家公司,每天都在加班,钱倒是给的不少,所以也就忍了。没想到8月一纸通知,所有人不许加班,薪资直降30%,顿时有吃不起饭的赶脚。 好在有个兄弟内推…

纯前端 根据目录解析word,拆分不同段落

前期回顾 两分钟学会 制作自己的浏览器 —— 并将 ChatGPT 接入_0.活在风浪里的博客-CSDN博客自定义浏览器,并集合ChatGPT,源码已公开https://blog.csdn.net/m0_57904695/article/details/130467253?spm1001.2014.3001.5501 👍 本文专栏…

Unity之OpenXR+XR Interaction Toolkit实现 监听VR手柄按键

一.前言 当我们接入XR Interaction Toolkit之后,我们可以很方便的做不同VR设备的适配,这在很大程度上提升了我们的开发效率,我们除了通过射线和物体交互之外,偶尔我们也会希望监听手柄上的部分按键的点击事件,今天我们…

网络安全大厂面试题合集

以下为网络安全各个方向涉及的面试题合集,星数越多代表问题出现的几率越大,祝各位都能找到满意的工作。 注:本套面试题,已整理成pdf文档,但内容还在持续更新中,因为无论如何都不可能覆盖所有的面试问题&…

国考省考结构化面试:情景模拟题的答题思路,人际关系题的变种,就题答题,灵活多变,关键在自己多思考,说话要有艺术

国考省考结构化面试:情景模拟题的答题思路,人际关系题的变种,就题答题,灵活多变,关键在自己多思考,说话要有艺术 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能,附带…

ansible常用模块总结

目录 一、 assert模块 二、 authorized_key模块 三、at模块 四、blockinfile模块 五、command模块 六、copy模块 七、 cron模块 八、 firewalld模块 九、 fail模块 十、 file模块 十一、 fetch模块 十二、filesystem模块 十三、 get_url模块 十四、group模块 十…

基于pytorch+transformers的车牌识别

目录 程序流程设计熟悉训练数据集CCPD2019数据集CCPD数据集标注信息单例再现 加载本地车牌数据集 程序流程设计 1,熟悉训练数据集; 2,加载本地车牌数据集; 3,定义网络模型; 4,输入数据集训练模…

关于复杂事件处理和事件驱动架构的争论

复杂事件处理(Complex Event Processing,CEP)系统和事件驱动架构(Event Driven Architecture,EDA)都被认为会在目前和未来的精致繁杂的系统设计中扮演重要角色。但是它们的角色是什么?会对业界产…

初识vue-模板

目录 模板语法 模板插值 指令 条件渲染(v-if ;v-show) 列表循环(v-for) ref JSX(render渲染) 条件渲染 列表渲染 八皇后框架-背景格(循环) 模板语法 Vue.js使用了…