首次开发H5长图页总结
首次开发H5长图页总结.
资源统一加载
资源统一加载, 分开获取
定义资源标识符
- 在
src/resources目录下 定义各个资源模块. - 在
Asset.js中获取定义好的所有模块, 循环出具体的文件路径, 统一数组. - 按照一定规则组件文件id, 方便页面中获取.
暴露方法, 挂载全局
在全局app.init的时候, 进行资源的初始化, 并把初始化的资源对象挂载到Global对象上, 方面后续其他页面的资源获取.(Global用作全局属性管理).代码的执行顺序为:
app.init() => new Asset() => asset.load() => asset.onComplete() => initStage() => ....
- load: 可开始加载全部资源
- onComplete: 资源全部加载完成
- getAsset: 获取指定资源
切换思想
全局只存在两个container; 所有页面交替出现
创建舞台的过程
所有的页面均在initStage()初始化舞台时, 进行创建, 以确保资源全部加载完成. 舞台初始化完成, 所有的页面也均初始化完成.
initStage()过程包括:
- initBus(): 初始化全局的事件订阅系统
- createStage(): 创建舞台, 在创建舞台的时候, 就和绑定好了滚动函数.
- initScene: 因为刚开始的代码逻辑出现问题, 全局只有一个场景, 是起初没有考虑到的
- 完成, 即可把第一个页面推出显示栈.
页面创建过程
在创建舞台的时候, 会初始化场景, 我们的页面总体分成: 舞台 > 场景 > 部分(页面)
初始化场景的过程, 也就是初始化所有页面的过程:
new Scene() => init partMap() => partMap.push(new Part)
partMap是所有页面的集合, 按照显示顺序进行创建.
- 每当执行new part时, 就是页面执行自身constructor, 并调用init方法的过程.
- 因每一个页面都是通过push方法, 放入到parMap中的, 故初始化过程的中partMap的长度就是, 当前页面所在partMap中的位置
- 页面创建后, 会包含所有后续需要的属性, 以及页面声明周期中所有状态的初始化.
- 并在创建过程中完成各个模块的监听
页面生命周期
正序执行过程: p1.start => p1.next => p2.start => p1.end => p2.next => ....
倒序执行过程: p2.prev => p1.restart => p2.end => ....
每次声明周期函数, 为避免计算错误, 只在特定的时间执行一次, 故需要一些关键的状态管理
start: 页面开始函数, 即让页面执行
addTo()添加到舞台中reStart: 重新展示页面, 让页面的执行
addTo(stage, 0), 让页面插入到舞台的最底层位置prev: 上一个页面战术, 即让上一个页面执行
reStart()重新展示next: 下一个页面战术, 即下一个页面执行
start()方法end: 页面展示结束, 从父元素中remove出来, 并重置方法执行状态.
除next方法, 需要在页面内具体实现外, 其他方法均为统一处理
shouldUpdate: 监听到滚动, 执行页面内具体逻辑
滑动高度
在
initStage的时候, 绑定滚动事件. 并广播全局事件.
动态计算
- 全局总高度: 每一次
new part的时候, 都会累加整个页面需要的总高度, 并以此设计能够滑动的高度. - 页面高度计算方式: 页面的高度, 是通过参数传入的.
- 页面开始高度:
- 从全局看: 当前页面高度是, 之前所有页面的累加高度, 也就是全局的高度.
- 从页面看: 所有的页面都是从0开始.
当前页面的滚动位置
当前页面滚动的位置 = 总共滚动过的高度 - 当前页面开始的高度
<0的部分还和上一个页面重叠>0之后, 自己完全出现合适的时机调用,next, 下一个页面就可以开始<0的过程了.- 当滚动的高度大于当前页面的高度时, 就是执行end的时候了.
附上核心实现函数
// Part.js
// 注: 此函数依赖全局模块
import Global from './Global'
const Part = Hilo.Class.create({
Mixes: Hilo.EventMixin,
constructor: function (properties) {
this.parentNode = properties.parentNode || null; // 页面所属场景
this.parentContainer = properties.parentNode ? properties.parentNode.content : null; // 页面所属容器
this.parentName = properties.parentNode ? properties.parentNode.name : ''; // 页面所属场景名称
this.name = properties.name || ''; // 页面名称
this.partHeight = properties.height || 0; // 页面的总高度
this.disappearNext = properties.disappear || 0; // 页面需要消失的距离
this.state = 'hide'; // 当前页面是否展示
this.nextDone = false; // next函数是否执行过
this.prevDone = false; // prev函数是否执行过
this.index = this.parentNode.partMap.length; // 此处为核心概念, 根据数组长度确定当前索引!!
this.content = new Hilo.Container({
id: this.name
});
this.initStartHeight(); // 计算当前页面的在全局中的开始高度
if (this.init instanceof Function) this.init();
// 监听用户滚动, 高度变化.
Global.bus.on('changeTouchHeight', this.changeTouchHeight.bind(this));
},
initStartHeight: function () {
// 获得当前页面在全剧中的高度
var perNode = this.getPrevNode()
this.startHeight = perNode ? Global.totalHeight += perNode.partHeight : Global.totalHeight;
// 页面能够滚动到的最大高度
var maxHeight = (this.startHeight + this.partHeight - Global.height) / Global.touchSpeed;
Global.scroller.setDimensions(0, 0, 0, maxHeight)
},
changeTouchHeight: function (info) { // 监听高度变化
if (this.state === 'show' && this.shouldUpdate instanceof Function) {
var touchHeight = info.detail.distance - this.startHeight; // 页面内的高度变化值
var direction = info.detail.direction; // 滚动的方向
if (direction === 'up' && touchHeight <= 0) { // 向上滚动, 且高度小于0, 上一个页面展示
this.prev();
}
if (direction === 'down' && touchHeight >= this.partHeight) { // 向下滚动, 超过当前页面最大高度, 从父容器中抽出
console.log(this.name, 'down end')
this.end()
}
if (direction === 'up' && this.getPrevNode() && touchHeight < -this.getDisappearPrev()) { // 向上滚动, 超过上一个页面的消失高度, 从父元素中抽出
console.log(this.name, 'up end')
this.end()
}
// 调用生命周期, 通知页面内变化
this.shouldUpdate(touchHeight, direction);
}
},
start: function () { // 开始展示
if (this.state === 'show') return;
this.state = 'show';
console.log(this.name, 'start');
if (this.onStart instanceof Function) this.onStart();
this.content.addTo(this.parentContainer);
},
reStart: function () { // 再次展示, 也就是向上滑动, 展示到舞台的最底层
if (this.state === 'show') return;
this.state = 'show';
console.log(this.name, 'reStart');
if (this.onreStart instanceof Function) this.onreStart();
this.content.addTo(this.parentContainer, 0);
},
prev: function () { // 展示上一个页面
if (this.state === 'hide' || this.prevDone) return;
if (this.getPrevNode() && this.getPrevNode().state === 'show') return;
this.prevDone = true;
console.log(this.name, 'prev')
if (this.onPrev instanceof Function) this.onPrev();
this.getPrevNode() && this.getPrevNode().reStart();
},
next: function () { // 展示下一个页面
if (this.state === 'hide' || this.nextDone) return;
if (this.getNextNode() && this.getNextNode().state === 'show') return;
this.nextDone = true;
console.log(this.name, 'next')
if (this.onNext instanceof Function) this.onNext();
this.getNextNode() && this.getNextNode().start();
},
end: function () { // 页面展示结束, 抽出
if (this.state === 'hide') return;
console.log(this.name, 'end')
if (this.onEnd instanceof Function) this.onEnd();
this.state = 'hide';
this.content.removeFromParent();
this.getNextNode() && (this.getNextNode().prevDone = false);
this.getPrevNode() && (this.getPrevNode().nextDone = false);
},
getPrevNode: function () { // 获取上一个页面节点
var map = this.parentNode.partMap;
var index = this.index;
return map[index - 1];
},
getNextNode: function () { // 获取下一个页面节点
var map = this.parentNode.partMap;
var index = this.index;
return map[index + 1];
},
getDisappearNext: function () { // 向下滚动消失需要的距离
return this.disappearNext;
},
getDisappearPrev: function () { // 向上滚动消失需要的距离
return (this.getPrevNode() && this.getPrevNode().getDisappearNext()) || 0;
},
});
export default Part;
首次开发H5长图页总结的更多相关文章
- ios开发之滑动长图截全屏应用
最近做项目遇到要求截取图片长度超出手机屏幕,即可滑动的长图截屏,这里简单说一下解决思路,下面附带Demo下载地址. ,当我们要截全屏时,将滑动视图的frame以及偏移量记录下来,然后将滑动视图偏移量设 ...
- 开发H5游戏引擎的选择:Egret或Laya?
开发H5游戏引擎的选择:Egret或Laya? 一.总结 一句话总结:选laya吧 二.开发H5游戏引擎的选择:Egret或Laya? 一.H5游戏开发的引擎介绍 开发H5游戏的引擎有很多,比如egr ...
- 模仿开发H5游戏,看你有多色
开发记录 前言 之前跟着慕课网学习开发H5小游戏开心鱼,勾起我的兴趣. 在写代码的过程中,不怎么会遇到问题.虽然代码是亲手敲出来的,但是由于并没有对游戏的整体思路,所以并不知道开发与优化的过程. 为了 ...
- web实时长图实践--摘抄
背景简介 全民K歌专辑发布新玩法,传统宣传专辑战绩的流程,从获取数据,到制作海报,到传播,周期长运营成本高,如何快速分享战绩进行荣誉感的传播成为一个亟待解决的问题. 产品:能不能在专辑大事件触发时,自 ...
- Android 截屏与 WebView 长图分享经验总结
最近在做新业务需求的同时,我们在 Android 上遇到了一些之前没有碰到过的问题,截屏分享. WebView 生成长图以及长图在各个分享渠道分享时图片模糊甚至分享失败等问题,在这过程中踩了很多坑,到 ...
- 基于vuecli3构建一个快速开发h5 APP的模板
基于vuecli3构建的一个快速开发h5 APP的模板,集成了高德地图.mint-ui,以及antv-f2可视化框架 vue-cli3安装 查看vue cli版本 vue --version 要求no ...
- 微信小程序_(校园视)开发视频的展示页_上
微信小程序_(校园视) 开发用户注册登陆 传送门 微信小程序_(校园视) 开发上传视频业务 传送门 微信小程序_(校园视) 开发视频的展示页-上 传送门 微信小程序_(校园视) 开发视频的展示页-下 ...
- iPhone截长图的方法
iPhone手机暂没有长图截取功能,所以我们只能通过别的方式进行长图截取. (2020年4月10日更新) ios13目前可以截长图了,不过只能在Safari中进行长图截取,而且存储形式为pdf格式,下 ...
- ReactNative新手学习之路04 组件化开发轮播图swiper支持安卓和IOS
react native 新手之路04 组件化开发轮播图swiper支持安卓和IOS npm install react-native-carousel --save git 地址Properties ...
随机推荐
- Android 7.1 GUI系统-窗口管理WMS-Surface管理(四)
Surface的管理 Surface是窗口能真正显示到物理屏幕上的基础,由surfaceflinger管理,可以通过WindowStateAnimator.java中的变量mDrawState来查看每 ...
- unity3d mvvm c#
using UnityEngine; using System.Collections; public interface IState { void BeforEnter(); void Befor ...
- 【Shell】变量的取用、删除、取代与替换
——来自<鸟哥的Linux私房菜> ——总结做方便查阅之用 变量的取用: echo echo $variableecho $PATHecho ${PATH} 变量的配置守则1.变量与变量内 ...
- AtCoder Grand Contest 014 D:Black and White Tree
题目传送门:https://agc014.contest.atcoder.jp/tasks/agc014_d 题目翻译 给你一棵树,每次任选一个点染色,先手染白色,后手染黑色.如果最后存在一个白色的点 ...
- 洛谷P1092虫食算——深搜
题目:https://www.luogu.org/problemnew/show/P1092 剪枝1:从右往左.从上往下按字母出现顺序搜索: 剪枝2:同一列前两个数字确定,可直接算出第三个数字并判断: ...
- 【转】Pro Android学习笔记(二):开发环境:基础概念、连接真实设备、生命周期
在Android学习笔记(二):安装环境中已经有相应的内容.看看何为新.这是在source网站上的Android架构图,和标准图没有区别,只是这张图颜色好看多了,录之.本笔记主要讲述Android开发 ...
- 一致性哈希算法原理、避免数据热点方法及Java实现
一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似.一致性哈希修正了CARP使用的简 单 ...
- 14 vue学习 postcssrc eslintrc.js babelrc
一 .postcssrc.js 众所周知为兼容所有浏览器,有的CSS属性需要对不同的浏览器加上前缀,然而有时添加一条属性,需要添加3~4条类似的属性只是为了满足浏览器的兼容,这不仅会增加许多的工作量 ...
- iOS端IM开发从入门到填坑
让App聊起来 IM开发从入门到填坑Demo IM的实现方式 拿来主义,使用第三方IM服务 IM的第三方服务商国内有很多,底层协议基本上都是基于TCP的,类似有网易云信.环信.融云.极光IM.Le ...
- Oracle内置函数大全(转)
SQL中的单记录函数 1.ASCII 返回与指定的字符对应的十进制数;SQL> select ascii('A') A,ascii('a') a,ascii('0') zero,ascii(' ...