HarmonyOS Next系列之实现一个左右露出中间大两边小带缩放动画的轮播图(十二)

news2024/11/25 16:18:18

系列文章目录

HarmonyOS Next 系列之省市区弹窗选择器实现(一)
HarmonyOS Next 系列之验证码输入组件实现(二)
HarmonyOS Next 系列之底部标签栏TabBar实现(三)
HarmonyOS Next 系列之HTTP请求封装和Token持久化存储(四)
HarmonyOS Next 系列之从手机选择图片或拍照上传功能实现(五)
HarmonyOS Next 系列之可移动悬浮按钮实现(六)
HarmonyOS Next 系列之沉浸式状态实现的多种方式(七)
HarmonyOS Next系列之Echarts图表组件(折线图、柱状图、饼图等)实现(八)
HarmonyOS Next系列之地图组件(Map Kit)使用(九)
HarmonyOS Next系列之半圆环进度条实现(十)
HarmonyOS Next 系列之列表下拉刷新和触底加载更多数据实现(十一)
HarmonyOS Next系列之实现一个左右露出中间大两边小带缩放动画的轮播图(十二)


文章目录

  • 系列文章目录
  • 前言
  • 一、实现原理
  • 二、Swiper组件使用回顾
    • 1、入参
    • 2、常用属性
      • index
      • autoPlay
      • interval
      • loop
      • itemSpace
      • prevMargin
      • nextMargin
      • DotIndicator
    • 3.常用事件
      • onChange
    • 4、事件customContentTransition
      • SwiperContentAnimatedTransition内置属性:
      • SwiperContentTransitionProxy内置属性
    • 完整代码:


前言

HarmonyOS Next(基于API12)实现一个左右露出中间大两边小带缩放动画的轮播图。

请添加图片描述


一、实现原理

难点解析:通过轮播图自定义动画属性customContentTransition,在滑动切换页面过程中根据回调参数获取页面相对选中页的起始位置移动比例,动态设置图片缩放比例。

二、Swiper组件使用回顾

1、入参

唯一入参(controller?: SwiperController)轮播图控制器,通过控制器可以控制翻页

private swiperController: SwiperController = new SwiperController()
......
.....
//控制翻到下一页
 this.swiperController.showNext()

//控制翻到上一页
 this.swiperController.showPrevious()
 ......
 ......
 build{
   Swiper(this.swiperController) {
      ......
      ......
  }
}

2、常用属性

index

设置当前在容器中显示的子组件的索引值。支持$$双向绑定变量

autoPlay

设置子组件是否自动播放。默认false

interval

设置使用自动播放时播放的时间间隔,默认3000ms

loop

设置是否开启循环,也即播放最后一张完后会自动回到第一张。,默认true

itemSpace

设置子组件与子组件之间间隙,默认0,单位vp

prevMargin

设置前边距,用于露出前一项的一小部分,默认0,单位vp

nextMargin

设置后边距,用于露出后一项的一小部分,默认0,单位vp

DotIndicator

圆点指示器属性,继承自Indicator,constructor()构造器
eg:

Swiper(){}
 .indicator( // 设置圆点导航点样式
        new DotIndicator()
          .itemWidth(15)//圆点宽
          .itemHeight(15)//圆点高
          .selectedItemWidth(15)//选中圆点宽
          .selectedItemHeight(15)//选中圆点高
          .color(Color.Gray)//圆点颜色
          .selectedColor(Color.Blue)//选中圆点颜色
          )

3.常用事件

onChange

onChange(event: (index: number) => void)
当前显示的子组件索引变化时触发该事件,返回值为当前显示的子组件的索引值


通过上面属性很容易实现一个左右露出的轮播图
示例代码如下:

@Entry
@Component
struct Index {
  @State currentIndex: number = 0//当前显示索引
  controller: SwiperController = new SwiperController()//控制器
  //图片
  imageList: string[] = ['https://img0.baidu.com/it/u=891057047,2511666354&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=667',
    'https://img2.baidu.com/it/u=2162972920,3759823780&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=664',
    'https://img1.baidu.com/it/u=1377826580,1094847210&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=750',
    'https://img2.baidu.com/it/u=3233674257,3277114296&fm=253&fmt=auto&app=120&f=JPEG?w=667&h=500',
    'https://img0.baidu.com/it/u=3948329438,2482580265&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=1082'
  ]



