HarmonyOS 鸿蒙Next PageFlip翻书效果demo 鸿蒙场景化代码

365bet怎么样 🌸 2025-10-24 23:25:35 🎨 admin 👁️ 7542 ❤️ 195
HarmonyOS 鸿蒙Next PageFlip翻书效果demo 鸿蒙场景化代码

HarmonyOS 鸿蒙Next PageFlip翻书效果demo 鸿蒙场景化代码

阅读器翻页效果demo

介绍

本示例基于显式动画、List组件、drawing接口实现了阅读器上下翻页、左右覆盖翻页以及仿真翻页效果。

阅读器翻页效果源码地址

效果图

使用说明

进入应用默认为仿真翻页,长按屏幕并滑动可实现翻页效果,点击屏幕中部区域,弹出翻页方式选择栏。

选择上下翻页,显示上下翻页页面,支持上下滑动翻页。

选择覆盖翻页,显示覆盖翻页页面。支持左右滑动翻页,以及点击屏幕左右侧后滑动翻页。

实现思路

上下翻页效果

使用List组件实现上下滑动效果,通过添加点击事件,点击屏幕,底部会出现翻页方式选择栏。核心代码如下,源码参考

UpDownFlipPage.ets

Column() {

List({ initialIndex: this.currentPageNum - Constants.PAGE_FLIP_PAGE_COUNT }) {

LazyForEach(this.data, (item: string) => {

ListItem() {

Text($r(item))

.fontSize($r('app.integer.flip_page_text_font_size'))

.width($r('app.string.page_flip_full_size'))

.lineHeight($r('app.integer.flip_page_text_line_height'))

.padding({ left: $r('app.integer.flip_page_padding_middle_two') })

.fontColor($r('app.color.text_font_color'))

.fontWeight(FontWeight.Normal)

.letterSpacing(1)

}

}, (item: string, index: number) => index + JSON.stringify(item))

}

.width($r('app.string.pageflip_bottomview_row_text_width'))

.height($r('app.string.page_flip_full_size'))

.scrollBar(BarState.Off)

.cachedCount(Constants.PAGE_FLIP_CACHE_COUNT)

.onScrollIndex((firstIndex: number) => {

this.currentPageNum = firstIndex + Constants.PAGE_FLIP_PAGE_COUNT;

})

}

.width($r('app.string.page_flip_full_size'))

.backgroundColor($r("app.color.page_flip_background_color"))

.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])

.onClick((event?: ClickEvent) => {

if (event) {

if (this.isMenuViewVisible) {

this.isMenuViewVisible = false;

} else {

this.isMenuViewVisible = true;

}

}

})

覆盖翻页效果

使用显式动画animateTo和堆叠容器Stack实现页面覆盖效果,通过触发滑动手势事件PanGesture,左右滑动屏幕或点击屏幕左侧右侧可进行翻页。animateTo中涉及的参数:

duration:动画执行的时长,单位毫秒,项目中固定为300ms。

curve:插值曲线,此处用了EaseOut,表示动画逐渐减速以低速结束。

核心代码如下,源码参考

CoverFlipPage.ets

private clickAnimateTo(isClick: boolean, isLeft?: boolean) {

animateTo({

duration: Constants.PAGE_FLIP_TO_AST_DURATION,

curve: Curve.EaseOut,

onFinish: () => {

if (this.offsetX > Constants.PAGE_FLIP_RIGHT_FLIP_OFFSETX &&

this.currentPageNum !== Constants.PAGE_FLIP_PAGE_START) {

this.currentPageNum -= Constants.PAGE_FLIP_PAGE_COUNT;

} else if (this.offsetX < Constants.PAGE_FLIP_LEFT_FLIP_OFFSETX &&

this.currentPageNum !== Constants.PAGE_FLIP_PAGE_END) {

this.currentPageNum += Constants.PAGE_FLIP_PAGE_COUNT;

}

this.offsetX = Constants.PAGE_FLIP_ZERO;

this.simulatePageContent();

}

}, () => {

if (isClick) {

if (isLeft) {

this.offsetX = this.screenW;

} else {

this.offsetX = -this.screenW;

}

} else {

if (this.offsetX > Constants.PAGE_FLIP_RIGHT_FLIP_OFFSETX &&

this.currentPageNum !== Constants.PAGE_FLIP_PAGE_START) {

this.offsetX = this.screenW;

} else if (this.offsetX < Constants.PAGE_FLIP_LEFT_FLIP_OFFSETX &&

this.currentPageNum !== Constants.PAGE_FLIP_PAGE_END) {

this.offsetX = -this.screenW;

} else {

this.offsetX = Constants.PAGE_FLIP_ZERO;

}

}

});

}

