Canvas 动画之支付宝价格拖动选择

(点击

上方公众号

,可快速关注)

作者:我仍旧在这里

http://segmentfault.com/a/1190000013266172

效果源码:http://github.com/supperjet/H5-Animation/tree/master/%E6%94%AF%E4%BB%98%E5%AE%9D%E4%BB%B7%E6%A0%BC%E6%8B%96%E5%8A%A8效果演示:http://codepen.io/supperjet/pen/paPVeM

今天给大家带来一个基于移动端的canvas价格选择效果。

主要功能就是拖动标尺变动价格,而且支付宝和京东金融的里也有这样的效果。

Canvas 动画之支付宝价格拖动选择

一、实现思路

整个效果的核心就是用canvas绘制的标尺。一共包括标尺主体,数字,和中间固定不变的标定轴,这几个部分都用canvas绘制。最上面的大号价格文字,因为其他地方会需要用它来计算相关的收益。所以,我们就用个DOM来呈现,这样比较方便获取。

标尺拖动的距离与价格之间有有一个映射关系,是整个效果最不好处理的部分,在具体处理到相关问题的时候我们再做分析。现在,我们先实现基础的标尺绘制。

二、标尺属性定义

我们先定义一个类叫

Rule.js

, 其具体属性如下。

Canvas 动画之支付宝价格拖动选择

