从零到一:实现通用一镜到底H5

66

图片描述

写在前面

整个2018年都被工作支配,文章自17年就断更了,每次看到有消息提示过往的文章被收藏,或者有人点赞,都不胜唏嘘。不过,凡事要始终保持积极的心态,现在回归为时未晚。最近有项目要做一镜到底,那就稍作研究吧。

一镜到底是什么?

百度百科-一镜到底
一镜到底,是指拍摄中没有cut情况,运用一定技巧将作品一次性拍摄完成。

那么运用到H5上面,是怎样的表现?网上案例也有很多,这里推荐数英的一篇文章,应用尽有:

一镜到底H5大合集:一口气看尽一个H5的套路

主要表现形式为以下几类:

  • 画中画(例如:网易-《娱乐画传》)
  • 时空穿梭(例如:天猫-《穿越时空的邀请函》)
  • 滚动动画(例如:网易-《爱的形状》)
  • 视频(这个好像没什么好说的...跟本文无关)

体验方式主要有:

  • 按住
  • 滑动

技术需求分析

图片描述

如上图的《爱的形状》,用户滑动屏幕,方块滚动,并且用户能控制播放进度;期间方块上面的纹理一直在变化,意味着动画一直在播放。

提取要点,要实现一个一镜到底H5,通常会有以下技术需求:

  1. 绘制画面:这里我们一般选用基于canvas的库,性能会更好,也方便实现效果。
  2. 添加动画:其中包括过渡、帧动画,因此需要一个动画库。
  3. 进度控制:要实现通过用户操作,来控制整个H5的前进、后退、暂停等,我们会需要进度控制相关的库。
  4. 用户操作:一镜到底的H5一般都需要用户操作以“播放”,按住或滑动,按住比较简单,用原生事件实现就好,滑动相对复杂一点,涉及阻尼运动,因此需要一个滑动相关的库。

有了需求,我们就可以相应去找解决方案了。绘图有用3D的threejs的,动画有人用anime.js,各有所好,能实现需求就行。

最终针对以上需求,我选用了AlloyTouch、TimelineMax、Pixi.js、TweenMax这几个库来实现通用的一镜到底。各个框架的优点这里就不赘述了,想了解详情的可以自行搜索,几乎都有中文资料,也很容易使用。

实现步骤要点

  1. 用Pixi创建场景,加入到想要加入的DOM容器当中。
  2. 用Pixi.loader加载精灵图。
  3. 将精灵图、背景及文本等元素绘制出来。
  4. 用TimelineMax创建一个总的Timeline,初始设置paused为true,可以设定整条Timeline的长度为1。
  5. 用TweenMax创建好过渡动画,然后将TweenMax加入到Timeline中,duration比如是占10%的话,就设定为0.1,从滚动到30%开始播放动画的话,delay就设置为0.3。
  6. 用AlloyTouch创建滚动监听,并设置好滚动高度,例如1000。
  7. 监听AlloyTouch的change事件,用当前滚动值 / 滚动高度 得到当前页面的进度。
  8. 调用总Timeline的seek方法,寻找到当前页面进度的地方,可以简单理解成拨动视频播放器的进度条滑块。
  9. 至此就可以通过用户滑动操作,控制页面元素的动画播放、后退了。

你可能会问那怎样实现上面说的几种类型的一镜到底?实际上,几种类型的不同只是动画变换方式不一样而已。

  • 画中画(缩放同时平移)
  • 时空穿梭(以中心缩放)
  • 滚动动画(平移为主,期间播放其他动画)

示例项目

简单写了个demo,如果感兴趣的朋友可以拉下来自己把玩一下。

点此查看仓库

点此查看demo

图片描述

(注:项目中素材来源于网络,仅供交流学习使用,切勿商用!)

展望

这里只实现了一个一镜到底H5的主要效果部分,距离完成还有很多工作:

  • 微信分享设置及引导
  • 添加一个加载界面
  • 添加音乐音效(用过howler,感觉不错)
  • 可能需要的生成海报(html2canvas,生成海报easy job)
  • ...

结语

这次没有用太多篇幅铺开来讲细节,主要是运用几个库组合来实现,而实际操作上还有很多地方要注意的,例如帧动画的实现,滑动的速度控制,滑到顶部、底部的处理等等。实际应用上还要继续打磨,毕竟一个漂亮的H5,是要花很多精力去构思,去优化体验的。

最后也希望能认识到更多在H5领域有研究的小伙伴,可以互相交流,甚至一起工作!

email: vincent@shikehuyu.com


如果觉得我的文章对你有用,请随意赞赏

你可能感兴趣的

20 条评论
北国风光 · 1月10日

一直很佩服做出这些精彩效果的前端童鞋们

+2 回复

0

@北国风光 同样很佩服能只写逻辑的后端童鞋们。

Vincent_Pat 作者 · 1月10日
pang · 1月11日

厉害厉害

+1 回复

小硕 · 1月11日

研究下 好久没写过纯展示的东西了

+1 回复

Airmusic · 1月13日

大神就是厉害,文章简洁明了,全是重点。

+1 回复

0

过奖,不敢当,只是研究了就发出来下。

Vincent_Pat 作者 · 1月14日
曹健 · 1月14日

厉害,收藏,支持!

+1 回复

0

假粉丝。

Vincent_Pat 作者 · 1月14日
冲锋鲁莽大风车 · 3月6日

大哥受我一拜!我这边去年就有这种需求了,但是一直不知道怎么做,这边文章简直醍醐灌顶,非常感谢!

+1 回复

0

一起学习一起进步哈哈哈,期待你的分享

Vincent_Pat 作者 · 3月7日
1

再次感谢大佬~大佬的代码我已经看完了,也在本地照抄实现了一下,不得不说大佬功力深厚,代码赏心悦目。
在此有个小建议,就是getSpritesAnimations方法中,动画的控制顺序貌似都是通过delay来实现的,由timeline加入到0位置。这样如果前面的delay想要改动的话,emmm...,貌似改动会大了点。我这边的做法是animation按顺序定义并打上label,每个animation再设置需要插入到哪个label,一环接一环配置下来,这样改动的话波及范围应该比delay少点。

0

@冲锋鲁莽大风车 我代码很烂……有很大改进空间的,毕竟只是个玩具哈哈要投入生产估计要做多很多工作,期待你分享最终作品出来哦~

Vincent_Pat 作者 · 3月8日
青ツ玉 · 1月21日

点赞!!!!

回复

helloworld · 2月14日

coding上面的代码在本地跑不起来

回复

0

咦,报什么错了?没更新过喔。

Vincent_Pat 作者 · 2月14日
0

找到问题了,config/index.js 文件中的host,改为 localhost或者我本地机子的就可以了

helloworld · 2月15日
0

@helloworld 哦,是的,之前忘了改回来了。

Vincent_Pat 作者 · 2月16日
helloworld · 4月25日

我想请问下,LongTake.js中 事件相关的 on trigger 是什么原理,看得有点懵

回复

0

哦,这其实是事件监听相关的方法啦,on监听事件,trigger触发事件。比如监听动画播放进度on('progress', function(){ ... }) LongTake在进度变化的时候去触发progress事件,trigger('progress', this.progress)

有点类似于 addEventListener 吧

Vincent_Pat 作者 · 4月27日
载入中...