找回密码
 立即注册
首页 业界区 业界 鸿蒙特效教程01-哔哩哔哩点赞与一键三连效果实现教程 ...

鸿蒙特效教程01-哔哩哔哩点赞与一键三连效果实现教程

雨角 2025-6-2 00:28:44
鸿蒙特效教程01-哔哩哔哩点赞与一键三连效果实现教程

本教程适合HarmonyOS初学者,通过简单到复杂的步骤,一步步实现类似哔哩哔哩APP中的点赞及一键三连效果。
开发环境准备


  • DevEco Studio 5.0.3
  • HarmonyOS Next API 15
最终效果预览

我们将实现以下两个效果:

  • 点击点赞按钮:实现点赞/取消点赞的切换效果,包含图标变色和缩放动画
  • 长按点赞按钮:实现一键三连效果,包含旋转、缩放和粒子动画
1.gif

一、基础布局实现

首先,我们需要创建基本的界面布局。这一步非常简单,只需要放置一个点赞图标。
  1. @Entry
  2. @Component
  3. struct BilibiliLike {
  4.   build() {
  5.     // 使用Stack布局,使元素居中对齐
  6.     Stack({ alignContent: Alignment.Center }) {
  7.       // 点赞图标
  8.       Image($r('app.media.ic_public_like'))
  9.         .width(50) // 设置图标宽度
  10.         .aspectRatio(1) // 保持宽高比为1:1
  11.         .objectFit(ImageFit.Contain) // 设置图片适应方式
  12.     }
  13.     .width('100%') // 容器占满宽度
  14.     .height('100%') // 容器占满高度
  15.     .backgroundColor('#f1f1f1') // 设置背景颜色为浅灰色
  16.   }
  17. }
复制代码
这一步实现了最基础的布局,我们使用了Stack布局使元素居中,并添加了一个点赞图标。点赞图标大家可以去 iconfont.cn 平台下载一个,通过 $() 函数导入资源$r('app.media.ic_public_like')。
二、添加状态和颜色切换

接下来,我们添加状态变量来跟踪点赞状态,并实现点击时的颜色切换效果。
  1. @Entry
  2. @Component
  3. struct BilibiliLike {
  4.   // 是否已点赞状态
  5.   @State isLiked: boolean = false
  6.   // 未点赞时的颜色(灰色)
  7.   @State unlikeColor: string = '#757575'
  8.   // 点赞后的颜色(蓝色)
  9.   @State likeColor: string = '#4eabe6'
  10.   build() {
  11.     Stack({ alignContent: Alignment.Center }) {
  12.       Image($r('app.media.ic_public_like'))
  13.         .width(50)
  14.         .aspectRatio(1)
  15.         .objectFit(ImageFit.Contain)
  16.         .fillColor(this.isLiked ? this.likeColor : this.unlikeColor) // 根据点赞状态设置颜色
  17.         .onClick(() => {
  18.           // 点击时切换点赞状态
  19.           this.isLiked = !this.isLiked
  20.         })
  21.     }
  22.     .width('100%')
  23.     .height('100%')
  24.     .backgroundColor('#f1f1f1')
  25.   }
  26. }
复制代码
这一步我们添加了:

  • isLiked 状态变量,用于跟踪是否已点赞
  • 两个颜色变量 unlikeColor 和 likeColor
  • 在图标上添加 fillColor 属性,根据点赞状态切换颜色
  • 为图标添加 onClick 事件,实现点击时切换点赞状态
现在点击图标时,图标会在灰色和蓝色之间切换,实现了基本的点赞/取消点赞效果。
三、添加点击动画效果

