一个H5的3D滑动组件实现(兼容2D模式)
起由
原始需求来源于一个项目的某个功能,要求实现3D图片轮播效果,而已有的组件大多是普通的2D图片轮播,于是重新造了一个轮子,实现了一个既支持2D,又支持3D的滑动、轮播组件。
实现思路
刚一开始肯定是无法直接实现3D滑动组件的,所以将功能拆分,如下步骤
- 实现一个双向循环链表,作为底层Item的数据结构
- 基于链表,实现一个无限循环的2D滑动组件
- 基于2D滑动组件做3D变化得到3D组件
- 兼容性检查以及功能封装,简化使用,确保稳定
双向循环链表的模拟
以前看到的轮播组件大多是用数组来作为底层数据结构,最近,整合受简书上的某一篇文章启发,觉得链表方式挺不错的,于是先动手造一个JS模拟的链表(一些现有的资源大多不符合预期,于是重新造轮)
原理
双向循环链表原理比较简单,这里不再赘述
实现
实现了一个双向链表,支持循环和非循环,参考 https://github.com/dailc/jsDataStruct
2D滑动组件的实现
在H5时代,2D滑动组件大多是通过translate3d 和transition实现的,采用X轴位移来实现滑动,所以虽说最终的效果只是2D得平面滑动,其实也是基于3D变换的。
实现原理描述
假设屏幕宽为W,滑动组件中有(A,B,C,D,E )5个item,每一个item的宽度都占满屏幕。采用循环模式(也就是E往右滑动可以到A)
- 构建双向循环链表,其中从A开始
A._next = B;
B._next = C;
...
E._next = A;
A._prev = E;
B._prev = A;
...
E._prev = D;
如上,所以所有元素首尾相连,构成循环
初始化组件时,各自的位置如下(只考虑X轴(→),Y(↓)和Z(垂直屏幕)都是0)。
E(-2W),D(-W),A(0),B(W),C(2W)。
一般只会允许同时显示最多5个元素,其它位置的元素暂时隐藏通过监听滑动组件的touch,来判断当前组件应该的X轴唯一translateX
touchmove过程中,显示的元素进行相应的translateX位移(向左滑为负,向右滑为正)。比如A的位置为(0+translateX),其它元素类似
touchend时,判断当前的translateX,如果大于item宽度的50%,则判断移到下一个位置,如果大于item宽度的150%,则移到下下个元素。同理,如果小于-50%,则移到到上各元素,小于-150%,则移动到上上个元素
移动到上一个元素,各自item的translateX 减去W即可,移动到下一个元素,加上W。并且移动过程中设置
transition(cubic-bezier(0.165, 0.84, 0.44, 1))由于是通过双向循环链表构建,所以每次移动只需要通过_next就可找到下一个元素,通过_prev即可找到上一个元素,并且自动循环
原理流程
以下为上述中向右滑动一位,的过程图述

效果预览
下图是将item的宽度设为屏幕50%后的2D滑动效果

3D滑动组件的进一步实现
上述过程中实现了2D滑动组件,那么带3D组件的组件该如何实现呢?毕竟最初的需求就是3D效果。
其实上述2D滑动组件就已经用到了3D变化了,只不过我们只用了X轴变换。所以看起来仍然是2D效果,所以接下来我们就是需要利用到另外两个轴的变换。
最终效果图示
最终我们需要实现如图所示的3D滑动效果

