【Harmony】轮播图特效,持续更新中。。。。

效果预览
swiper官网例子
请添加图片描述
Swiper 高度可变化
请添加图片描述
两边等长露出,跟随手指滑动
请添加图片描述
Swiper 指示器导航点位于 Swiper 下方
请添加图片描述

一、官网 例子

请添加图片描述
参考代码:

// xxx.ets
class MyDataSource implements IDataSource {private list: number[] = []constructor(list: number[]) {this.list = list}totalCount(): number {return this.list.length}getData(index: number): number {return this.list[index]}registerDataChangeListener(listener: DataChangeListener): void {}unregisterDataChangeListener() {}
}@Entry
@Component
struct SwiperExample {private swiperController: SwiperController = new SwiperController()private data: MyDataSource = new MyDataSource([])aboutToAppear(): void {let list: number[] = []for (let i = 1; i <= 10; i++) {list.push(i);}this.data = new MyDataSource(list)}build() {Column({ space: 5 }) {Swiper(this.swiperController) {LazyForEach(this.data, (item: string) => {Text(item.toString()).width('90%').height(160).backgroundColor(0xAFEEEE).textAlign(TextAlign.Center).fontSize(30)}, (item: string) => item)}.cachedCount(2).index(1).autoPlay(true).interval(4000).indicator(Indicator.digit() // 设置数字导航点样式.right("43%").top(200).fontColor(Color.Gray).selectedFontColor(Color.Gray).digitFont({ size: 20, weight: FontWeight.Bold }).selectedDigitFont({ size: 20, weight: FontWeight.Normal })).loop(true).duration(1000).itemSpace(0).displayArrow(true, false)Row({ space: 12 }) {Button('showNext').onClick(() => {this.swiperController.showNext()})Button('showPrevious').onClick(() => {this.swiperController.showPrevious()})}.margin(5)}.width('100%').margin({ top: 5 })}
}

二、Swiper 高度可变化

请添加图片描述
主要逻辑代码:

// TODO: 知识点: Swiper组件绑定onGestureSwipe事件,在页面跟手滑动过程中,逐帧触发该回调// 性能知识点: onGestureSwipe属于频繁回调,不建议在onGestureSwipe做耗时和冗余操作.onGestureSwipe((index:number,extraInfo:SwiperAnimationEvent)=>{animateTo({duration: Constants.DURATION_SWIPER,curve: Curve.EaseOut,playMode: PlayMode.Normal,onFinish: () => {// logger.info('play end');}}, () => { // 通过左右滑动的距离来计算对应的上下位置的变化if (index === 0 && extraInfo.currentOffset < 0) {this.swiperDistance = extraInfo.currentOffset / Constants.SCROLL_WIDTH * Constants.SMALL_FONT_SIZE;} else if (index === 1 && extraInfo.currentOffset > 0) {this.swiperDistance = extraInfo.currentOffset / Constants.SCROLL_WIDTH * Constants.SMALL_FONT_SIZE - Constants.SMALL_FONT_SIZE;} else if (index === 2 && extraInfo.currentOffset < 0) {this.swiperDistance = extraInfo.currentOffset / Constants.SCROLL_WIDTH * Constants.GRID_SINGLE_HEIGHT - Constants.SMALL_FONT_SIZE;} else if (index === 3 && extraInfo.currentOffset > 0) {this.swiperDistance = extraInfo.currentOffset / Constants.SCROLL_WIDTH * Constants.GRID_SINGLE_HEIGHT - Constants.SMALL_FONT_SIZE - Constants.GRID_SINGLE_HEIGHT;}})}).onAnimationStart((_: number, targetIndex: number)=>{animateTo({duration: Constants.DURATION_DOWN_PAGE,curve: Curve.EaseOut,playMode: PlayMode.Normal,onFinish: () => {// logger.info('play end');}}, () => {if (targetIndex === 0) {this.swiperDistance = 0;} else if (targetIndex === 1 || targetIndex === 2) {this.swiperDistance = -Constants.SMALL_FONT_SIZE;} else {this.swiperDistance = -Constants.SMALL_FONT_SIZE - Constants.GRID_SINGLE_HEIGHT;}})}).indicator(new DotIndicator()// .selectedItemWidth($r('app.float.swipersmoothvariation_select_item_width')).selectedItemWidth('18fp')// .selectedItemHeight($r('app.float.swipersmoothvariation_select_item_height')).selectedItemHeight('3vp')// .itemWidth($r('app.float.swipersmoothvariation_default_item_width')).itemWidth('5vp')// .itemHeight($r('app.float.swipersmoothvariation_default_item_height')).itemHeight('-3vp')// .selectedColor($r('app.color.swipersmoothvariation_swiper_selected_color')).selectedColor(Color.Yellow)// .color($r('app.color.swipersmoothvariation_swiper_unselected_color'))).color('#FFFF8662'))

逻辑结构相对复杂,请查看下面 demo 开源地址

三、Swiper 指示器导航点位于 Swiper 下方

请添加图片描述
主要是分离内容区域和空白区域给指示器留白蛤

