You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular组件多模板下的局部手风琴式动画实现咨询

Angular Card-Based Local Accordion Animation Solution

Hey there! Let's tackle this accordion animation for your production-grade card layout. Since you're working with Angular (given the ng-content reference), here's a maintainable, component-friendly approach that fits your existing structure:

Core Approach

We'll leverage Angular's built-in Animation module to add state-driven transitions to your Card component. The goal is to animate the internal content area (the part with ng-content) when toggling, while keeping the header and summary bottom fixed (or optionally animating them too, if needed).

Step 1: Set Up Animation Dependencies

First, make sure the Angular Animations module is imported in your root module:

// app.module.ts
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  imports: [
    BrowserAnimationsModule,
    // ... other imports
  ]
})
export class AppModule { }

Step 2: Update the Base Card Component

Modify your base Card component to include a toggle state, animation triggers, and click handling for the header.

Card Component Class (card.component.ts)

import { Component, Input } from '@angular/core';
import { trigger, state, style, animate, transition } from '@angular/animations';

@Component({
  selector: 'app-card',
  templateUrl: './card.component.html',
  styleUrls: ['./card.component.css'],
  animations: [
    trigger('accordionAnimation', [
      state('expanded', style({
        height: '*',
        opacity: 1,
        overflow: 'visible'
      })),
      state('collapsed', style({
        height: '0',
        opacity: 0,
        overflow: 'hidden'
      })),
      transition('expanded <=> collapsed', animate('300ms ease-in-out'))
    ])
  ]
})
export class CardComponent {
  @Input() isExpanded = true; // Default to expanded
  @Input() headerTitle: string;
  @Input() summaryText: string;

  toggleExpansion(): void {
    this.isExpanded = !this.isExpanded;
  }
}

Card Template (card.component.html)

<div class="card-container">
  <!-- Card Header (toggle trigger) -->
  <div class="card-header" (click)="toggleExpansion()" role="button" [attr.aria-expanded]="isExpanded">
    <h3>{{ headerTitle }}</h3>
    <span class="toggle-icon">{{ isExpanded ? '▼' : '▶' }}</span>
  </div>

  <!-- Animated Internal Content -->
  <div class="card-content" [@accordionAnimation]="isExpanded ? 'expanded' : 'collapsed'">
    <ng-content></ng-content>
  </div>

  <!-- Card Summary Bottom -->
  <div class="card-footer">
    <p>{{ summaryText }}</p>
  </div>
</div>

Card Styles (card.component.css)

.card-container {
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  margin: 1rem 0;
  overflow: hidden;
}

.card-header {
  padding: 1rem;
  background-color: #f5f5f5;
  display: flex;
  justify-content: space-between;
  align-items: center;
  cursor: pointer;
}

.card-content {
  padding: 0 1rem; /* Adjust padding to avoid jump on toggle */
}

.card-footer {
  padding: 1rem;
  background-color: #fafafa;
  border-top: 1px solid #e0e0e0;
}

.toggle-icon {
  font-size: 1.2rem;
}

Step 3: Reuse with Child Components

Since you have two child components inheriting from the base Card, they can directly leverage the animation without extra work. Here's an example for a Chart Card:

// chart-card.component.ts
import { Component, Input } from '@angular/core';
import { CardComponent } from '../card/card.component';

@Component({
  selector: 'app-chart-card',
  templateUrl: './chart-card.component.html',
  styleUrls: ['./chart-card.component.css']
})
export class ChartCardComponent extends CardComponent {
  @Input() chartData: any[]; // Child-specific input
}
<!-- chart-card.component.html -->
<app-card [headerTitle]="'Sales Overview'" [summaryText]="'Total: $12,450'">
  <!-- Your chart component here -->
  <app-line-chart [data]="chartData"></app-line-chart>
</app-card>

Key Optimizations & Customizations

  • Adjust Animation Behavior: Modify the animate() parameters (e.g., '500ms ease-out') to match your app's design system.
  • Animate Footer Too: If you want the summary footer to slide with the content, move it inside the animated card-content div or add a separate trigger for it.
  • Accessibility: We added role="button" and aria-expanded attributes to make the toggle keyboard-navigable. You can also add tabindex="0" and handle keydown events for Enter/Space keys.
  • Performance: Using height transitions is straightforward, but for dynamic content, consider using max-height with a sufficiently high value (e.g., max-height: 2000px) to avoid layout jumps.

Troubleshooting Tips

  • If the animation has jumpy behavior: Ensure the card-content has no margin (use padding instead) and that the overflow: hidden is properly applied.
  • Child components not inheriting state: Make sure you're extending the base class correctly and passing inputs through to the parent component.

内容的提问来源于stack exchange,提问作者Zerok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:31:54