  build() {
    Column() {
      Swiper(this.controller) {
        ForEach(this.imageList, (item: string, index: number) => {
          Image(item).draggable(false).height(200).borderRadius(10)
        }, (index: number) => index.toString())
      }
      .width('100%')
      .autoPlay(true)//自动播放
      .itemSpace(20)//每张图片之间间距
      .prevMargin(30)//前一张图片露出宽度
      .nextMargin(30)//后一张图片露出宽度
      .indicator(new DotIndicator().color(Color.Gray).selectedColor(Color.White)) //指示器样式
      .onChange((index:number) => {
        //切换图片监听
        this.currentIndex = index
      })

    }
    .width('100%')
    .height('100%')
    .padding({top:10})
  }
}


运行效果:
请添加图片描述


4、事件customContentTransition

customContentTransition(transition: SwiperContentAnimatedTransition)
自定义Swiper页面切换动画,也是本次实现切换缩放动画轮播图的关键事件,
在轮播滑动切换过程中,在视窗内(可视区域)所有页面逐帧触发回调

SwiperContentAnimatedTransition内置属性:

名称说明
timeoutSwiper自定义切换动画超时时间,默认0,单位ms
transition自定义切换动画具体内容,类型Callback < SwiperContentTransitionProxy>

SwiperContentTransitionProxy内置属性

名称说明
selectedIndex当前选中索引
index轮播图索引
positionindex页面相对于(selectedIndex对应页面的起始位置)的移动比例。
mainAxisLengthindex对应页面在主轴方向上的长度

说明:触发事件的条件是出现可视区域内的图片都会逐张触发,例如从索引为0图片切换到索引为1过程,0和1两张图片都会出现在可视区域内,所以2张图片都会触发该事件,该事件会随着移动比例变化而多次触发直到图片移出可视区域。
position:表示当前页面相对选中页面(selectedIndex对应页面)的移动比例,啥意思呢,通过打印数据来理解:

示例:

Swiper(this.controller) {
        ForEach(this.imageList, (item: string, index: number) => {
          Image(item).draggable(false).height(200).borderRadius(10)
        }, (index: number) => index.toString())
      }
      .width('100%')
      .autoPlay(false)//自动播放
      .indicator(new DotIndicator().color(Color.Gray).selectedColor(Color.White)) //指示器样式
      .onChange((index:number) => {
        //切换图片监听
        this.currentIndex = index
      })
      .customContentTransition({
        timeout:1000,
        //自定义动画
        transition:(proxy: SwiperContentTransitionProxy)=>{
         if(proxy.index===0){
         //打印第一张的position值变化情况
           console.log(proxy.position.toString(),'position')
         }
        }
      })

测试:
(1)从第一张切换到第二张过程(向左滑)观察第一张图片postition值变化:
请添加图片描述

在这里插入图片描述
可以看到这个过程 position值趋近0到-1变化,
在开始滑动那一刻,selectedIndex为0也即第一张自己,自己和自己初始位置移动比例为0,所以position开始值为0。
滑动完成那一刻,selectedIndex为1也即第二张图片,自己和下一张图片(selectedIndex为1图片)距离为图片本身宽度,这个比例为1,因为是往左滑动所以比例为负数也即-1。index在selectedIndedx左边为负数,右边为正数

(2)从第二张切换到第一张过程(向右滑)第一张图片postition值变化:
请添加图片描述

在这里插入图片描述
可以看到这个过程index为0(第一张图片)的 position值趋近-1到0变化,(也就是上一步逆过程)。

观察第二张情况:

(1)从第一张切换到第二张过程(向左滑)观察第二张图片postition值变化:
在这里插入图片描述
趋近从1到0变化过程

(2)从第二张切换到第一张过程(向右滑)第一张图片postition值变化:
在这里插入图片描述
趋近从0到1变化过程


总结:图片在最中间position=0,往两边趋近-1和1,左负右正,取绝对值就是形成1-0-1顺序。

我们想要实现的轮播图效果缩放比例刚好相反,中间图片缩放比例1,两边比较小假设0.8,形成图片缩放顺序0.8-1-0.8

很容易得出移动过程中图片缩放比例计算公式为: 1-0.2*Math.abs( position)

完整代码:

@Entry
@Component
struct Index {
  //图表实例
  @State currentIndex: number = 0
  controller: SwiperController = new SwiperController()
  imageList: string[] = [
    'https://img0.baidu.com/it/u=891057047,2511666354&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=667',
    'https://img2.baidu.com/it/u=2162972920,3759823780&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=664',
    'https://img1.baidu.com/it/u=1377826580,1094847210&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=750',
    'https://img2.baidu.com/it/u=3233674257,3277114296&fm=253&fmt=auto&app=120&f=JPEG?w=667&h=500',
    'https://img0.baidu.com/it/u=3948329438,2482580265&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=1082'
  ]
  @State scaleList: number[] = [] //所有图片缩放比
  @State imgMargin: number = 30 //左右图片露出宽度
  @State itemSpace: number = 25 //每张图表间距
  private scaleRatio = 0.75 //缩放系数,其他图片比例和最中间选中图片比例