  Column() {Swiper(this.swiperController){// TODO 高性能知识点:此处为了演示场景,列表数量只有3个,使用ForEach,列表数量较多的场景,推荐使用LazyForEach+组件复用+缓存列表项实现ForEach(this.swiperData,(item:Resource)=>{Column(){// TODO 知识点:将swiper区域分割成内容区和空白区Image(item).width('100%').height('22%').borderRadius(10)Column().width('100%').height(50).backgroundColor(Color.Gray)}})}.width('95%').loop(true).autoPlay(true)// TODO 知识点:通过indicator属性,将导航点放置到空白区域,实现指示器导航点位于swiper下方的效果.indicator(new DotIndicator().bottom(15))}.height('100%').width('100%').justifyContent(FlexAlign.Center)

四、Swiper组件实现容器视图居中完全展示,两边等长露出,跟随手指滑动

请添加图片描述
逻辑简约描述:
难点在于偏移的计算
要特别注意宽度和高度值设置,保持统一单位。
在实际的开发过程中,因为单位的马虎导致即使代码是一样的,也出现过多次错位等问题
建议先完整参考代码写一遍之后再按实际需求进行偏移算法修改
比较烧脑,准备两罐红牛缓解疲劳蛤!

偏移计算:

/*** 计算卡片偏移量,并维护偏移量列表。* @param targetIndex { number } swiper target card's index.*/calculateOffset(target: number) {let left = target - 1;let right = target + 1;// 计算上一张卡片的偏移值if (this.isIndexValid(left)) {this.cardsOffset[left] = this.getMaxOffset(left);}// 计算当前卡片的偏移值if (this.isIndexValid(target)) {this.cardsOffset[target] = this.getMaxOffset(target) / 2;}// 下一张片的偏移值if (this.isIndexValid(right)) {this.cardsOffset[right] = 0;}}

滑动触发偏移计算:

.onChange((index) => {// logger.info(TAG, `Target index: ${index}`);this.calculateOffset(index);}).onGestureSwipe((index, event) => {const currentOffset = event.currentOffset;// 获取当前卡片(居中)的原始偏移量const maxOffset = this.getMaxOffset(index) / 2;// 实时维护卡片的偏移量列表,做到跟手效果if (currentOffset < 0) {// 向左偏移/** 此处计算原理为:按照比例设置卡片的偏移量。* 当前卡片居中,向左滑动后将在左边,此时卡片偏移量即为 maxOffset * 2(因为向右对齐)。* 所以手指能够滑动的最大距离(this.displayWidth)所带来的偏移量即为 maxOffset。* 易得公式:卡片实时偏移量 = (手指滑动长度 / 屏幕宽度) * 卡片最大可偏移量 + 当前偏移量。* 之后的计算原理相同,将不再赘述。*/this.cardsOffset[index] = (-currentOffset / this.displayWidth) * maxOffset + maxOffset;if (this.isIndexValid(index + 1)) {// 下一个卡片的偏移量const maxOffset = this.getMaxOffset(index + 1) / 2;this.cardsOffset[index + 1] = (-currentOffset / this.displayWidth) * maxOffset;}if (this.isIndexValid(index - 1)) {// 上一个卡片的偏移量const maxOffset = this.getMaxOffset(index - 1) / 2;this.cardsOffset[index - 1] = (currentOffset / this.displayWidth) * maxOffset + 2 * maxOffset;}} else if (currentOffset > 0) {// 向右滑动this.cardsOffset[index] = maxOffset - (currentOffset / this.displayWidth) * maxOffset;if (this.isIndexValid(index + 1)) {const maxOffset = this.getMaxOffset(index + 1) / 2;this.cardsOffset[index + 1] = (currentOffset / this.displayWidth) * maxOffset;}if (this.isIndexValid(index - 1)) {const maxOffset = this.getMaxOffset(index - 1) / 2;this.cardsOffset[index - 1] = 2 * maxOffset - (currentOffset / this.displayWidth) * maxOffset;}}}).onAnimationStart((index, targetIndex) => {this.calculateOffset(targetIndex);})

~~~~~~~~~~~待扩展

五、收尾两侧都有等长偏移的露出

六、卡片叠加楼层效果

开源 Demo 工程地址

Demo 工程

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

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

相关文章

软考高级:嵌入式系统调度算法 AI 解读

嵌入式系统中的调度算法用于管理任务的执行顺序&#xff0c;确保系统资源能够有效分配。以下是几种常见的调度算法的通俗讲解。 生活化例子 想象你是一位超市收银员&#xff0c;有很多顾客排队&#xff0c;每位顾客都可以看作一个任务&#xff0c;收银台就是你的处理器。你需…

PostgreSQL技术内幕10:PostgreSQL事务原理解析-日志模块介绍

文章目录 0.简介1.PG日志介绍2.事务日志介绍3.WAL分析3.1 WAL概述3.2 WAL设计考虑3.2.1 存储格式3.2.2 实现方式3.2.3 数据完整性校验3.3 check ponit 4.事务提交日志&#xff08;CLOG&#xff09;4.1 clog存储使用介绍4.2 slru缓冲池并发控制 0.简介 本文将延续上一篇文章内容…

【无标题】Java_Se 数据变量与运算符

标识符、变量、常量、数据类型、运算符、基本数据类型的类型转换等。这些是编程中的“砖块”&#xff0c;是编程的基础。要想开始正式编程&#xff0c;还需要再学“控制语句”&#xff0c;控制语句就像“水泥”&#xff0c;可以把“砖块”粘到一起&#xff0c;最终形成“一座大…

华为OD机试 - 二维伞的雨滴效应(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

ClickHouse-Kafka Engine 正确的使用方式

Kafka 是大数据领域非常流行的一款分布式消息中间件&#xff0c;是实时计算中必不可少的一环&#xff0c;同时一款 OLAP 系统能否对接 Kafka 也算是考量是否具备流批一体的衡量指标之一。ClickHouse 的 Kafka 表引擎能够直接与 Kafka 系统对接&#xff0c;进而订阅 Kafka 中的 …

镀金引线---

一、沉金和镀金 沉金和镀金都是常见的PCB金手指处理方式&#xff0c;它们各有优劣势&#xff0c;选择哪种方式取决于具体的应用需求和预算。 沉金&#xff08;ENIG&#xff09;是一种常用的金手指处理方式&#xff0c;它通过在金手指表面沉积一层金层来提高接触性能和耐腐蚀性…

【C++】模拟实现vector

在上篇中我们已经了解过的vector各种接口的功能使用&#xff0c;接下来我们就试着模拟实现一下吧&#xff01; 注意&#xff1a;我们在此实现的和C标准库中实现的有所不同&#xff0c;其目的主要是帮助大家大概理解底层原理。 我们模拟vector容器的大致框架是&#xff1a; t…

2024年【四川省安全员B证】新版试题及四川省安全员B证考试试卷

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 四川省安全员B证新版试题参考答案及四川省安全员B证考试试题解析是安全生产模拟考试一点通题库老师及四川省安全员B证操作证已考过的学员汇总&#xff0c;相对有效帮助四川省安全员B证考试试卷学员顺利通过考试。 1、…

【webpack4系列】webpack基础用法(二)

文章目录 entryoutputloaderpluginmode前端构建基础配置关联HTML插件html-webpack-plugin构建 CSS 解析 ES6和React JSX解析 ES6解析 React JSX 解析CSS、Less和Sass解析CSS解析Less解析sass 解析图片和字体资源解析&#xff1a;解析图片资源解析&#xff1a;解析字体资源解析&…

JS - 获取剪切板内容 Clipboard API

目录 1&#xff0c;需求最终效果 2&#xff0c;实现示例 3&#xff0c;注意点1&#xff0c;只支持安全上下文环境2&#xff0c;只能读取当前页面的剪切板3&#xff0c;权限获取问题4&#xff0c;获取内容的 MIME_TYPE 问题1&#xff0c;文本内容2&#xff0c;图片内容 5&#x…

魅思-视频管理系统 getOrderStatus SQL注入漏洞复现

0x01 产品简介 魅思-视频管理系统是一款集成了视频管理、用户管理、手机端应用封装等功能的综合性视频管理系统。该系统不仅以其强大的视频管理功能、灵活的用户管理机制、便捷的手机端应用封装功能以及高安全性和现代化的界面设计,成为了市场上备受关注的视频管理系统之一。…

一个基于 laravel 和 amis 开发的后台框架, 友好的组件使用体验,可轻松实现复杂页面(附源码)

前言 随着互联网应用的发展&#xff0c;后台管理系统的复杂度不断增加&#xff0c;对于开发者而言&#xff0c;既要系统的功能完备&#xff0c;又要追求开发效率的提升。然而&#xff0c;传统的开发方式往往会导致大量的重复劳动&#xff0c;尤其是在构建复杂的管理页面时。有…

Web植物管理系统-下位机部分

本节主要展示上位机部分&#xff0c;采用BSP编程&#xff0c;不附带BSP中各个头文件的说明&#xff0c;仅仅是对main逻辑进行解释 main.c 上下位机通信 通过串口通信&#xff0c;有两位数据验证头&#xff08;verify数组中保存对应的数据头 0xAA55) 通信格式 上位发送11字节…

机器学习:opencv--图像金字塔

目录 一、图像金字塔 1.图像金字塔是什么&#xff1f; 2.有哪些常见类型&#xff1f; 3.金字塔的构建过程 4.图像金字塔的作用 二、图像金字塔中的操作 1.向下采样 2.向上采样 3.注意--无法复原 三、代码实现 1.高斯金字塔向下采样 2.高斯金字塔向上采样 3.无法复…

基于SpringBoot+Vue+MySQL的志愿服务管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着社会对志愿服务需求的日益增长&#xff0c;传统的志愿服务管理方式已难以满足高效、透明、精准的管理需求。为提升志愿服务组织的运营效率&#xff0c;优化资源配置&#xff0c;增强志愿者参与度和满意度&#xff0c;开发基…

LinuxC高级作业1

1.已知网址www.hqyj.com截取出网址的每一个部分 2.整理思维导图 3.将配置桥接网络的过程整理成文档 i)) 保证虚拟机提供了桥接模式 菜单栏中 ----> 虚拟机 -----> 设置 -----> 网络适配器 ii) 保证虚拟机可以设置桥接网络 菜单栏中 ----> 编辑 -----> 虚拟网…

linux第一课(操作系统核心)

一.关于linux (1)linux是一款开源的操作系统(是多用户&#xff0c;多任务&#xff0c;多线程)。 (2)一般所说的linux指的是linux核心&#xff0c;即对计算机硬件资源负责调度管理&#xff0c;主要职责是进程管理&#xff0c;内存管理文件系统&#xff0c;设备驱动&#xff0c…

禹神3小时快速上手typescript

一、TypeScript简介 TypeScript 由微软开发&#xff0c;是基于 JavaScript 的⼀个扩展语⾔。TypeScript 包含了 JavaScript 的所有内容&#xff0c;即&#xff1a; TypeScript 是 JavaScrip t 的超集。TypeScript 增加了&#xff1a;静态类型检查、接⼝、 泛型等很多现代开发特…

(计算机毕设)基于SpringBoot+Vue的“乐锄”农产品销售网站的设计与实现

毕业设计&#xff08;论文&#xff09; 博主可接毕设&#xff01;&#xff01;&#xff01; 基于SpringBootVue的“乐锄”农产品销售网站的设计与实现 摘 要 传统的农资采购销售模式&#xff0c;造成农业生产的效率和质量低&#xff0c;人们对食品安全问题关注不断增加&#x…

golang 字符串浅析

go的字符串是只读的 测试源代码 package mainimport ("fmt""unsafe" )func swap(x, y string) (string, string) {return y, x }func print_string(obj *string, msg string) {string_ptr : (*[2]uintptr)(unsafe.Pointer(obj))first_obj_addr : string_…