下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。
1. 基础点赞功能实现
1.1 创建数据模型
// VideoModel.ets
export class VideoModel {
id: string = "";
title: string = "";
author: string = "";
coverUrl: string = "";
videoUrl: string = "";
likes: number = 0;
isLiked: boolean = false;
comments: number = 0;
shares: number = 0;
}
1.2 点赞按钮组件
// LikeButton.ets
@Component
export struct LikeButton {
@Prop video: VideoModel;
@State private isAnimating: boolean = false;
build() {
Column() {
// 点赞按钮
Image(this.video.isLiked ? $r('app.media.ic_liked') : $r('app.media.ic_like'))
.width(40)
.height(40)
.scale({ x: this.isAnimating ? 1.2 : 1, y: this.isAnimating ? 1.2 : 1 })
.animation({ duration: 200, curve: Curve.EaseInOut })
.onClick(() => {
this.handleLike();
})
// 点赞数
Text(this.video.likes.toString())
.fontSize(14)
.fontColor(Color.White)
.margin({ top: 4 })
}
.alignItems(HorizontalAlign.Center)
}
private handleLike() {
// 触发动画
this.isAnimating = true;
setTimeout(() => {
this.isAnimating = false;
}, 200);
// 更新点赞状态
this.video.isLiked = !this.video.isLiked;
this.video.likes += this.video.isLiked ? 1 : -1;
// 这里可以添加网络请求,同步点赞状态到服务器
this.syncLikeStatus();
}
private syncLikeStatus() {
// 实际项目中这里应该调用API同步点赞状态
console.log(`视频${this.video.id}点赞状态: ${this.video.isLiked}`);
}
}
2. 双击点赞功能实现
2.1 视频组件封装
// VideoPlayer.ets
@Component
export struct VideoPlayer {
@Prop video: VideoModel;
@State private showLikeAnimation: boolean = false;
private lastTapTime: number = 0;
build() {
Stack() {
// 视频播放器
Video({
src: this.video.videoUrl,
controller: new VideoController()
})
.width('100%')
.height('100%')
.objectFit(ImageFit.Cover)
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Down) {
this.handleTap();
}
})
// 点赞动画
if (this.showLikeAnimation) {
Image($r('app.media.ic_liked'))
.width(80)
.height(80)
.position({ x: '50%', y: '50%' })
.scale({ x: 0, y: 0 })
.opacity(1)
.animation({
duration: 1000,
curve: Curve.EaseOut,
onFinish: () => {
this.showLikeAnimation = false;
}
})
.scale({ x: 1.5, y: 1.5 })
.opacity(0)
}
// 右侧互动栏
Column() {
LikeButton({ video: this.video })
.margin({ bottom: 20 })
// 其他互动按钮(评论、分享等)...
}
.position({ x: '85%', y: '50%' })
}
.width('100%')
.height('100%')
}
private handleTap() {
const currentTime = new Date().getTime();
const timeDiff = currentTime - this.lastTapTime;
if (timeDiff < 300) { // 双击判定
if (!this.video.isLiked) {
this.video.isLiked = true;
this.video.likes += 1;
this.showLikeAnimation = true;
this.syncLikeStatus();
}
}
this.lastTapTime = currentTime;
}
private syncLikeStatus() {
// 同步点赞状态到服务器
console.log(`视频${this.video.id}通过双击点赞`);
}
}
3. 点赞动画优化
3.1 粒子爆炸效果
// ParticleLikeAnimation.ets
@Component
export struct ParticleLikeAnimation {
@State private particles: { id: number, x: number, y: number, scale: number, opacity: number }[] = [];
private particleCount: number = 12;
build() {
Stack() {
ForEach(this.particles, (particle) => {
Image($r('app.media.ic_liked'))
.width(20)
.height(20)
.position({ x: `${particle.x}%`, y: `${particle.y}%` })
.scale({ x: particle.scale, y: particle.scale })
.opacity(particle.opacity)
})
}
}
public startAnimation() {
this.particles = [];
// 生成粒子
for (let i = 0; i < this.particleCount; i++) {
this.particles.push({
id: i,
x: 50,
y: 50,
scale: 0,
opacity: 1
});
}
// 动画效果
this.particles.forEach((particle, index) => {
const angle = (index * (360 / this.particleCount)) * (Math.PI / 180);
const distance = 15 + Math.random() * 10;
setTimeout(() => {
particle.x = 50 + Math.cos(angle) * distance;
particle.y = 50 + Math.sin(angle) * distance;
particle.scale = 0.5 + Math.random() * 0.5;
particle.opacity = 0;
}, index * 50);
});
setTimeout(() => {
this.particles = [];
}, 1000);
}
}
3.2 在VideoPlayer中使用粒子动画
// 修改VideoPlayer.ets
@Component
export struct VideoPlayer {
@State private particleAnimRef: ParticleLikeAnimation | null = null;
build() {
Stack() {
// ...其他组件
// 替换原来的点赞动画
ParticleLikeAnimation({ ref: this.particleAnimRef })
// ...其他组件
}
}
private handleTap() {
const currentTime = new Date().getTime();
const timeDiff = currentTime - this.lastTapTime;
if (timeDiff < 300) { // 双击判定
if (!this.video.isLiked) {
this.video.isLiked = true;
this.video.likes += 1;
this.particleAnimRef?.startAnimation();
this.syncLikeStatus();
}
}
this.lastTapTime = currentTime;
}
}
4. 数据持久化与同步
4.1 使用分布式数据服务
// LikeService.ets
import distributedData from '@ohos.data.distributedData';
export class LikeService {
private kvManager: distributedData.KVManager;
private kvStore: distributedData.KVStore;
async init() {
const config = {
bundleName: 'com.example.douyin',
userInfo: {
userId: 'currentUser',
userType: distributedData.UserType.SAME_USER_ID
}
};
this.kvManager = distributedData.createKVManager(config);
const options = {
createIfMissing: true,
encrypt: false,
backup: false,
autoSync: true,
kvStoreType: distributedData.KVStoreType.SINGLE_VERSION
};
this.kvStore = await this.kvManager.getKVStore('likes_store', options);
}
async syncLike(videoId: string, isLiked: boolean) {
if (!this.kvStore) {
await this.init();
}
try {
await this.kvStore.put(videoId, isLiked);
await this.kvStore.sync({
deviceIds: ['all'],
mode: distributedData.SyncMode.PUSH
});
} catch (error) {
console.error('同步点赞状态失败:', JSON.stringify(error));
}
}
async getLikeStatus(videoId: string): Promise<boolean> {
if (!this.kvStore) {
await this.init();
}
try {
const result = await this.kvStore.get(videoId);
return !!result;
} catch (error) {
console.error('获取点赞状态失败:', JSON.stringify(error));
return false;
}
}
}
4.2 在LikeButton中集成数据服务
// 修改LikeButton.ets
@Component
export struct LikeButton {
private likeService: LikeService = new LikeService();
aboutToAppear() {
this.loadLikeStatus();
}
private async loadLikeStatus() {
const isLiked = await this.likeService.getLikeStatus(this.video.id);
this.video.isLiked = isLiked;
}
private async syncLikeStatus() {
await this.likeService.syncLike(this.video.id, this.video.isLiked);
}
}
5. 完整视频页面实现
// DouyinPage.ets
@Entry
@Component
struct DouyinPage {
@State currentVideoIndex: number = 0;
@State videos: VideoModel[] = [
{
id: "1",
title: "第一个视频",
author: "创作者1",
coverUrl: "resources/cover1.jpg",
videoUrl: "resources/video1.mp4",
likes: 1234,
isLiked: false,
comments: 56,
shares: 12
},
// 更多视频...
];
build() {
Stack() {
// 视频滑动容器
Swiper() {
ForEach(this.videos, (video: VideoModel) => {
SwiperItem() {
VideoPlayer({ video: video })
}
})
}
.index(this.currentVideoIndex)
.autoPlay(false)
.indicator(false)
.loop(false)
.vertical(true)
.edgeEffect(EdgeEffect.Spring)
.onChange((index: number) => {
this.currentVideoIndex = index;
})
// 顶部导航
Row() {
Text("推荐")
.fontSize(18)
.fontColor(Color.White)
.margin({ left: 20 })
// 其他导航项...
}
.width('100%')
.height(50)
.position({ x: 0, y: 30 })
}
.width('100%')
.height('100%')
.backgroundColor(Color.Black)
}
}
6. 实际项目注意事项
-
性能优化:
- 使用LazyForEach加载视频列表
- 视频预加载机制
- 动画使用硬件加速
-
网络请求:
- 实现点赞API接口
- 添加请求重试机制
- 处理网络异常情况
-
用户体验:
- 添加加载状态指示器
- 实现点赞操作的防抖处理
- 离线状态下的点赞处理
-
安全考虑:
- 点赞操作的身份验证
- 防止重复点赞
- 数据加密传输
-
测试要点:
- 双击手势的灵敏度测试
- 动画性能测试
- 多设备同步测试
-
扩展功能:
- 点赞列表查看
- 点赞通知功能
- 热门点赞视频推荐
通过以上实现,你可以在HarmonyOS 5应用中创建类似抖音的点赞功能,包括基础点赞、双击点赞、动画效果和数据同步等核心功能。