点击时的颜色变化已经实现了,但用户体验还不够好。我们需要添加一些动画效果,让点赞操作更加生动。
  1. @Entry
  2. @Component
  3. struct BilibiliLike {
  4.   @State isLiked: boolean = false
  5.   @State unlikeColor: string = '#757575'
  6.   @State likeColor: string = '#4eabe6'
  7.   // 添加控制缩放的状态变量
  8.   @State scaleValue: number = 1
  9.   build() {
  10.     Stack({ alignContent: Alignment.Center }) {
  11.       Image($r('app.media.ic_public_like'))
  12.         .width(50)
  13.         .aspectRatio(1)
  14.         .objectFit(ImageFit.Contain)
  15.         .fillColor(this.isLiked ? this.likeColor : this.unlikeColor)
  16.         .scale({ x: this.scaleValue, y: this.scaleValue }) // 添加缩放效果
  17.         .onClick(() => {
  18.           this.toggleLike() // 调用点赞切换方法
  19.         })
  20.     }
  21.     .width('100%')
  22.     .height('100%')
  23.     .backgroundColor('#f1f1f1')
  24.   }
  25.   // 处理点赞动画效果
  26.   toggleLike() {
  27.     // 切换点赞状态
  28.     this.isLiked = !this.isLiked
  29.     // 点赞动画 - 第一阶段:放大
  30.     animateTo({
  31.       duration: 300, // 动画持续300毫秒
  32.       curve: Curve.Friction, // 使用摩擦曲线,效果更自然
  33.       delay: 0 // 无延迟立即执行
  34.     }, () => {
  35.       this.scaleValue = 1.5 // 图标放大到1.5倍
  36.     })
  37.     // 点赞动画 - 第二阶段:恢复原大小
  38.     animateTo({
  39.       duration: 100, // 动画持续100毫秒
  40.       curve: Curve.Friction, // 使用摩擦曲线
  41.       delay: 300 // 延迟300毫秒执行,等第一阶段完成
  42.     }, () => {
  43.       this.scaleValue = 1 // 图标恢复到原始大小
  44.     })
  45.   }
  46. }
复制代码
这一步我们添加了:

  • scaleValue 状态变量,用于控制图标的缩放比例
  • 图标添加 scale 属性,绑定到 scaleValue 状态
  • 创建了 toggleLike 方法,实现点赞状态切换和动画效果
  • 使用 animateTo 方法创建两段动画:先放大,再恢复原大小
现在点击图标时,不仅会变色,还会有一个放大再缩小的动画效果,让交互更加生动。
四、添加长按手势识别

接下来,我们要实现长按触发一键三连的功能,首先需要添加长按手势识别。
  1. @Entry
  2. @Component
  3. struct BilibiliLike {
  4.   @State isLiked: boolean = false
  5.   @State unlikeColor: string = '#757575'
  6.   @State likeColor: string = '#4eabe6'
  7.   @State scaleValue: number = 1
  8.   // 添加一个标记三连效果的状态
  9.   @State isTripleAction: boolean = false
  10.   build() {
  11.     Stack({ alignContent: Alignment.Center }) {
  12.       Image($r('app.media.ic_public_like'))
  13.         .width(50)
  14.         .aspectRatio(1)
  15.         .objectFit(ImageFit.Contain)
  16.         .fillColor(this.isLiked ? this.likeColor : this.unlikeColor)
  17.         .scale({ x: this.scaleValue, y: this.scaleValue })
  18.         .draggable(false) // 防止用户拖拽图片,导致点赞按钮无法长按
  19.         // 添加长按手势
  20.         .gesture(
  21.           LongPressGesture({ repeat: false }) // 长按手势,不重复触发
  22.             .onAction(() => {
  23.               console.info("检测到长按事件")
  24.               // 设置状态
  25.               this.isTripleAction = true
  26.               this.isLiked = true
  27.             })
  28.         )
  29.         .onClick(() => {
  30.           this.toggleLike()
  31.         })
  32.     }
  33.     .width('100%')
  34.     .height('100%')
  35.     .backgroundColor('#f1f1f1')
  36.   }
  37.   // 点赞动画方法保持不变
  38.   toggleLike() {
  39.     // 代码同上...
  40.   }
  41. }
复制代码
这一步我们添加了:

  • isTripleAction 状态变量,用于标记是否触发了一键三连效果
  • 使用 gesture 方法添加长按手势识别
  • 在长按触发时设置相关状态
  • 注意图片添加 draggable(false),防止用户拖拽图片,导致点赞按钮无法长按
现在,长按图标后,会将点赞状态设为已点赞,并触发三连状态,但还没有具体的动画效果。
五、添加长按动画效果