仿真翻页效果

使用@ohos.graphics.drawing接口及NodeContainer组件,实现仿真翻页效果的绘制。根据手指滑动触摸位置,计算仿真页的边缘节点,填充区域后实现。核心代码如下,源码参考

EmulationFlipPage.ets

NodeContainer(this.myNodeController)

.onAppear(() => {

AppStorage.setOrCreate('colorFlag', true);

this.newRectNode();

})

.width(px2vp(this.windowWidth))

.height(px2vp(this.windowHeight))

.gesture(

PanGesture()

.onActionUpdate((event: GestureEvent) => {

AppStorage.setOrCreate('drawState', DrawState.DS_MOVING);

clearInterval(this.timeID);

for (let i = 0; i < event.fingerList.length; i++) {

if (event.fingerList[i] == undefined ||

event.fingerList[i].localX < 0 ||

event.fingerList[i].localY < 0 ||

event.fingerList[i].localX > px2vp(this.windowWidth) ||

event.fingerList[i].localY > px2vp(this.windowHeight)) {

return;

}

if (this.panPositionX < event.fingerList[i].localX) {

this.moveForward = MoveForward.MF_FORWARD;

this.panPositionX = event.fingerList[i].localX;

} else {

this.moveForward = MoveForward.MF_BACKWARD;

this.panPositionX = event.fingerList[i].localX;

}

this.positionX = vp2px(event.fingerList[i].localX);

this.positionY = vp2px(event.fingerList[i].localY);

AppStorage.setOrCreate('positionX', this.positionX);

AppStorage.setOrCreate('positionY', this.positionY);

if (!this.isDrawing) {

this.isDrawing = true;

if (this.positionY < (this.windowHeight / Constants.PAGE_FLIP_THREE)) {

AppStorage.setOrCreate('drawPosition', DrawPosition.DP_TOP);

} else if (this.positionY >

(this.windowHeight * Constants.PAGE_FLIP_TWO / Constants.PAGE_FLIP_THREE)) {

AppStorage.setOrCreate('drawPosition', DrawPosition.DP_BOTTOM);

} else {

AppStorage.setOrCreate('drawPosition', DrawPosition.DP_MIDDLE);

}

}

this.newRectNode();

}

})

.onActionEnd(() => {

AppStorage.set('drawState', DrawState.DS_RELEASE);

let num: number = Constants.DISTANCE_FRACTION;

if (this.moveForward === 1) {

let xDiff = (this.windowWidth - (AppStorage.get('positionX') as number)) / num;

let yDiff = 0;

if (AppStorage.get('drawPosition') as number === DrawPosition.DP_BOTTOM) {

yDiff = (this.windowHeight - (AppStorage.get('positionY') as number)) / num;

} else {

yDiff = (0 - (AppStorage.get('positionY') as number)) / num;

}

this.setTimer(xDiff, yDiff, () => {

this.newRectNode();

});

} else {

AppStorage.setOrCreate('positionY', (AppStorage.get('flipPositionY') as number));

this.setTimer(Constants.FLIP_X_DIFF, 0, () => {

this.newRectNode();

});

}

this.isDrawing = !this.isDrawing;

})

)

工程结构&模块类型

├──entry/src/main/ets/

│ ├──common

│ │ └──Constants.ets // 公共常量类

│ ├──entryability

│ │ └──EntryAbility.ets // 程序入口类

│ ├──page

│ │ └──Index.ets // 首页

│ ├──view

│ │ ├──BottomView.ets // 按钮弹窗

│ │ ├──CoverFlipPage.ets // 覆盖翻页

│ │ ├──EmulationFlipPage.ets // 仿真翻页

│ │ └──UpDownFlipPage.ets // 上下翻页

│ └──viewmodel

│ ├──BasicDataSource.ets // 列表数据类

│ └──PageNodeController.ets // 节点控制类

└──entry/src/main/resource // 应用静态资源目录

参考资料

相关推荐

sci论文proof后多久发表
365完美体育app官网

sci论文proof后多久发表

📅 08-23 👁️ 3115