现在我们来了解一下每个属性的含义:

  • x,y

    : 标尺的坐标位置

  • vx

    : 标尺的移动速度

  • ax

    : 标尺移动加速度

  • color

    : 绘制标尺线条的颜色,与文字颜色

  • scaleX,scaleY

    : 缩放比

  • markShort,markLong

    : 标尺长短线的长度

  • textHeight

    : 文字距离标尺主体的高度

  • min,max

    : 要展示的最大值和最小值

  • width

    : 标尺的像素宽度

  • step

    : 步长

  • seg

    : 段数

  • pxStep

    : 在canvas上的实际步长(单位为px)

  • minPxStep

    : 每个pxStep分10小段,每小段的实际像素宽度

  • lineBottom

    : 底部横线参数

  • lineRed

    : 标定轴参数

  • 参数比较多,但真正需要传入的参数其实并不是很多。这里我讲解一下(8)~(15)这几个参数的思路。

    min, max : 参数的作用是设置需要显示的最大金额和最小金额。这两个参数是外部传入的,比如设定用户最小能存100元,最大能存100000万元。那么min和max就分别对应100和100000。

    width : 是整个标尺的实际屏幕长度,比如你只想标尺绘制1000px,那这里就传1000就好了。

    step : 步长的含义就是每隔多少分一段,比如我们设定的最大金额为10000元, 那设置step为1000就意味着,每隔1000元表示一个小段,这也是canvas上标尺刻度需要绘制的数据。

    seg : 段数等于总金额max除以step。

    pxStep : 为真正映射到canvas上的像素步长。

    miniPxStep : 每个pxStep分为10小段,每小段的像素距离。

    lineBottom : 独立出来不和标尺刻度一起绘制,在绘制标尺的底部横线时,我是这样想的。底部横线的宽度其实就是canvas的宽度,没必要从标尺的初始画到标尺的结尾。而且为了用户体验,刻度的初始位置和结束位置都位于整个canvas的中心。所以,如果合在一起绘制,你需要先绘制一段没刻度的横线,然后再绘制刻度,到最后还要绘制一段没刻度的横线。这给无疑让绘制和后续的标尺移动变得相当麻烦。所以我把它抽出来,就是一条贯穿canvas的普通横线。

    lineRed : 标定轴,始终在canvas的中间,也独立出来不和标尺刻度一起绘制。

    属性都有了,下面添加一个draw方法,把我们的标尺绘制出来。

    三、标尺绘制

    (1) 绘制标尺刻度部分

    Canvas 动画之支付宝价格拖动选择

    这里有个截图错误,应该是

    i+=this.miniPxStep

    。这应该不难理解,就是每隔

    miniPxStep

    绘制一次线段,线段的类型根据

    n

    这个变量来确定。

    (2) 绘制标尺文字部分

    Canvas 动画之支付宝价格拖动选择

    文字的绘制不能以真实的屏幕像素为准,必须映射到金额上,所以,这里绘制的数字是

    (n/10)*this.step

    。同时,还做了一个特殊的处理,就是初始值是1,不是0。因为,我们的金额不允许输入0元。如果你不需要这个,把这里注释掉就ok了。

    (3) 绘制底部横线

    Canvas 动画之支付宝价格拖动选择

    (4) 绘制标定轴

    Canvas 动画之支付宝价格拖动选择

    这样整个标尺就完成了,rule.js文件在顶部的github中。现在我们调用一下这个文件,看看画出来的效果怎样。

    Canvas 动画之支付宝价格拖动选择

    这里我们设置了最大额度为100000元,最小额度为500元。整个标尺的长度为5000px,步长step为1000元。效果图如下:

    Canvas 动画之支付宝价格拖动选择

    让标尺偏移个200px, 比如设置:

    x:ruleX-200

    , 效果如下:

    Canvas 动画之支付宝价格拖动选择

    设置步长step为500,效果如下:

    Canvas 动画之支付宝价格拖动选择

    ok,现在静态标尺就绘制完成,下一步就要完成交互功能,让标尺能够跟随鼠标滚动,并且展示当前拖动的金额。

    四、拖动标尺

    现在我们开始实现标尺的拖动。标尺的拖动原理很简单,就是让标尺的位置跟随鼠标移动。这里为了演示方便我换成了鼠标事件,到移动端换成touch事件即可。

    首先引入我们的工具函数

    utils.js

    文件,然后定义几个变量。

    Canvas 动画之支付宝价格拖动选择

    isMouseDown

    用来判断鼠标是否抬起,

    oldX

    用来记录上一次拖动的位置,

    mouse

    是使用

    captureMouse

    返回的对象,返回鼠标在canvas上的当前位置信息。

    然后,监听canvas的鼠标事件

    mousedown,mouseup,mousemove

    。并改变rule的位置。

    Canvas 动画之支付宝价格拖动选择

    当鼠标按下时,

    isMouseDown

    变为true,

    offsetX

    在上面忘记写了,它的作用是记录鼠标按下的位置与标尺位置之间的偏移量。然后在鼠标移动时标尺的位置

    rule.x=mouse.x-offsetX

    。如果不这样做,在点击canvas并拖动标尺的一瞬间,你会发现标尺的初始位置会瞬移到鼠标点击位置,这样体验很不好,我们需要不管点击哪,标尺都会在现有的位置跟随鼠标移动。如果,无法体会,动手试一试去掉回事什么效果。

    oldX

    也很好理解,就是记录标尺上一次的位置,这里还没有用到它,后面可能会用到。现在我们把标尺的绘制写进动画函数中

    Canvas 动画之支付宝价格拖动选择

    看看动画效果如何。

    Canvas 动画之支付宝价格拖动选择

    ok,现在我们已经实现了标尺跟随鼠标的拖动。下一步,我们就把拖动的金额显示出来。

    五、金额显示

    首先,增加一个

    input

    输入框,然后获取它。

    Canvas 动画之支付宝价格拖动选择

    这里设置了输入框的最小值为标尺的最小额度,这里可以先不用管它。我们主要看

    onMouseMove

    函数

    Canvas 动画之支付宝价格拖动选择

    注意

    money

    的计算值,它为

    (centerX-rule.x)*rule.ratioScale

    (centerX-rule.x)

    比较好理解,因为,我们的标尺是从canvas的中心点绘制的。但

    rule.ratioScale

    在最开始的构造函数中并没有定义。这里需要在构造函数中加上,它的含义是每像素代表多少钱,可以认为是图形比例尺。

  • this

    .ratioScale =

    Math

    .floor(

    this

    .max /

    this

    .width)

    //比列尺

  • 那么自然,移动距离乘以比例尺就得出钱数了。我们看看效果。

    Canvas 动画之支付宝价格拖动选择

    注意到上面的效果中金额显示出现了负数,所以我们需要对移动范围做限制。让其只能在限定的最大和最小金额之间移动。

    六、移动范围限定

    对一定范围的限定主要分为两部分。一、标尺范围的限定。二、金额显示的限定。这两部分我们放在一起做。

    (1) 

    重设标尺的初始位置假设我们设置的最小金额为500元,那么初始标定轴的位置应该就是500元的位置。所以初始化标尺的位置后,我们给它重置为最小金额的位置。这时候需要把金额换算一下。

  • rule.x = centerX - rule.min / rule.ratioScale;

  • 就是把金额值得计算倒一下。

    (2) 

    限定标尺的移动范围

    Canvas 动画之支付宝价格拖动选择

    这里定义了一个检测边界值得函数,当金额小于最小投资金额时,标尺的位置为初始位置start(注意这个初始位置是已经被重置过的), 并且设置金额为最小额度。最大位置同理。然后,在

    onMouseMove

    中调用。

    Canvas 动画之支付宝价格拖动选择

    看看效果图。

    Canvas 动画之支付宝价格拖动选择

    七、输入金额移动标尺

    标尺的移动除了拖动以外,我们也希望通过金额输入框来达到。即输入金额,标尺便移动到目标金额的位置。

    Canvas 动画之支付宝价格拖动选择

    同时我们也做了边界限定,当输入的金额小于或者大于设定值时会,设置标尺的位置和输入框的显示为边界值,看看效果。

    Canvas 动画之支付宝价格拖动选择

    八、来个速度吧

    现在拖动的还比较不自然,我们想要手指离开后标尺还会继续移动,直到速度慢慢减为0。为此,新建两个变量。

  • var

    speed =

    0

    , fl =

    0.95

    ;

    //初始速度, 摩擦系数

  • 新建一个

    move

    函数,在动画循环中调用。

    Canvas 动画之支付宝价格拖动选择

    Canvas 动画之支付宝价格拖动选择

    至此,拖动输入的核心功能就开发完了。如果你要在项目中使用,另一个需要注意的事情是canvas在移动端的模糊问题,这个已经有了很多的解决方案,你只需要耐心调试就好。源码和效果在顶部哦~

    觉得本文对你有帮助?请分享给更多人

    关注「前端大全」,提升前端技能

    Canvas 动画之支付宝价格拖动选择