京东技术:3分钟学会在小程序开发纸飞机动画

偷懒的程序员 2018-08-24 13:33:33 ⋅ 708 阅读

发布求购信息叫“纸飞机”,发送信息完毕之后,屏幕会出现一个纸飞机的飞行轨迹。

动画设计需求为:

1、纸飞机需要平滑的运动

2、有多种飞行方式

>>>>  纸飞机飞翔动画

>>>>  css3动画

动画的实现方式有很多种,大部分人想到jq的amination,css3的amination和transition


1、position vs transform


    


对比一下,左边是布局方式的left和top,右边是transform的translate,尤其是绘画和渲染简直天差地别。看了chrome的专业介绍,transform会走硬件加速,就是机器的显卡越好,这个差距越明显。


2、运动动画


回过来继续说飞机,我们写个飞机飞行的css3,让飞机从0px飞到1000px

 
  1. @keyframes move {

  2.  from {transform: translateX(0px)}

  3.  to {transform: translateX(1000px)}

  4. }


然后给标签应用动画,让标签播放动画,10秒播放完毕。

 
  1. #plane {

  2.    animation: move 10s linear;

  3.    width: 100px;

  4.    height: 500px;

  5. }


动画虽然播放了,可是设计的要求肯定不是让你这么直直的飞,效果太差了。但是css3只能这么弄,我们加上translateY就可以斜着飞了,貌似这是极限了。

 
  1. @keyframes move {

  2.  from{transform: translate(0px, 0px)}

  3.  to{transform: translate(1000px, 500px)}

  4. }


3、运动合成


实际上,我们的思维不能这么局限,回想一下中学的物理和数学。


速度是可以分解的,v等于v1和v2的合成。


再想想著名的平抛运动——x轴做匀速直线运动,y轴做自由落体运动(重力加速运动),因此,我们也可以分两个div,一个大div套着小div。

 
  1. <div id="plane">

  2.    <div id="entity"></div>

  3. </div>


设置一个y的运行0px到500px

 
  1. @keyframesfalling {

  2.    from{transform: translateY(0px)}

  3.    to{transform: translateY(500px)}

  4. }


注意动画这里,虽然还是10秒完成动画,但是用了淡入,就是先慢后快。

 
  1. #entity {

  2.    animation: falling 10s ease-in;

  3.    width: 50px;

  4.    height: 50px;

  5. }


我们也可以改变一下这个动画方式,比如改成5秒执行两次并且反弹。

 
  1. animation: falling 5s ease-in alternate 2;


其他的方式就更多了,总之,就看你怎么组合了。

>>>>  canvas动画

但是我们的纸飞机不能就这么一种飞法啊!


设计小姐姐给我们提出了要多几种飞行方式,可是每一种方式要调整到设计满意的样子都很难,更别说是那么多种飞行方式了。如果设计妥协,那我们的产品精致程度就要大打折扣。


这时候,我们重新捋一遍,设计做的效果肯定是有各种软件,其实软件也是把数据做了渲染。我们是否可以把设计做好的东西里面直接把数据应用到我们的开发中呢?这样肯定是还原了设计,并且修改成本非常低。


其实,设计就是画了一条线,然后拉成曲线,就是我们常说的贝塞尔曲线。


是不是听了很懵逼?


不用想那么多了!我封装了一个game.class.js类,你只需要在引用就行了。以后我们也多多这种类,别人初始化用一下就行了,根本不用去理解你怎么完成的。(这个类是小程序专用,h5需要修改)

 
  1. var context = wx.createCanvasContext('aeroplane', this);//构造画布

  2. var game = new Game.main(context);//构造game类

  3. game.setPlane(plane);

  4. game.launch(bezier);//启动


Context就是canvas的context,你可以随意创建一个;Plane是飞机的数据有地址和宽高。

 
  1. plane: {

  2.  url:"/static/images/3.png",

  3.  width:80,

  4.  height:77.6

  5. }


Bezier就是一个数组,里面放三个坐标就是二次贝塞尔,四个坐标就是三次贝塞尔。

 
  1. cube: [ //三次贝塞尔

  2.  {

  3.   x: -20,

  4.   y:600,

  5.   z:1

  6.  },

  7.  {

  8.   x:200,

  9.   y:500,

  10.   z:1

  11.  },

  12.  {

  13.   x:250,

  14.   y:300,

  15.   z:.5

  16.  },

  17.  {

  18.   x:300,

  19.   y:50,

  20.   z:.5

  21.  }

  22. ],

  23. square: [ //二次贝塞尔

  24.  {

  25.   x:0,

  26.   y:200

  27.  },

  28.  {

  29.   x:100,

  30.   y:0

  31.  },

  32.  {

  33.   x:200,

  34.   y:200

  35.  }

  36. ],


有了这些,就可以随意的生成小飞机动画了。

>>>>  动画解析

但是有些童鞋,表示“我就喜欢刨根问底,告诉我怎么做的!”好,我们一步步来。

>>>>  二次贝塞尔曲线

其实,就是给起始点和结束点中间加了一个控制点。


公式为:

>>>>  三次贝塞尔曲线

其实,就是给起始点和结束点中间加了两个控制点。


公式为:


由于有了两个控制点,可以更随意的绘制路径。

>>>>  函数解析

所谓的公式其实就是函数(function),比如这个公式,就是一个叫B的函数,参数为t,t的取值范围是0~1,p0~3这里其实是常数,因为在变化过程中他是不变的。