下一步,我们为长按添加更丰富的动画效果,包括旋转和缩放。
  1. @Entry
  2. @Component
  3. struct BilibiliLike {
  4.   @State isLiked: boolean = false
  5.   @State isTripleAction: boolean = false
  6.   @State scaleValue: number = 1
  7.   @State unlikeColor: string = '#757575'
  8.   @State likeColor: string = '#4eabe6'
  9.   // 添加旋转角度状态
  10.   @State rotation: number = 0
  11.   build() {
  12.     Stack({ alignContent: Alignment.Center }) {
  13.       Image($r('app.media.ic_public_like'))
  14.         .width(50)
  15.         .aspectRatio(1)
  16.         .objectFit(ImageFit.Contain)
  17.         .fillColor(this.isLiked ? this.likeColor : this.unlikeColor)
  18.         .scale({ x: this.scaleValue, y: this.scaleValue })
  19.         .rotate({ z: 1, angle: this.rotation }) // 添加旋转效果
  20.         .draggable(false)
  21.         .gesture(
  22.           LongPressGesture({ repeat: false })
  23.             .onAction(() => {
  24.               this.triggerTripleAction() // 调用三连效果方法
  25.             })
  26.         )
  27.         .onClick(() => {
  28.           this.toggleLike()
  29.         })
  30.     }
  31.     .width('100%')
  32.     .height('100%')
  33.     .backgroundColor('#f1f1f1')
  34.   }
  35.   // 点赞动画方法保持不变
  36.   toggleLike() {
  37.     // 代码同上...
  38.   }
  39.   // 处理一键三连动画效果
  40.   triggerTripleAction() {
  41.     // 设置三连状态和点赞状态
  42.     this.isTripleAction = true
  43.     this.isLiked = true
  44.     // 阶段一:点赞按钮放大并旋转
  45.     animateTo({
  46.       duration: 200, // 动画持续200毫秒
  47.       curve: Curve.EaseInOut // 使用缓入缓出曲线
  48.     }, () => {
  49.       this.scaleValue = 1.8 // 图标放大到1.8倍
  50.       this.rotation = 20 // 图标旋转20度
  51.     })
  52.     // 阶段二:点赞按钮缩小并恢复角度
  53.     animateTo({
  54.       duration: 100, // 动画持续100毫秒
  55.       curve: Curve.EaseInOut, // 使用缓入缓出曲线
  56.       delay: 200 // 延迟200毫秒,等阶段一完成
  57.     }, () => {
  58.       this.scaleValue = 1.2 // 图标缩小到1.2倍
  59.       this.rotation = 0 // 图标恢复原始角度
  60.     })
  61.     // 阶段三:点赞按钮恢复原始大小
  62.     animateTo({
  63.       duration: 100, // 动画持续100毫秒
  64.       curve: Curve.EaseInOut, // 使用缓入缓出曲线
  65.       delay: 300 // 延迟300毫秒,等阶段二完成
  66.     }, () => {
  67.       this.scaleValue = 1 // 图标恢复原始大小
  68.     })
  69.     // 重置三连状态
  70.     setTimeout(() => {
  71.       this.isTripleAction = false
  72.     }, 1000) // 延迟1000毫秒(1秒)执行
  73.   }
  74. }
复制代码
这一步我们添加了:

  • rotation 状态变量,用于控制图标的旋转角度
  • 图标添加 rotate 属性,实现旋转效果
  • 创建了 triggerTripleAction 方法,实现三连动画效果
  • 三段连续动画,实现放大旋转、缩小恢复的动画序列
现在,长按图标会触发一系列动画:图标先放大并顺时针旋转,然后缩小并恢复原始角度,最后恢复原始大小,整个过程非常流畅。
六、添加粒子爆炸效果

