在一次项目开发中,有个应用需求,就是不仅展示用户答题之后的分数和测评等级,还要利用动画圆圈的形式展示用户完成比。

首先一般先想到的就是利用canvas绘图,因为如果用CSS来制作的话会很麻烦,而且还要配合脚本一起完成才行。

HTML5 <canvas> 标签用于绘制图像(通过脚本,通常是 JavaScript)。

不过,<canvas> 元素本身并没有绘制能力(它仅仅是图形的容器) - 您必须使用脚本来完成实际的绘图任务。

getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性。

getContext("2d") 对象属性和方法,可用于在画布上绘制文本、线条、矩形、圆形等等。

具体可查看w3c官网文档里给出的介绍:http://www.w3school.com.cn/tags/html_ref_canvas.asp

还有小程序官网平台给出的文档:https://developers.weixin.qq.com/miniprogram/dev/component/canvas.html?search-key=arc


好,现在开始正式绘制这个需求。

canvas其中有一个属性是绘图的关键,那就是它的arc属性,具体是这样的:

   let cxt_arc = wx.createCanvasContext('canvasArc');//创建并返回绘图上下文context对象。
   /*
   cxt_arc.arc(x, y, r, sAngle, eAngle, counterclockwise);
   x                  Number    圆的x坐标
   y                  Number    圆的y坐标
   r                  Number    圆的半径
   sAngle             Number    起始弧度,单位弧度(在3点钟方向)
   eAngle             Number    终止弧度
   counterclockwise   Boolean   可选。指定弧度的方向是逆时针还是顺时针。默认是false,即顺时针。
   */

这里尤其要特别注意的是第四个参数,第四个参数代表绘图的起始弧度,并且默认是从三点钟方向开始的,所以如果想从12点钟方向开始绘图的话,需要将第四个参数设置为:- Math.PI * 1 / 2。意思很明显,因为第六个参数是指绘图的方向,如果设置为false,那就是顺时针,一般也设置为顺时针,因为12点钟是在3点钟的逆时针方向上,所以第四个参数应该为负数,即需要负整个圆的四分之一,因为2*PI代表的是整个圆,那么1/2就是四分之一圆了,所以要想从12点钟开始绘图,那么第四个参数需设置为:- Math.PI * 1 / 2。

好,接下来直接上代码:

上代码之前,这里给三个个提示:

1.就是脚本里面设置的一些关系像素的数据默认都是px,而现在小程序为了兼容各个移动终端,给出了一个新的像素单位,就是rpx。但是canvas绘图是与脚本一起完成的,所以这里建议大家还是统一像素单位比较好;

2.下面我是用定时器setInterval实现的,一定要注意的是,一旦启用定时器,那么在实现你的功能之后,一定要记得关闭;

3.微信小程序里有一个用于展示进度的组件<progress>,大家可以直接调用,但是比较局限。链接:https://developers.weixin.qq.com/miniprogram/dev/component/progress.html?search-key=progress

HTML部分:

<view class='circleBar'>
  <view class="wrap">
    <view class="top">
        <canvas class="cir" style=' width:106px; height:106px;' canvas-id="canvasArc"></canvas>
        <view class="centerWord">{{resultComment}}</view>
    </view>
  </view>
</view>

CSS部分:

/* 圆形进度条 */

.circleBar {
  width: 100%;
  height: auto;
  overflow: hidden;
  position: relative;
}

.cir {
  display: inline-block;
  background-color: #fff;
  border-radius: 100%;
}

.top {
  text-align: center;
}

.centerWord {
  width: 100%;
  position: absolute;
  top: 40px;
  left: 0;
  text-align: center;
  color: #3686ff;
}

JS部分:

Page({

  /**
   * 页面的初始数据
   */
  data: {
    timer: ''
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    // 页面初始化 options为页面跳转所带来的参数
    let that = this;
    // 以下两个是测试数据
    let totalItems = 100;
    let rightItems = 80;
    let completePercent = parseInt((rightItems / totalItems) * 100);
    that.getResultComment(completePercent);
    that.showScoreAnimation(rightItems, totalItems);
  },

  showScoreAnimation: function (rightItems, totalItems) {
   /*
   cxt_arc.arc(x, y, r, sAngle, eAngle, counterclockwise);
   x	                    Number	  圆的x坐标
   y	                    Number	  圆的y坐标
   r	                    Number	  圆的半径
   sAngle	            Number	  起始弧度,单位弧度(在3点钟方向)
   eAngle	            Number	  终止弧度
   counterclockwise	    Boolean	  可选。指定弧度的方向是逆时针还是顺时针。默认是false,即顺时针。
   */
    let that = this;
    let copyRightItems = 0;
    that.setData({
      timer: setInterval(function () {
        copyRightItems++;
        if (copyRightItems == rightItems) {
          clearInterval(that.data.timer)
        } else {
          // 页面渲染完成
          // 这部分是灰色底层
          let cxt_arc = wx.createCanvasContext('canvasArc');//创建并返回绘图上下文context对象。
          cxt_arc.setLineWidth(6);//绘线的宽度
          cxt_arc.setStrokeStyle('#d2d2d2');//绘线的颜色
          cxt_arc.setLineCap('round');//线条端点样式
          cxt_arc.beginPath();//开始一个新的路径
          cxt_arc.arc(53, 53, 50, 0, 2 * Math.PI, false);//设置一个原点(53,53),半径为50的圆的路径到当前路径
          cxt_arc.stroke();//对当前路径进行描边
          //这部分是蓝色部分
          cxt_arc.setLineWidth(6);
          cxt_arc.setStrokeStyle('#3ea6ff');
          cxt_arc.setLineCap('round')
          cxt_arc.beginPath();//开始一个新的路径
          cxt_arc.arc(53, 53, 50, -Math.PI * 1 / 2, 2 * Math.PI * (copyRightItems / totalItems) - Math.PI * 1 / 2, false);
          cxt_arc.stroke();//对当前路径进行描边
          cxt_arc.draw();
        }
      }, 20)
    })
  },

  getResultComment: function (completePercent) {
    let that = this;
    switch (true) {
      case completePercent < 60:
        that.setData({
          resultComment: "渣渣"
        })
        break;
      case completePercent >= 60 && completePercent <= 69:
        that.setData({
          resultComment: "学弱"
        })
        break;
      case completePercent >= 70 && completePercent < 80:
        that.setData({
          resultComment: "中等"
        })
        break;
      case completePercent >= 80 && completePercent < 90:
        that.setData({
          resultComment: "良好"
        })
        break;
      case completePercent >= 90 && completePercent < 95:
        that.setData({
          resultComment: "优秀"
        })
        break;
      case completePercent >= 95 && completePercent < 100:
        that.setData({
          resultComment: "学霸"
        })
        break;
      case completePercent >= 100:
        that.setData({
          resultComment: "学神"
        })
        break;
    }
  },
})

下来是效果展示图:




Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