我们拿个实际例子吧:

  • 开始位置为(-20,600)

  • 第一个控制点为(200,500)

  • 第二个控制点为(250,300)

  • 结束点为(300,50)


我们用公式算出点

 
  1. t=0.1

  2. x = -20*(1-0.1)3 + 3*200 * 0.1*(1-0.1)2 +3* 250*0.12*(1-0.1)+300*0.13

  3. y = 600*(1-0.1)3 + 3*500 * 0.1*(1-0.1)2 +3* 300*0.12*(1-0.1)+50*0.13

  4. t=0.5

  5. x = -20*(1-0.5)3 + 3*200 * 0.1*(1-0.5)2 +3* 250*0.12*(1-0.5)+300*0.13

  6. y = 600*(1-0.5)3 + 3*500 * 0.1*(1-0.5)2 +3* 300*0.12*(1-0.5)+50*0.13

  7. ……


这样,所有点的集合为这样的一条贝塞尔曲线。

既然画线知道了,我们把所有点做为飞机的做标来设置就可以了,并且t与时间相匹配,比如setinterval,设置300毫秒执行一次飞机定位,并且t+=0.1,于是就完成了一个动画,如果想让动画更连贯,最好用requestAnimationFrame,并且分段更细一点。


这样设计只要做出满意的动画轨迹,然后把关键点的做标给技术,马上动画就完成了。并且t最好也用缓动来完成,因为飞机开始起飞慢,中间快,最后停下又慢。

>>>>  反三角函数

但是飞机飞行的时候不是一直水平的,它是按照曲线的切线运动的。这个怎么实现呢?就要用我们的反三角函数了。

不对,是反→



我们知道当前的坐标,又知道上一个坐标,然后yt-y0和xt-x0就是三角函数的值,把这个用反三角函数就可以求出角度(其实是弧度)了,然后让其旋转。

 
  1. let r = Math.atan2(p.y - yt, p.x - xt);

  2. _context.rotate(r);


记住,一定要用atan2不要用atan,那个只能算出π/2之内的值。

>>>>  总结

总的来说,我们的思维要开阔一些。其实自己深度不够没事,我们可以增加我们的深度;最怕的是都不知道可以往某个方面去想,所以我们要多增加点交流,技术储备就会越来越多。


点击阅读原文,下载纸飞机demo


---------------END----------------

后续的内容同样精彩

长按关注“IT实战联盟”哦



全部评论: 0

    我有话说:

    微信程序微商城(七):动态API实现商品分类

    微信程序商品分类页面布局并且调用动态API获取数据并加载

    京东到家订单中心系统mysql到es的转化之路

    原文:https://www.toutiao.com/i6796507988602389006 京东到家订单中心系统业务中,无论是外部商家的订单生产,或是内部上下游系统的依赖,订单查询的调用量都非常

    开源资讯」BookChat v2.4 发布,通用书籍阅读微信程序

    BookChat - 面向程序员开源书籍和文档阅读学习程序

    微信程序抖音实战-首页(下)

    抖音程序首页动态数据获取

    A3Mall v1.5.2 发布,免费开源的 PHP 程序商城系统

    项目介绍 A3Mall商城系统是基于ThinkPhp6.0+Vue开发的一套移动电商系统, 支持微信公众号商城、H5商城、程序商城,支持多种营销活动,优惠劵、订单活动、团购、秒杀、会员特价、积分

    微信程序 - iconfont 图标字体

    你还使用图片作为程序的图标?大猪告诉大家如何程序上使用iconfont字体图标

    微信程序实战篇:如何解决https域名问题 ?

    开发自己的微信程序绕不开https问题,为了能程序中调用我们自己的API服务请打开看一看吧!!!

    微信程序电商实战-入门篇

    程序开发工具有新版本更新啦!开发体验更好了,接下来一起为电商程序做一下准备前期准备工作~~

    微信程序微商城(四):动态API实现商品详情页(上)

    1、实现商品详情页面布局(这篇实现3个模块,头部商品图片轮播、商品价格和商品描述、商品详情展示) 2、根据用户点击不同的商品请求API动态加载数据

    微信程序电商实战-首页(上)

    上一篇:微信程序电商实战-入门篇 嗨,大家好!经过近两周的精心准备终于开始微信程序电商实战之路喽。那么最终会做成什么样呢?好了,不啰嗦了 我们先看首页长什么样吧!   首页效果图

    微信程序微商城(一):https框架搭建并实现导航功能

    本文将带领大家搭建https的程序框架,并实现动态获取数据展示效果!

    微信程序实战篇:程序之页面数据传递

    我们程序的时候经常会遇到子页面向主页面回传数据或者普通页面跳转到tabBar 页面携带数......

    微信程序微商城(五):动态API实现商品详情页(下)

    加入购物车悬浮框、商品数量、价格计算、收藏和加入购物车功能开发

    精品推荐:微信程序常见的UI框架/组件库

    想要开发出一套高质量的程序,运用框架,组件库是省时省力省心必不可少一部分,随着程序日渐火爆,各种不同类型

    微信程序电商实战-商品列表流式布局

    今天给大家分享一下微信程序中商品列表的流式布局方式,根据文章内容操作就可以看到效果哦~~~

    微信程序电商实战-购物车(上)

    好久没更新程序电商实战的文章了,是因为最近一直做整体架构调整,一些准备工作也是比较耗费时间的。这几天将会有新版的 程序电商教程推出.......

    京东技术:使用JDReact程序双向转换

    JDReact是京东商城前台产品研发部推出的多端融合开发框架。