最后,我们添加粒子爆炸效果,让一键三连的视觉效果更加丰富。
  1. @Entry
  2. @Component
  3. struct BilibiliLike {
  4.   @State isLiked: boolean = false
  5.   @State isTripleAction: boolean = false
  6.   @State scaleValue: number = 1
  7.   @State rotation: number = 0
  8.   @State unlikeColor: string = '#757575'
  9.   @State likeColor: string = '#4eabe6'
  10.   // 添加粒子透明度状态
  11.   @State iconOpacity: number = 0
  12.   build() {
  13.     Stack({ alignContent: Alignment.Center }) {
  14.       // 粒子效果容器
  15.       Column() {
  16.         // 当触发三连效果时显示粒子
  17.         if (this.isTripleAction) {
  18.           // 创建8个粒子,均匀分布在圆周上
  19.           ForEach([1, 2, 3, 4, 5, 6, 7, 8], (item: number) => {
  20.             Circle()
  21.               .width(8) // 粒子宽度
  22.               .height(8) // 粒子高度
  23.               .fill(this.likeColor) // 使用点赞颜色填充粒子
  24.               // 使用三角函数计算粒子在圆周上的位置
  25.               .position({ x: 25 + 50 * Math.cos(item * Math.PI / 4), y: 25 + 50 * Math.sin(item * Math.PI / 4) })
  26.               .opacity(this.iconOpacity) // 控制粒子的透明度
  27.           })
  28.         }
  29.       }
  30.       .width(50) // 设置容器宽度
  31.       .height(50) // 设置容器高度
  32.       // 点赞按钮
  33.       Image($r('app.media.ic_public_like'))
  34.         .width(50)
  35.         .aspectRatio(1)
  36.         .objectFit(ImageFit.Contain)
  37.         .fillColor(this.isLiked ? this.likeColor : this.unlikeColor)
  38.         .scale({ x: this.scaleValue, y: this.scaleValue })
  39.         .rotate({ z: 1, angle: this.rotation })
  40.         .draggable(false)
  41.         .gesture(
  42.           LongPressGesture({ repeat: false })
  43.             .onAction(() => {
  44.               this.triggerTripleAction()
  45.             })
  46.         )
  47.         .onClick(() => {
  48.           this.toggleLike()
  49.         })
  50.     }
  51.     .width('100%')
  52.     .height('100%')
  53.     .backgroundColor('#f1f1f1')
  54.   }
  55.   // 点赞动画方法保持不变
  56.   toggleLike() {
  57.     // 代码同上...
  58.   }
  59.   // 处理一键三连动画效果
  60.   triggerTripleAction() {
  61.     // 设置三连状态和点赞状态
  62.     this.isTripleAction = true
  63.     this.isLiked = true
  64.     // 点赞按钮动画部分保持不变
  65.     // ...
  66.     // 添加粒子出现动画
  67.     animateTo({
  68.       duration: 500, // 动画持续500毫秒
  69.       curve: Curve.EaseOut, // 使用缓出曲线,开始快结束慢
  70.       delay: 200 // 延迟200毫秒执行
  71.     }, () => {
  72.       this.iconOpacity = 1 // 粒子透明度变为1,完全显示
  73.     })
  74.     // 粒子消失动画
  75.     animateTo({
  76.       duration: 300, // 动画持续300毫秒
  77.       curve: Curve.Linear, // 使用线性曲线,匀速变化
  78.       delay: 700 // 延迟700毫秒,等粒子完全显示一段时间
  79.     }, () => {
  80.       this.iconOpacity = 0 // 粒子透明度变为0,完全消失
  81.     })
  82.     // 重置三连状态
  83.     setTimeout(() => {
  84.       this.isTripleAction = false
  85.     }, 1000) // 延迟1000毫秒(1秒)执行
  86.   }
  87. }
复制代码
这一步我们添加了:

  • iconOpacity 状态变量,用于控制粒子的透明度
  • 在Stack中添加粒子效果容器
  • 使用ForEach和条件渲染,当触发三连效果时创建并显示粒子
  • 使用三角函数计算粒子在圆周上的位置
  • 添加粒子的动画效果,包括出现和消失
七、完整实现

