Angular项目足球小游戏开发求助:定时显隐与点击失效问题
解决方案
问题根源
你当前的代码用单个setInterval每10秒切换显隐,导致显示时长是10秒而非需求的5秒;同时直接用jQuery操作DOM不符合Angular的响应式理念,还会和手动点击的逻辑冲突。
修复步骤
- 用Angular变量控制显隐:放弃jQuery的
fadeIn/fadeOut,改用组件变量绑定控制元素显示状态,同时用Angular的方式处理位置和样式。 - 拆分定时器逻辑:用一个
setInterval负责每10秒触发足球出现,每次出现后用setTimeout控制5秒后自动隐藏;点击时立即清除自动隐藏的定时器并隐藏足球。 - 清理定时器避免内存泄漏:在组件销毁时清除所有定时器。
完整代码示例
组件类代码
import { Component, OnInit, OnDestroy, ElementRef, ViewChild } from '@angular/core'; @Component({ selector: 'app-football-minigame', templateUrl: './football-minigame.component.html', styleUrls: ['./football-minigame.component.css'] }) export class FootballMinigameComponent implements OnInit, OnDestroy { isFootballVisible = false; footballPosition = { left: '0px', top: '0px' }; balance = 0; userId = 1; // 替换为实际用户ID private hideTimeout: any; private showInterval: any; @ViewChild('minigameWindow') minigameWindow!: ElementRef; ngOnInit(): void { // 每10秒触发一次足球出现 this.showInterval = setInterval(() => { this.showFootball(); }, 10000); } ngOnDestroy(): void { // 清理定时器,避免内存泄漏 if (this.hideTimeout) clearTimeout(this.hideTimeout); if (this.showInterval) clearInterval(this.showInterval); } showFootball(): void { // 计算随机位置 this.placeRandomPosition(); // 显示足球 this.isFootballVisible = true; // 设置5秒后自动隐藏 this.hideTimeout = setTimeout(() => { this.hideFootball(); }, 5000); } hideFootball(): void { this.isFootballVisible = false; if (this.hideTimeout) { clearTimeout(this.hideTimeout); this.hideTimeout = null; } } onFootballClick(): void { // 立即隐藏足球 this.hideFootball(); // 添加5金币 this.addCredits(this.userId, 5); } addCredits(userId: number, amount: number): void { // 这里实现添加金币的逻辑,比如更新余额或调用API this.balance += amount; console.log(`用户${userId}余额增加${amount},当前余额:${this.balance}`); } private placeRandomPosition(): void { const windowElement = this.minigameWindow.nativeElement; const windowWidth = windowElement.offsetWidth; const windowHeight = windowElement.offsetHeight; const footballSize = 80; // 足球宽高都是80px // 计算随机位置,确保足球不会超出容器 const randomLeft = Math.floor(Math.random() * (windowWidth - footballSize)); const randomTop = Math.floor(Math.random() * (windowHeight - footballSize)); this.footballPosition = { left: `${randomLeft}px`, top: `${randomTop}px` }; } }
HTML模板代码
<div #minigameWindow id="minigame-window" class="card-body" style="height: 65vh; position: relative;"> <!-- 足球元素,用*ngIf控制显隐,绑定随机位置 --> <div *ngIf="isFootballVisible" class="football rotate90" [style.left]="footballPosition.left" [style.top]="footballPosition.top" (click)="onFootballClick()" style="position: absolute; cursor: pointer;" > <img src="assets/football-157930_640.png" class="rotate90" height="80px" width="80px"> </div> <!-- 可选:显示当前余额 --> <div>当前余额:{{ balance }}金币</div> </div>
关键说明
- 用
@ViewChild获取容器元素,避免直接用jQuery选择器,符合Angular规范。 - 每次显示足球时重新计算随机位置,确保每次出现的位置都不一样。
- 点击足球时会立即清除自动隐藏的定时器,避免后续自动隐藏逻辑触发。
- 组件销毁时清理所有定时器,防止内存泄漏。
内容的提问来源于stack exchange,提问作者mooney-jjang
相关产品推荐
相关产品推荐

