小程序也能做这么精致的动效?看完我给大神献上了膝盖…… | 开发

作者:牛咖

小池是一款具有吸引力的预算应用程序,允许用户通过轻松录入,享受记账的幸福,并为用户提供大量非凡的记录输入!

在这篇文章中,会详细介绍如何做出如图的交互效果,我们将根据 canvas 画布渲染圆球所需的步骤进行讲解。

如 GIF 图中所展示的效果,黏糊糊的粘连的路径是由 metaball 函数来创建出的,然后根据返回的路径坐标值,再基于贝塞尔曲线使用 canvas 画布绘制而成。

实现原理

可以看到,这个交互效果主要由两个圆球组成,它们之间存在三种情况:完全重合,完全分离和有交叠部分。

在两圆完全重合时,小圆不会出现;当两圆之间距离超出设置的最大连接距离时,两圆会完全分离不接触;而重点在于第三种情况,两圆有接触但没有完全重合。

当第三种情况发生时,我们就需要考虑以下几点:

  • 两圆有接触没有完全重叠,会出现两条弧形的轨迹,在这里称它为连接器。
  • 两圆之间的切线就是连接器的最宽处(如图1-1),通过 metaball 函数计算出四个切点位置,假设切点分别为 p1,p2,p3,p4。(考虑到图形效果,切点位置还与控制因子 v 相关,当 v=0.5 时效果最佳)
  • 把梯形形状的连接器转换为弧形轨迹(如图1-1),需要 metaball 函数计算出四个控制点位置,假设控制点分别为 h1,h2,h3,h4。
  • 当发生移动时,这八个点的状态如图 1-3 所示。
  • metaball 函数的功能就是通过计算出这八个点的坐标,并返回出来。

左:图 1-1,右:图 1-2

图 1-3

实现方法

下表为 metaball 函数的参数与返回值信息:

了解 metaball 函数的实现原理后,下面讲解使用 canvas 来绘制图形的步骤:

1. 引入 metaball 函数

import metaball from 'utils/metaball.js'

2. 设置大圆/小圆的半径和中心点坐标

radius1 = r1
radius2 = r2
center1 = { x: x1, y: y1 }
center2 = { x: x2, y: y2 }

3. 设置两圆分离的最大距离

maxDist = radius1 + radius2 * 2;

4. 创建 canvas 绘图上下文(传入定义在 <canvas/> 的 canvas-id)

ctx = wx.createCanvasContext('canvas');

值得在注意的是,在手指触摸动作开始事件 touchstart 触发的事件回调函数中:

  • 通过参数 e.touches[0].x/y 获取当前触摸点位置信息,并赋值给小圆的圆心位置变量。
  • 在定时器中,每次要先清除画布,然后调用 metaball 函数,使用数组变量 a 接收 metaball 函数的返回值,并对返回结果进行如下判断:
center2.x = e.touches[0].x 
center2.y = e.touches[0].y 
setInterval(() => {
      ctx.clearRect(0, 0, width, height);
      a = metaball(
        radius1,
        radius2,
        [center1.x, center1.y],
        [center2.x, center2.y],
        maxDist
      );
      if (a.length <= 1) {} if (a.length >= 2) {
        ctx.beginPath()
        ctx.setFillStyle('#ffffff')
        ctx.arc(center2.x,center2.y,radius2,0,Math.PI * 2,true)
        ctx.fill()
      }
      if (a.length > 2) {
        ctx.beginPath()
        ctx.setFillStyle('#ffffff')
        // [p1, h1, h3, p3, p4, h4, h2, p2]
        ctx.moveTo(a[7][0], a[7][1])
        ctx.lineTo(a[0][0], a[0][1])
        ctx.bezierCurveTo(
          a[1][0],
          a[1][1],
          a[2][0],
          a[2][1],
          a[3][0],
          a[3][1]
        )
        ctx.lineTo(a[4][0], a[4][1])
        ctx.bezierCurveTo(
          a[5][0],
          a[5][1],
          a[6][0],
          a[6][1],
          a[7][0],
          a[7][1]
        )
        ctx.fill()
      }
      ctx.draw()
    }, 20)
  • 手指触摸后移动事件 touchmove 触发的事件回调函数中监听手指移动事件,将当前的触摸点位置信息赋值给小圆的圆心位置变量。
center2.x = e.touches[0].x center2.y = e.touches[0].y
  • 手指触摸动作结束事件 touchend 触发的事件回调函数中把小圆的圆心位置重置到大圆的圆心位置。
center2.x = center1.x center2.y = center1.y

以上就是「小池记账」小程序的主页交互效果制作,当你认真去思考去完善一个小程序时,你会发现,原来小程序也可以很美。

「小池记账」小程序使用链接

https://minapp.com/miniapp/6042/

相关阅读

/ 知晓程序

微信,我小鸡忍你很久了…… | 开发

原文发布于微信公众号 - 知晓程序(zxcx0101)

原文发表时间:2018-04-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏游戏开发那些事

【Unity游戏开发】UGUI不规则区域点击的实现

  马三从上一家公司离职了,最近一直在出去面试,忙得很,所以这一篇博客拖到现在才写出来。马三在上家公司工作的时候,曾处理了一个UGUI不规则区域点击的问题,制作...

1143
来自专栏Android群英传

onTouchEvent(二) 使用Scroller实现黏性滑动的ScrollView

663
来自专栏文武兼修ing——机器学习与IC设计

基于OpenCv-Python的视频组合

step0:概述 动机:手头有数个20秒左右的短视频(守望先锋最佳镜头),期望能组合成一个长视频 ? 英雄不朽,图片来源http://upload-images...

3828
来自专栏Coding迪斯尼

VUE+WebPack游戏设计:&#39;乘法防线&#39;游戏设计

1002
来自专栏极客猴

Python 绘图,我只用 Matplotlib(三)—— 柱状图

上篇文章,我已经讲解绘制图像大致步骤,接下来的系列文章将分别对各种图形做讲解。其实就是了解各个图种的绘图 API。文章就讲解第一种图形,柱状图。

1002
来自专栏菩提树下的杨过

silverlight:如何在图片上挖个洞?

一、不写代码的方法:用Blend 看图说话: 这是待处理的图片win7 ? 在win7上,画一个矩形,再用钢笔随便画个封闭的path ? 将矩形与path合...

17710
来自专栏Android先生

RecyclerView 梳理:点击&amp;长按事件、分割线、拖曳排序、滑动删除

这次主要是把 RecyclerView 比较常用的基本的点,在这里集中整理一下。从这篇文章主要梳理以下几点:

953
来自专栏向治洪

Android开发之Path详解

在制作高级控件的时候往往会用到很多的高级数学公式,例如本文将要讲到的贝塞尔曲线,结合Path使用,可以实现很多复杂的动画效果。 一.Path常用方法表 作...

3015
来自专栏清墨_iOS分享

OpenGLES-02 绘制基本图元(点、线、三角形)

在绘制之前,我们需要了解下面的知识: 一、渲染管线 下图中展示整个OpenGL ES 2.0可编程渲染管线 ? 渲染管线.png 图中Vertex Shade...

3409
来自专栏移动开发的那些事儿

TextView实现自定义换行以及缩进文字的格式化对齐

我们通常在自定义控件的时候会遇到不想用系统默认的文字换行,而需要根据自己的需求来实现文字的换行,原理如下:

822

扫码关注云+社区