  aboutToAppear(): void {
    this.scaleList = this.imageList.map((item: string, index: number) => {
      //初始化时候第二张和最后一张设置缩小,loop为true时候最后一张会在初始化的最左边显示
      return index === 1 || index === this.imageList.length - 1 ? this.scaleRatio : 1
    })
  }

  build() {
    Column() {
      Swiper(this.controller) {
        ForEach(this.imageList, (item: string, index: number) => {
          Image(item).draggable(false).height(300).scale({
            y: this.scaleList[index],
          }).borderRadius(10)
        }, (index: number) => index.toString())
      }
      .width('100%')
      .autoPlay(true)
      .index(this.currentIndex)
      .itemSpace(this.itemSpace)
      .prevMargin(this.imgMargin)
      .nextMargin(this.imgMargin)
      .indicator(new DotIndicator().color(Color.Gray).selectedColor(Color.White))
      .customContentTransition({//自定义动画
        timeout: 1000,
        transition: (proxy: SwiperContentTransitionProxy) => {
          let scale= 1 - Math.min(Math.max(Math.abs(proxy.position), 0), 1) * (1 - this.scaleRatio)
          this.scaleList[proxy.index] = scale

        }
      })
      .onChange((i) => this.currentIndex = i)

    }
    .width('100%')
    .height('100%')
    .padding({ top: 10 })
  }
}

运行效果:
请添加图片描述

说明:定义一个数组参数scaleList保存每张图片缩放比例,滑动过程通过动态计算更新对应图片缩放比例,首次渲染,两边缩小的图片分别对应第二张和最后一张,初始渲染需设置好2张缩放后的比例。为了itemSpace设置的精准性,这边只设置了图片y方向(高度)的缩放,在缩放比例不是很大情况下看不出图片变形。当然也可以根据实际需要设置x方向也缩放,设置完两张图片间隙会比 itemSpace大些因为图片宽度被缩放,往图片中心变小,间隙就变大。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2118044.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ASP.NET Core 中间件

一、什么是中间件&#xff1f; 中间件 是一种装配到 ASP.NET Core 应用程序请求处理管道中的软件组件&#xff0c;用于处理 HTTP 请求和响应。 每个中间件组件可以&#xff1a; 选择是否将请求传递到下一个中间件&#xff1a;通过调用 next() 或者不调用 next() 来决定是否将…

HTML5中的数据存储sessionStorage、localStorage

第8章 HTML5中的数据存储 之前通常使用Cookie存储机制将数据保存在用户的客户端。 H5增加了两种全新的数据存储方式&#xff1a;Web Stroage和Web SQL Database. 前者用于临时或永久保存客户端少量数据&#xff0c;后者是客户端本地化的一套数据库系统。 8.1 Web Storage存…

日本“大米荒”持续!政府再次拒绝投放储备米

KlipC报道&#xff1a;日本多地从7月开始出现“大米荒”&#xff0c;有部分新米上市&#xff0c;但是许多超市的大米仍然存在断购或限购的情况&#xff0c;并且部分新米价格上涨至去年同期的两倍。大阪府官员再次呼吁日本中央政府尽快投放储备米以缓解供应紧张&#xff0c;但遭…

Dynamics CRM Ribbon Workbench-the solution contains non-entity components

今天在一个低版本的环境里准备用Ribbon Workbench去编辑一个按钮时&#xff0c;遇到了如下错误 一开始没当回事&#xff0c;以为是我的解决方案问题&#xff0c;去检查了下&#xff0c;只有一个组件&#xff0c;并且哪怕我把组件换成了某个实体也不行&#xff0c;尝试了其他任何…

开源NAS系统-OpenMediaVault(OMV)共享存储网盘搭建和使用(保姆级教程)

1、OpenMediaVault简介 OpenMediaVault,简称:OMV,是由原 FreeNAS 核心开发成员 Volker Theile 发起的基于 Debian Linux 的开源 NAS 操作系统,主要面向家庭用户和小型办公环境。 OpenMediaVault是一款基于Debian Linux的开源网络附加存储(NAS)操作系统,它提供了强大的存…

酒店智能轻触开关:智慧化的创新实践

在追求高品质住宿体验的今天&#xff0c;酒店智能轻触开关作为智慧酒店建设的关键一环&#xff0c;正逐步成为提升酒店服务品质、优化运营效率、增强顾客满意度的有力工具。本文将深入探讨酒店智能轻触开关如何助力酒店实现智慧化管理&#xff0c;以及它所带来的多重变革。 一、…

大模型时代下,nlp初学者需要怎么入门?