基本3D坐标轴
我们将屏幕左上角看成原点。那么
- X轴就是平行于屏幕的水平方向,从左到右
- Y轴就是平行于屏幕的垂直方向,从上到下
- Z轴就是垂直于屏幕(垂直于这个面),由内向外(也就是从屏幕后面穿过屏幕,指向做电脑前面的人)
分析我们需要的3D变换
对比已经完成的2D效果和最终3D效果的图,我们发现有以下区别
- Y轴存在旋转(rotateY),目测,左侧第一个Item的旋转角度在(30度和45度之间)
- Z轴存在纵深(translateZ或translate3d),可以观察出,屏幕中心的Item和左侧或右侧的纵深不一样,屏幕中心的Z值更大(更突出)
- 需要找一个合适的视点(perspective),因为存在Z轴纵深,所以肯定是需要找到一个合适的视点来观察整个组件的。
实际实现
实际实现过程中,和上述分析的过程一致,在2D变换的基础上,针对Y轴进行了旋转计算,针对Z轴进行了纵深计算。
基本过程是:
找到一个合适的Y轴旋转计算公式(比如那左侧的Item调试,找到一个合适的点)
找到合适的适应于不同屏幕分辨率的Z轴纵深以及视点位置,(比如在屏幕320时,找到一个合适的Z轴纵深和perspective,然后再屏幕768时再找到一个,进行线性插值即可)
详细过程不再赘述
兼容性检查以及功能封装
初步做出来的效果并不能很好的兼容各种分辨率屏幕以及功能较为简陋。
所以接下来的主要工作是:
- 找到合适的插值公式,使的3D变化适应于较多的屏幕。
- 检查代码,使的兼容更多的浏览器版本(比如Chrome,APP内嵌Webview,FireFox等等,当然了,肯定不考虑IE)
- 代码封装抽象工作,合理开放API,以及便于后续拓展(剥离第三方库的依赖,进一步封装后,使的类库代码更优雅)
基本上述工作完成后,一个崭新的3D滑动组件类库就完成了,它主要有如下功能;
- 支持3D滑动效果(核心功能)
- 兼容2D滑动效果(同时保证普通的使用)
- 开放以下API
* reset 重置,这个可以重写更换options
* prev 上一个item
* next 下一个item
* moveTo 移动到某一个指定item,会寻找最短路径
* bindItemChangedHandler 绑定item切换的监听回调
* bindItemTapHandler 绑定item的tap监听
* unBindItemTapHandler 解绑item的tap监听,会取消所有的item的tap事件以及item内部的tap
* tap 绑定item内部某元素的tap事件,因为无法用click监听,所以单独提供了监听函数
- 便于拓展,比如这个组件有提供一个图片轮播拓展示例
源码及效果
效果展示
源码
原文地址
原文在我个人博客上面
参考链接
一个H5的3D滑动组件实现(兼容2D模式)的更多相关文章
- 写一个js向左滑动删除 交互特效的插件——Html5 touchmove
需求描述 需要实现类似QQ中对联系人的操作:向左滑动,滑出删除按钮.滑动超过一半时松开则自动滑到底,不到一半时松开则返回原处. 纯js实现 使用了h5的touchmove等事件,以及用js动态改变cs ...
- HT for Web列表和3D拓扑组件的拖拽应用
很多可视化编辑器都或多或少有一些拖拽功能,比如从一个List列表中拖拽一个节点到拓扑组件上进行建模,并且在拖拽的过程中鼠标位置下会附带一个被拖拽节点的缩略图,那么今天我们就来实现这样的拖拽效果. 首先 ...
- iSlider手机平台JS滑动组件
iSlider手机平台JS滑动组件,无任何插件依赖.它能够处理任何元素,例如图片或者DOM元素.它有如下特性:能够自定义动画,自带的动画包括default, rotate, flip 和 depth你 ...
- wpf做的3d滑动gallery
原文:wpf做的3d滑动gallery wpf做的3d滑动gallery 随着iphone\ipad的流行及热捧,现在做移动产品不管是什么平台的,领导总想做成像ios系统的样子.自从微软发布了wind ...
- 移动端H5页面惯性滑动监听
移动端H5页面惯性滑动监听 在移动端,当你快速滑动有滚动条的页面时,当你手指离开屏幕时,滚动条并不会立即停止,而是会随着"惯性"继续滑动一段距离. 在做项目的过程中,需要监听惯性滑 ...
- 编写第一个H5页面
<!DOCTYPE html><html ><head> <meta charset="UTF-8"> <title>第 ...
- Net dll组件版本兼容问题
dll组件版本兼容问题,是生产开发中经常遇到的问题,常见组件兼容问题如:Newtonsoft.Json,log4net等 为了节约大家时间,想直接看解决方法的,可直接点击目录3.4 目录 1.版本兼容 ...
- Vue + element从零打造一个H5页面可视化编辑器——pl-drag-template
pl-drag-template Github地址:https://github.com/livelyPeng/pl-drag-template 前言 想必你一定使用过易企秀或百度H5等微场景生成工具 ...
- H5打造3d场景不完全攻略(一): H5 3d表现形式
前言 日前,taobao造物节H5放肆地火了一把.相信接下来将3d嵌入网站的这种营销方式会被越来越多的人留意到.工作之余体验了若干个3d H5页面,感觉这类的H5互动体验性明显要比普通的要强,把二维的 ...
随机推荐
- 重构第2天:方法搬移(Move Method)
现在就重构来说是非常普通的,虽然我们经常会漏掉或忽略一些需要重构的地方.方法搬移,正如所定义的那样,把方法搬移到更适合他的位置.让我们看看下面这一段重构前的代码: 理解:方法搬移,正如所定义的那样,把 ...
- zk框架销毁Page上的Component
销毁Page上的Component ZK的组件之间是树状结构的,每一组件都只有一个根. 从页面上销毁一个组件可以通过下面两种方式来实现: 1. 组件不是根组件时:Component.setParent ...
- ruby -- 进阶学习(六) devise修改邮件发送者邮箱
在config/environment.rb/development.rb或者config/environment/production.rb中, 简单示范例子: Text03::Applicatio ...
- [python]在场景中理解装饰器
原来我也自己通过查资料,来学习python的装饰器,但是效果不好.因为没有接触过需要用到装饰器的场景,所以 一起的资料都只停留在纸面上,但是今天偶然看到了vimer的这篇文章:http://www.v ...
- BZOJ 1054 广搜
1054: [HAOI2008]移动玩具 在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动 时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩 ...
- Team Foundation Server简介
对于任何一个软件开发团队而言,成功的一个重要因素在于成员之间.成员与首先使用软件的用户之间有很好的沟通. Team Foundation Server是一个独立的服务器产品,逻辑上,由下列两层组成,这 ...
- Sql Server来龙去脉系列 必须知道的权限控制基础篇
题外话:最近看到各种吐槽.NET怎么落寞..NET怎么不行了..NET工资低的帖子.我也吐槽一句:一个程序猿的自身价值不是由他选择了哪一门技术来决定,而是由他自身能创造出什么价值来决定. 在进入本篇内 ...
- Linq之select子句
在Linq中select子句用来指定查询结果的类型和表现形式.Linq查询要么以select子句结尾,要么以group子句结尾. List<UserBaseInfo> users = ne ...
- ASP.NET MVC使用动态产生meta
在ASP.NET中,我们是很容易动态为header节点添加meta信息.<动态修改网页Header属性,Title,Meta标签等>http://www.cnblogs.com/insus ...
- asp.net Get和Post传参和接收参数
asp.netGet和Post传参和接收参数 Get请求: 对于传参:test.aspx?name=%e5%bc%a0%e4%b8%89 接收参数的方法: Request.QueryString[&q ...