最后,我们来看一下最终的完整代码实现。这里整合了前面所有的步骤,并添加了一些额外的细节优化。
  1. /**
  2. * 哔哩哔哩点赞和一键三连效果组件
  3. * 实现功能:
  4. * 1. 普通点击: 实现点赞/取消点赞效果
  5. * 2. 长按: 触发一键三连效果(点赞+粒子动画)
  6. */
  7. @Entry
  8. @Component
  9. struct BilibiliLike {
  10.   // 是否已点赞状态
  11.   @State isLiked: boolean = false
  12.   // 是否触发一键三连效果状态
  13.   @State isTripleAction: boolean = false
  14.   // 控制图标缩放比例
  15.   @State scaleValue: number = 1
  16.   // 控制图标透明度
  17.   @State opacityValue: number = 1
  18.   // 控制图标X轴偏移量
  19.   @State translateXValue: number = 0
  20.   // 控制图标Y轴偏移量
  21.   @State translateYValue: number = 0
  22.   // 控制图标旋转角度
  23.   @State rotation: number = 0
  24.   // 控制粒子效果透明度
  25.   @State iconOpacity: number = 0
  26.   // 未点赞时的颜色(灰色)
  27.   @State unlikeColor: string = '#757575'
  28.   // 点赞后的颜色(蓝色)
  29.   @State likeColor: string = '#4eabe6'
  30.   build() {
  31.     // 使用Stack布局,所有元素居中对齐
  32.     Stack({ alignContent: Alignment.Center }) {
  33.       // 粒子效果容器
  34.       Column() {
  35.         // 当触发三连效果时显示粒子
  36.         if (this.isTripleAction) {
  37.           // 创建8个粒子,均匀分布在圆周上
  38.           ForEach([1, 2, 3, 4, 5, 6, 7, 8], (item: number) => {
  39.             Circle()
  40.               .width(8) // 粒子宽度
  41.               .height(8) // 粒子高度
  42.               .fill(this.likeColor) // 使用点赞颜色填充粒子
  43.               // 使用三角函数计算粒子在圆周上的位置
  44.               .position({ x: 25 + 50 * Math.cos(item * Math.PI / 4), y: 25 + 50 * Math.sin(item * Math.PI / 4) })
  45.               .opacity(this.iconOpacity) // 控制粒子的透明度
  46.           })
  47.         }
  48.       }
  49.       .width(50) // 设置容器宽度
  50.       .height(50) // 设置容器高度
  51.       // 点赞按钮
  52.       Image($r('app.media.ic_public_like')) // 使用点赞图标资源
  53.         .width(50) // 设置图标宽度
  54.         .aspectRatio(1) // 保持宽高比为1:1
  55.         .objectFit(ImageFit.Contain) // 设置图片适应方式
  56.         .fillColor(this.isLiked ? this.likeColor : this.unlikeColor) // 根据点赞状态设置颜色
  57.         .scale({ x: this.scaleValue, y: this.scaleValue }) // 设置缩放值
  58.         .opacity(this.opacityValue) // 设置透明度
  59.         .rotate({ z: 1, angle: this.rotation }) // 设置旋转角度,绕z轴旋转
  60.         .translate({ x: this.translateXValue, y: this.translateYValue }) // 设置平移值
  61.         .draggable(false) // 防止用户拖拽图片,导致点赞按钮无法长按
  62.         // 添加长按手势,触发一键三连效果
  63.         .gesture(
  64.           LongPressGesture({ repeat: false }) // 长按手势,不重复触发
  65.             .onAction(() => {
  66.               this.triggerTripleAction() // 调用三连效果方法
  67.             })
  68.         )
  69.         // 添加点击事件,触发普通点赞效果
  70.         .onClick(() => {
  71.           this.toggleLike() // 调用点赞切换方法
  72.         })
  73.     }
  74.     .width('100%') // 容器占满宽度
  75.     .height('100%') // 容器占满高度
  76.     .backgroundColor('#f1f1f1') // 设置背景颜色为浅灰色
  77.     .expandSafeArea() // 扩展到安全区域
  78.   }
  79.   /**
  80.    * 处理点赞/取消点赞动画效果
  81.    * 点击时切换点赞状态并播放放大缩小动画
  82.    */
  83.   toggleLike() {
  84.     // 切换点赞状态
  85.     this.isLiked = !this.isLiked
  86.     // 点赞动画 - 第一阶段:放大
  87.     animateTo({
  88.       duration: 300, // 动画持续300毫秒
  89.       curve: Curve.Friction, // 使用摩擦曲线,效果更自然
  90.       delay: 0 // 无延迟立即执行
  91.     }, () => {
  92.       this.scaleValue = 1.5 // 图标放大到1.5倍
  93.     })
  94.     // 点赞动画 - 第二阶段:恢复原大小
  95.     animateTo({
  96.       duration: 100, // 动画持续100毫秒
  97.       curve: Curve.Friction, // 使用摩擦曲线
  98.       delay: 300 // 延迟300毫秒执行,等第一阶段完成
  99.     }, () => {
  100.       this.scaleValue = 1 // 图标恢复到原始大小
  101.     })
  102.   }
  103.   /**
  104.    * 处理一键三连动画效果
  105.    * 包含多个动画阶段:放大旋转、粒子出现与消失
  106.    */
  107.   triggerTripleAction() {
  108.     // 设置三连状态和点赞状态
  109.     this.isTripleAction = true // 启用三连效果
  110.     this.isLiked = true // 设置为已点赞状态
  111.     // 阶段一:点赞按钮放大并旋转
  112.     animateTo({
  113.       duration: 200, // 动画持续200毫秒
  114.       curve: Curve.EaseInOut // 使用缓入缓出曲线
  115.     }, () => {
  116.       this.scaleValue = 1.8 // 图标放大到1.8倍
  117.       this.rotation = 20 // 图标旋转20度
  118.     })
  119.     // 阶段二:点赞按钮缩小并恢复角度
  120.     animateTo({
  121.       duration: 100, // 动画持续100毫秒
  122.       curve: Curve.EaseInOut, // 使用缓入缓出曲线
  123.       delay: 200 // 延迟200毫秒,等阶段一完成
  124.     }, () => {
  125.       this.scaleValue = 1.2 // 图标缩小到1.2倍
  126.       this.rotation = 0 // 图标恢复原始角度
  127.     })
  128.     // 阶段三:点赞按钮恢复原始大小
  129.     animateTo({
  130.       duration: 100, // 动画持续100毫秒
  131.       curve: Curve.EaseInOut, // 使用缓入缓出曲线
  132.       delay: 300 // 延迟300毫秒,等阶段二完成
  133.     }, () => {
  134.       this.scaleValue = 1 // 图标恢复原始大小
  135.       this.isLiked = true // 确保点赞状态为true
  136.     })
  137.     // 阶段四:粒子出现动画
  138.     animateTo({
  139.       duration: 500, // 动画持续500毫秒
  140.       curve: Curve.EaseOut, // 使用缓出曲线,开始快结束慢
  141.       delay: 200 // 延迟200毫秒执行
  142.     }, () => {
  143.       this.iconOpacity = 1 // 粒子透明度变为1,完全显示
  144.     })
  145.     // 阶段五:粒子消失动画
  146.     animateTo({
  147.       duration: 300, // 动画持续300毫秒
  148.       curve: Curve.Linear, // 使用线性曲线,匀速变化
  149.       delay: 700 // 延迟700毫秒,等粒子完全显示一段时间
  150.     }, () => {
  151.       this.iconOpacity = 0 // 粒子透明度变为0,完全消失
  152.     })
  153.     // 延时重置三连状态,完成整个动画周期
  154.     setTimeout(() => {
  155.       this.isTripleAction = false // 关闭三连效果状态
  156.     }, 1000) // 延迟1000毫秒(1秒)执行
  157.   }
  158. }
复制代码
拓展与优化

以上是基本的实现,如果想进一步优化,可以考虑:

  • 添加声音效果:在点赞和三连时添加声音反馈
  • 添加震动反馈:利用设备振动提供触觉反馈
  • 优化粒子效果:使用更复杂的粒子系统,例如随机大小、颜色和速度
  • 添加投币和收藏图标:真正实现完整的"一键三连"效果,显示投币和收藏图标
总结

通过这个教程,我们从零开始实现了哔哩哔哩的点赞和一键三连效果。主要用到了以下技术:

  • HarmonyOS的ArkUI布局系统
  • 状态管理(@State)
  • 手势处理(点击、长按)
  • 动画系统(animateTo)
  • 条件渲染
  • 数学计算(用于粒子位置)
这些技术和概念不仅适用于这个特定效果,还可以应用于各种交互设计中。希望这个教程能帮助你更好地理解HarmonyOS开发,并创建出更加精美的应用界面!

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册