当前位置: 首页 > article >正文

angular轮播图

说明:我计划用angular实现一个轮播图的效果,必须设置图片切换动画,图片自动轮播,设置轮播的间隔时间,然后还有两个按钮 收到控制图片的上一页,下一页的切换
效果图:
在这里插入图片描述

step1: C:\Users\Administrator\WebstormProjects\untitled4\src\app\banner\banner.component.ts

import { Component , Input, OnInit, OnDestroy, OnChanges, SimpleChanges} from '@angular/core';
import { trigger, transition, style, animate, state } from '@angular/animations';
import {NgForOf, NgIf} from '@angular/common';

@Component({
  selector: 'app-banner',
  imports: [
    NgForOf,
    NgIf
  ],
  templateUrl: './banner.component.html',
  styleUrl: './banner.component.css',
  animations: [
    trigger('slide', [
      state('void', style({ opacity: 0 })),
      transition('void => *', [
        style({ transform: 'translateX(100%)', opacity: 0 }),
        animate('600ms cubic-bezier(0.25, 0.8, 0.25, 1)',
          style({ transform: 'translateX(0)', opacity: 1 }))
      ]),
      transition('* => void', [
        animate('600ms cubic-bezier(0.25, 0.8, 0.25, 1)',
          style({ transform: 'translateX(-100%)', opacity: 0 }))
      ])
    ])
  ]
})
export class BannerComponent implements OnInit, OnDestroy, OnChanges  {
  @Input() images: string[] = [];
  currentIndex = 0;
  autoPlayInterval: any;
  isDragging = false;
  startX = 0;
  threshold = 50;
  defaultImages = [
    'https://randomuser.me/api/portraits/men/1.jpg',
    'https://randomuser.me/api/portraits/men/2.jpg',
    'https://randomuser.me/api/portraits/men/3.jpg',
    'https://randomuser.me/api/portraits/men/4.jpg',
    'https://randomuser.me/api/portraits/men/5.jpg',
    'https://randomuser.me/api/portraits/men/6.jpg'
  ];

  ngOnInit() {
    this.initImages();
    this.startAutoPlay();
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes['images']) {
      this.initImages();
    }
  }

  private initImages() {
    if (this.images.length === 0) {
      this.images = [...this.defaultImages];
    }
  }

  ngOnDestroy() {
    clearInterval(this.autoPlayInterval);
  }

  startAutoPlay() {
    this.autoPlayInterval = setInterval(() => {
      this.next();
    }, 3000);
  }

  next() {
    this.currentIndex = (this.currentIndex + 1) % this.images.length;
  }

  prev() {
    this.currentIndex = (this.currentIndex - 1 + this.images.length) % this.images.length;
  }

  goTo(index: number) {
    this.currentIndex = index;
  }

  pauseAutoPlay() {
    clearInterval(this.autoPlayInterval);
  }

  resumeAutoPlay() {
    this.startAutoPlay();
  }

  onTouchStart(e: TouchEvent) {
    this.startX = e.touches[0].clientX;
    this.isDragging = true;
    this.pauseAutoPlay();
  }

  onTouchMove(e: TouchEvent) {
    if (!this.isDragging) return;
    const currentX = e.touches[0].clientX;
    const diff = this.startX - currentX;

    if (Math.abs(diff) > this.threshold) {
      diff > 0 ? this.next() : this.prev();
      this.isDragging = false;
    }
  }

  onTouchEnd() {
    this.isDragging = false;
    this.resumeAutoPlay();
  }

}

step2: C:\Users\Administrator\WebstormProjects\untitled4\src\app\banner\banner.component.html

<!-- banner.component.html -->
<div class="carousel-container"
     (mouseenter)="pauseAutoPlay()"
     (mouseleave)="resumeAutoPlay()"
     (touchstart)="onTouchStart($event)"
     (touchmove)="onTouchMove($event)"
     (touchend)="onTouchEnd()">

  <div class="slide-wrapper">
    <ng-container *ngFor="let img of images; let i = index">
      <div class="slide" @slide *ngIf="currentIndex === i"> <!-- 分离条件判断 -->
        <img [src]="img" alt="Slide {{i + 1}}">
      </div>
    </ng-container>
  </div>


  <button class="nav-btn prev-btn" (click)="prev()">
    <svg viewBox="0 0 24 24">
      <path d="M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z"/>
    </svg>
  </button>

  <button class="nav-btn next-btn" (click)="next()">
    <svg viewBox="0 0 24 24">
      <path d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"/>
    </svg>
  </button>

  <div class="indicators">
    <button *ngFor="let img of images; let i = index"
            class="indicator"
            [class.active]="i === currentIndex"
            (click)="goTo(i)">
    </button>
  </div>
</div>

step3: C:\Users\Administrator\WebstormProjects\untitled4\src\app\banner\banner.component.css

/* banner.component.css */
.carousel-container {
  position: relative;
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}

.slide-wrapper {
  position: relative;
  width: 100%;
  padding-top: 56.25%; /* 16:9 aspect ratio */
}

.slide {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.nav-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 48px;
  background: rgba(255, 255, 255, 0.9);
  border: none;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.nav-btn:hover {
  background: white;
  transform: translateY(-50%) scale(1.1);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
}

.nav-btn svg {
  width: 24px;
  height: 24px;
  fill: #2d3748;
}

.prev-btn {
  left: 20px;
}

.next-btn {
  right: 20px;
}

.indicators {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
}

.indicator {
  width: 12px;
  height: 12px;
  border: none;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.5);
  cursor: pointer;
  transition: all 0.3s ease;
}

.indicator.active {
  background: white;
  width: 24px;
}

.indicator:not(.active):hover {
  background: rgba(255, 255, 255, 0.8);
  transform: scale(1.2);
}

/* 移动端优化 */
@media (max-width: 768px) {
  .nav-btn {
    width: 36px;
    height: 36px;
  }

  .nav-btn svg {
    width: 20px;
    height: 20px;
  }

  .indicators {
    bottom: 10px;
  }

  .indicator {
    width: 8px;
    height: 8px;
  }

  .indicator.active {
    width: 16px;
  }
}

end


http://www.kler.cn/a/562940.html

相关文章:

  • git拉取远程分支到本地分支
  • 第6章 数据工程(二)
  • 【华为OD机考】华为OD笔试真题解析(14)--开心消消乐
  • ComfyUI:Stable Diffusion 及 LoRA、VAE 、ControlNet模型解析
  • 洛谷每日1题-------Day4__陶陶摘苹果
  • 免费使用SCI润色神器QuillBot
  • 软件工程----敏捷模型
  • 岳阳市美术馆预约平台(小程序论文源码调试讲解)
  • Java基础关键_012_包装类
  • WPF10绑定属性
  • 重启 nginx
  • 36. Spring Boot 2.1.3.RELEASE 中实现监控信息可视化并添加邮件报警功能
  • 动态表头导出EasyExcel
  • ExpMoveFreeHandles函数分析和备用空闲表的关系
  • python曲线回归小案例教程
  • 全球首个平行推理模型,对标Claude3.7,零延迟
  • 机试刷题_NC17 最长回文子串【python】
  • OpenAPI Generator:API开发的瑞士军刀
  • JavaEE 编写Java程序,实现简单的echo程序(网络编程TCP实践练习)
  • 解决Spring Boot中LocalDateTime返回前端数据为数组结构的问题