前言 自从 ChatGPT 横空出世以来&#xff0c;自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09;研究领域就出现了一种消极的声音&#xff0c;认为大模型技术导致 NLP “死了”。 有人认为 NLP 的市场肯定有&#xff0c;但 NLP 的研究会遇到麻…

图片产生3D模型

HyperHuman 上传图片&#xff0c;点击生成 可以多生成几次&#xff0c;点击应用 让效果再好一点 生成完成之后可以导出为fbx格式

实战|等保2.0 Oracle数据库测评过程

以下等保测评过程以Oracle 11g为例&#xff0c;通过PL/SQL进行管理&#xff0c;未进行任何配置、按照等保2.0标准&#xff0c;2021报告模板&#xff0c;三级系统要求进行测评。 一、身份鉴别 a) 应对登录的用户进行身份标识和鉴别&#xff0c;身份标识具有唯一性&#xff0c;…

E212: Can‘t open file for writing

如图 1. 查看当前用户的用户名和所属组 如果你只想查看当前登录用户的用户名和所属组&#xff0c;可以使用以下命令&#xff1a; whoami groups 检查文件和目录权限&#xff1a; ls -ld /private/var/log/wyhy ls -l /private/var/log/wyhy/market.log 修改文件权限&#…

RAKsmart美国大带宽服务器租用体验怎么样?

RAKsmart是一家提供全球服务器租用服务的知名供应商&#xff0c;其在美国的服务器产品种类多样&#xff0c;包括大带宽服务器、多IP站群服务器以及高防御服务器等&#xff0c;以适应不同业务的需求。rak小编为您整理发布。 下面是对RAKsmart美国大带宽服务器租用的具体介绍&…

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

随机分类,保持均衡水平Python

1、目的&#xff1a; 10000个样本有4个指标&#xff0c;按照逾期金额分10类&#xff0c;确保每类别逾期金额均衡。 2、数据&#xff1a; 3、思路&#xff1a; 将10000个样本按照逾期金额排序&#xff0c; 等距分箱为2500个类别 增加一列随机数 根据类别和随机数升序排列 增加…

MCU6.用keil新建项目

1.新建项目 打开keil4 2.选择单片机的类型 STC并没有出现在其中,但兼容8051芯片,选Atmel的AT89C51或AT89C52均可 本文选AT89C52 弹出的窗口点否 3.查看项目 4.新建文件 5.保存文件 6.将文件添加到工程 双击Source Group 1 点击Add 7.添加已有的工程 如果要添加已有的工程 8…

Java并发编程实战 09 | 为什么需要

什么是守护线程&#xff1f; 守护线程&#xff08;Daemon Thread&#xff09;是Java中的一种特殊线程&#xff0c;那么相对于普通线程它有什么特别之处呢&#xff1f; 在了解守护线程之前&#xff0c;我们先来思考一个问题&#xff1a;JVM在什么情况下会正常退出&#xff1f;…

腾讯公众号种类这么多,为什么小程序能脱颖而出

在微信公众平台中&#xff0c;公众号和小程序是两种不同的功能实体&#xff0c;它们各自承担着不同的角色和使命。然而&#xff0c;随着小程序的崛起&#xff0c;它在众多功能中逐渐脱颖而出&#xff0c;成为商家和开发者的新宠。具体分析如下&#xff1a; 技术优势与用户体验 …

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤&#xff08;UserCF&#xff09;2. 基于物品的协同过滤&#xff08;ItemCF&#xff09;3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过…

顶点照明渲染路径

1. 顶点照明渲染路径处理光照的方式 基本思想就是所有的光都按照逐顶点的方式进行计算的&#xff0c;在内置渲染管线中&#xff0c;它只会最多记录8个光源的数据&#xff0c;只会将光相关的数据填充到那些逐顶点相关的内置光源变量 顶点照明渲染路径仅仅是前向渲染路径的一个…

Mybatis-PlusDruid数据源

一、Mybatis-Plus简介 &#xff08;一&#xff09;什么是Mybatis-Plus Mybatis-Plus是一个Mybatis&#xff08;OPENS NEW WINDOW&#xff09;的增强工具&#xff0c;在Mybatis的基础上只做增强不做改变&#xff0c;为简化开发。 &#xff08;二&#xff09;Mybatis-Plus的优…

C语言之头文件,预处理命令#include

0 为什么要添加头文件&#xff1f;为什么要使用头文件&#xff1f; 可以看下下面图片左边&#xff0c;是不使用头文件&#xff0c;假设我们为了实现某些功能&#xff0c;编写的函数&#xff0c;全部声明在主函数之前&#xff0c;写几个函数还行&#xff0c;如果是大型项目&…