如何动态修改CSS的height样式?Angular用户排行榜开发问询
To dynamically set the height of your progress bar based on user points, you'll need to calculate a percentage relative to the maximum points in your leaderboard, then bind that percentage to the element's height style using Angular's property binding. Here's how to implement it:
Step 1: Calculate Maximum Points (Component Class)
First, derive the maximum points value from your sortedUsers$ observable. This gives us a reference point to compute each user's relative progress:
import { Component } from '@angular/core'; import { Observable, map } from 'rxjs'; // Define your User interface if you haven't already interface User { id: number; imgUrl: string; points: number; // Add other user properties as needed } @Component({ selector: 'app-leaderboard', templateUrl: './leaderboard.component.html', styleUrls: ['./leaderboard.component.css'] }) export class LeaderboardComponent { sortedUsers$: Observable<User[]>; // Your existing observable of sorted users // Create a derived observable for maximum points maxPoints$: Observable<number> = this.sortedUsers$.pipe( map(users => { if (!users.length) return 0; return Math.max(...users.map(user => user.points)); }) ); }
Step 2: Bind Dynamic Height in the Template
Use Angular's [style.height.%] property binding to set the height based on the percentage of max points each user has. We wrap the list in an ng-container to handle the async pipe for max points efficiently:
<div class="user"> <ng-container *ngIf="maxPoints$ | async as maxPoints"> <ul id="jogadores" *ngFor="let u of sortedUsers$ | async; let i=index;" (click)="routeToUser(u.id)"> <li class="user"> <img class="gravatar" src="https://www.gravatar.com/avatar/{{u.imgUrl}}?d=https://www.1plusx.com/app/mu-plugins/all-in-one-seo-pack-pro/images/default-user-image.png" /> <div class="progressBar"> <!-- Calculate percentage and bind to height --> <span [style.height.%]="maxPoints > 0 ? (u.points / maxPoints) * 100 : 0"> <i></i> <b>{{u.points}}</b> </span> <!-- ... rest of your progress bar content --> </div> </li> </ul> </ng-container> </div>
Alternative: Precompute Percentages in Component
If you prefer to avoid template calculations (for performance or clarity), precompute the percentage for each user in a combined observable:
// In your component class usersWithProgress$: Observable<Array<User & { progressPercent: number }>> = this.sortedUsers$.pipe( map(users => { const maxPoints = users.length ? Math.max(...users.map(u => u.points)) : 0; return users.map(user => ({ ...user, progressPercent: maxPoints > 0 ? (user.points / maxPoints) * 100 : 0 })); }) );
Then in the template:
<div class="user"> <ul id="jogadores" *ngFor="let u of usersWithProgress$ | async; let i=index;" (click)="routeToUser(u.id)"> <li class="user"> <img class="gravatar" src="https://www.gravatar.com/avatar/{{u.imgUrl}}?d=https://www.1plusx.com/app/mu-plugins/all-in-one-seo-pack-pro/images/default-user-image.png" /> <div class="progressBar"> <span [style.height.%]="u.progressPercent"> <i></i> <b>{{u.points}}</b> </span> <!-- ... rest of your content --> </div> </li> </ul> </div>
Key Notes
- Division by Zero Handling: We check if
maxPointsis greater than 0 before calculating the percentage to avoid errors when there are no users or all users have 0 points. - Dynamic Updates: Since we're using observables, any changes to
sortedUsers$will automatically trigger recalculation of max points and progress percentages, keeping your heights up-to-date. - Unit Binding: Using
[style.height.%]automatically appends the percentage unit, so you just need to pass the numeric percentage value.
内容的提问来源于stack exchange,提问作者user122222

