HarmonyOS CustomerBanner

滚动轮播图

一、项目简介

1. demo地址: https://gitee.com/hyhe/customer-banner.git

2. 项目效果图

CustomerBanner.gif

3. 使用示例

// 1. 导入头文件
import { CustomerSwiper } from './CustomerBanner/CustomerSwiper'
import { CustomerSwiperConfiguration } from './CustomerBanner/CustomerSwiperConfiguration'

@Entry
@Component
struct Index {
  // 初始化横向滚动配置项
  horizontalConfig: CustomerSwiperConfiguration = new CustomerSwiperConfiguration()
  // 初始化纵向滚动配置项
  verticalConfig: CustomerSwiperConfiguration = new CustomerSwiperConfiguration()
  
  // 更具UI设置配置项参数
  aboutToAppear() {
    this.verticalConfig.itemWidth = 300
    this.verticalConfig.itemHeight = 200
    this.verticalConfig.isHorizontal = false

    this.horizontalConfig.itemWidth = 300
    this.horizontalConfig.itemHeight = 200

  }

  build() {
    Column() {
      // 调用
      CustomerSwiper({ swiperConfig: this.verticalConfig })
        .margin({top: 100})
        .width("100%").height(300)
        .clip(true)
      CustomerSwiper({ swiperConfig: this.horizontalConfig }).width("100%").height(300).clip(true)
    }
  }
}

二、项目主要类介绍

1. 配置项类 CustomerSwiperConfiguration

export class CustomerSwiperConfiguration {
  /**
   *  isHorizontal 是否横向滚动
   *  默认: true 横向滚动
   */
  isHorizontal: boolean = true

  /**
   * 单个元素的宽度
   * */
  itemWidth: number = 300;

  /**
   * 单个元素的高度
   * */
  itemHeight: number = 100

  /**
   * 显示元素的个数
   * */
  showCount: number = 5;

  /**
   * 元素之间的间隔距离
   * */
  itemSpace: number = 10

  /**
   * 透明度系数
   * */
  opacityCoefficients: number = 0.1;

  /**
   * 偏移量系数
   * */
  offsetCoefficients: number = 20;

  /**
   * 换下一页的拖动距离
   * */
  maxMoveOffset: number = 60;

  /**
   * 元素倒角
   * */
  radius: number = 10

  /**
   * 拖动动作延时
   * */
  duration: number = 300

  /**
   * 自动滚动延时
   * */
  animationDuration: number = 3000
}

2. 滚动轮播类 CustomerSwiper

  1. 主要计算方法
// 计算初始化元素距离页面展示元素的偏移量
getImgCoefficients(index?: number): number {
    if (index === undefined) {
      return 0;
    }
    let coefficient = this.aheadIndex - index;
    let tempCoefficient = Math.abs(coefficient);
    if (tempCoefficient <= this.halfCount) {
      return coefficient;
    }
    let dataLength = this.imageList.length;
    let tempOffset = dataLength - tempCoefficient;
    if (tempOffset <= this.halfCount) {
      if (coefficient > 0) {
        return -tempOffset;
      }
      return tempOffset;
    }
    return 0;
  }

  // 计算纵向滚动时元素的纵向偏移量 
  getOffSetY(index?: number): number {
    if (index === undefined) {
      return 0;
    }
    let offsetIndex = this.getImgCoefficients(index);
    let tempOffset = Math.abs(offsetIndex);
    let offsetY = this.marginBottom / (tempOffset + 1);
    if (tempOffset === 1) {
      offsetY += -offsetIndex * this.swiperConfig.itemHeight - this.swiperConfig.itemSpace;
    } else {
      offsetY += -offsetIndex * this.swiperConfig.itemHeight - this.swiperConfig.itemSpace;
    }
    return offsetY;
  }
  // 计算横向滚动时元素的纵向偏移量 
  getOffsetX(index?: number): number {
    if (index === undefined) {
      return 0
    }
    let offsetIndex = this.getImgCoefficients(index)
    let tempOffset = Math.abs(offsetIndex)
    let offsetX = this.marginRight / (tempOffset + 1)
    if (tempOffset === 1) {
      offsetX += -(offsetIndex * this.swiperConfig.itemWidth + this.swiperConfig.itemSpace)
    } else {
      offsetX += -offsetX * this.swiperConfig.itemWidth - this.swiperConfig.itemSpace
    }
    return offsetX
  }
  // 计算每一个元素的宽度
  getItemWidth(index?: number): number {
    return index !== this.aheadIndex && this.getImgCoefficients(index) === 0
      ? this.swiperConfig.itemWidth
      : this.swiperConfig.itemWidth - this.swiperConfig.offsetCoefficients * Math.abs(this.getImgCoefficients(index))
  }
  1. 拖拽手势代码
 // 添加滑动手势
 PanGesture({ direction: this.swiperConfig.isHorizontal ? PanDirection.Horizontal : PanDirection.Vertical })
        .onActionStart((event: GestureEvent | undefined) => {
          if (!event) {
            return;
          }
          this.clearTiming()
          this.changedIndex = false;
          this.handlePanGesture(this.swiperConfig.isHorizontal ? event.offsetX : event.offsetY);
        })
        .onActionUpdate((event: GestureEvent | undefined) => {
          if (!event) {
            return;
          }
          this.handlePanGesture(this.swiperConfig.isHorizontal ? event.offsetX : event.offsetY);
        })
        .onActionEnd(() => {
          animateTo({
            duration: this.swiperConfig.duration,
          }, () => {
            this.swiperConfig.isHorizontal ? this.marginRight = 0 : this.marginBottom = 0;
            this.second = this.aheadIndex
            this.startTiming()
          });
        })
  1. 拖拽动作处理
// 根据滑动偏移量offset处理是否要切换下一页
handlePanGesture(offset: number): void {
    if (Math.abs(offset) < this.swiperConfig.maxMoveOffset) {
      this.marginBottom = offset;
    } else {
      if (this.changedIndex) {
        return;
      }
      this.changedIndex = true;
      this.startAnimation(offset < 0);
    }
  }

  // 进行切换
  startAnimation(isUp: boolean): void {
    animateTo({
      duration: this.swiperConfig.duration,
    }, () => {
      let dataLength = this.imageList.length;
      let tempIndex = isUp ? this.aheadIndex + 1 : dataLength + this.aheadIndex - 1;
      this.aheadIndex = tempIndex % dataLength;
      this.marginBottom = 0;
    });
  }
  1. 时间计时器处理
// 开始启动时间计时器并切换页面
startTiming() {
    this.timer = setInterval(() => {
      this.second++;
      if (this.second === this.imageList.length) {
        this.second = 0
      }
      this.startAnimation(true)
    }, this.swiperConfig.animationDuration);
  }

  // 销毁计时器
  clearTiming() {
    if (this.timer !== -1) {
      clearInterval(this.timer);
      this.timer = -1;
    }
  }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 用到的组件 1、通过CocoaPods安装 2、第三方类库安装 3、第三方服务 友盟社会化分享组件 友盟用户反馈 ...
    SunnyLeong阅读 14,598评论 1 180
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,680评论 2 59
  • 一、启动项目 1. 安装脚手架和依赖 首先保证你的电脑上有node和npm,版本越新越好 npm install...
    在路上919阅读 929评论 0 2
  • 项目流程: 多区域轮播多区域列表循环展示根据不同城市展示不同景点 城市展示,城市搜索城市右侧字母与左侧城市联动效果...
  • 由于简书没有目录的功能,为了更加清晰的学习,我制作了一个目录地址如下:学习Vue目录 链接地址: https:/...
    读书的鱼阅读 10,051评论 13 249