|
|
@@ -0,0 +1,135 @@
|
|
|
+import { Location } from "../model/AnimationModel"
|
|
|
+import image from "@ohos.multimedia.image"
|
|
|
+import { BubbleStorage } from "../model/Storage"
|
|
|
+import { AppStorageV2 } from "@kit.ArkUI"
|
|
|
+
|
|
|
+@ComponentV2
|
|
|
+export struct reagencyComp {
|
|
|
+ // 训练开始与否
|
|
|
+ @Param trainStarted: number = 0
|
|
|
+
|
|
|
+ bubbleConnect: BubbleStorage = AppStorageV2.connect(BubbleStorage, () => new BubbleStorage())!
|
|
|
+
|
|
|
+ // 点击了气泡
|
|
|
+ @Event bubbleClick: (time: number)=>void
|
|
|
+
|
|
|
+ // 气泡的数组
|
|
|
+ @Local bubbles: Array<Location> = []
|
|
|
+ @Local h: number = 0
|
|
|
+ @Local w: number = 0
|
|
|
+
|
|
|
+ timeC: number = -1
|
|
|
+
|
|
|
+ // 训练开始
|
|
|
+ @Monitor('trainStarted') startTrain() {
|
|
|
+ if(this.trainStarted == 1) {
|
|
|
+ // 这里进行气泡的重新赋值
|
|
|
+ this.bubbles.forEach(item => {
|
|
|
+ let time = new Date().getTime() - item.id!
|
|
|
+ let second = Math.max(this.bubbleConnect.bubbleDisappearTime * 1000 - item.id!, 1)
|
|
|
+ item.id = time
|
|
|
+
|
|
|
+ if(item.timer != -1) clearTimeout(item.timer)
|
|
|
+
|
|
|
+ item.timer = setTimeout(() => {
|
|
|
+ this.deleteBubble(item.id!)
|
|
|
+ }, second)
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+ this.timeC = setInterval(() => {
|
|
|
+ let location = this.generateBubbleLocation()
|
|
|
+ this.getUIContext().animateTo({ duration: 300 }, () => {
|
|
|
+ this.bubbles.push(location)
|
|
|
+ })
|
|
|
+ }, this.bubbleConnect.bubbleFrequency * 1000)
|
|
|
+ } else if (this.trainStarted == 0) {
|
|
|
+ clearInterval(this.timeC)
|
|
|
+ // 暂停不只是要暂停定时器,还要暂停气泡的消失
|
|
|
+ // 1. 将time设置为 当前花费的时间
|
|
|
+ // 2. 在再次开始时, 将 time 设置为 new Date - time
|
|
|
+ // 3. 设置的消失时间也要变化
|
|
|
+ this.bubbles.forEach(item => {
|
|
|
+ clearTimeout(item.timer)
|
|
|
+ item.timer = -1
|
|
|
+ let time = new Date().getTime() - item.id!
|
|
|
+ item.id = time
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 重置
|
|
|
+ if(this.timeC != -1) clearInterval(this.timeC)
|
|
|
+
|
|
|
+ this.bubbles.forEach(item => {
|
|
|
+ if(item.timer != -1)
|
|
|
+ clearTimeout(item.timer)
|
|
|
+ })
|
|
|
+
|
|
|
+ this.bubbles = []
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 生成气泡位置
|
|
|
+ generateBubbleLocation(): Location {
|
|
|
+ // 计算气泡的最大位置范围,避免气泡超出容器边界
|
|
|
+ const maxX = this.w - 50;
|
|
|
+ const maxY = this.h - 50;
|
|
|
+
|
|
|
+ // 生成随机坐标,确保气泡完全在可视区域内
|
|
|
+ const x = Math.random() * maxX;
|
|
|
+ const y = Math.random() * maxY;
|
|
|
+
|
|
|
+ // 创建带随机坐标的location实例
|
|
|
+ let location = new Location(x, y);
|
|
|
+
|
|
|
+ // 设置定时器,在指定时间后自动消失
|
|
|
+ location.timer = setTimeout(() => {
|
|
|
+ location.timer = -1
|
|
|
+ this.deleteBubble(location.id!);
|
|
|
+ }, this.bubbleConnect.bubbleDisappearTime * 1000); // 将秒转换为毫秒
|
|
|
+
|
|
|
+ location.id = new Date().getTime()
|
|
|
+
|
|
|
+ return location;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 删除气泡
|
|
|
+ deleteBubble(id: number, isEvent: boolean = false) {
|
|
|
+ if(this.trainStarted != 1 && isEvent == true) return
|
|
|
+
|
|
|
+ let index = this.bubbles.findIndex(item => item.id == id)
|
|
|
+ let location = this.bubbles[index]
|
|
|
+ let time = new Date().getTime() - location.id!
|
|
|
+
|
|
|
+ clearTimeout(location.timer)
|
|
|
+
|
|
|
+ this.getUIContext().animateTo({ duration: 300 }, () => {
|
|
|
+ this.bubbles.splice(index, 1)
|
|
|
+ })
|
|
|
+
|
|
|
+ if(isEvent) {
|
|
|
+ this.bubbleClick(time)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ build() {
|
|
|
+ Column() {
|
|
|
+ Repeat(this.bubbles)
|
|
|
+ .each(item => {
|
|
|
+ Image($r('app.media.icon_bubble'))
|
|
|
+ .width(50)
|
|
|
+ .aspectRatio(1)
|
|
|
+ .position({x: item.item.x, y: item.item.y})
|
|
|
+ .onClick(() => { this.deleteBubble(item.item.id!, true) })
|
|
|
+ })
|
|
|
+ .key(item => `${item.x}-${item.y}`)
|
|
|
+ }
|
|
|
+ .width("100%")
|
|
|
+ .height("100%")
|
|
|
+ .borderRadius(10)
|
|
|
+ .backgroundColor(Color.Black)
|
|
|
+ .onAreaChange((o, n) => {
|
|
|
+ this.w = n.width as number
|
|
|
+ this.h = n.height as number
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|