使用小程序实现图表(圆饼图、柱状图、折线图)

一、文章前言

此文主要实现在小程序上将数据通过各种图表的方式进行展现,增加用户体验。

二、开发前的准备

2.1、下载及安装微信Web开发者工具。
2.2、准备用于界面展示的JSON数据。

三、开发步骤

1、折线图

在这里插入图片描述
3.1、打开微信开发者工具,新建项目,选择不使用模板、不使用云服务。
在这里插入图片描述
3.2、在pages文件夹下面创建一个文件夹并新建对应的page文件。
在这里插入图片描述

3.3、在utils文件夹新建一个JS文件,并定义对应的函数,作用是在onLoad时就定义画布的初始高度及宽度。

/*
注意,使用前需要初始化(传入系统宽度值)
  示例:
  onLoad: function () {
    var that = this;
    wx.getSystemInfo({
      success: function (res) {
        dimen.init(res.windowWidth);
        canvasWidth = dimen.rpx2px(710); // 必须在初始化后在使用这些函数方法,不然用下列函数算出的值都是错的
        canvasHeight = dimen.rpx2px(400);
      }
    });
  }
*/

var width = 375;
var r = 0.5;  // 比率

function init(w) {
    
    
    width = w;
    r = width / 750.0;
}

function px2rpx(px) {
    
    
    var rpx = px / r;
    return rpx;
}

function rpx2px(rpx) {
    
    
    var px = rpx * r;
    return px;
}

module.exports = {
    
    
    init: init,
    px2rpx: px2rpx,
    rpx2px: rpx2px
}

3.4、目前只是做测试,还没有接入API,所以再次定义一个JS用于存放展示的JSON数据。
在这里插入图片描述

var visitTrend = [
  {
    
    
    "ref_date": "20170701",
    "session_cnt": 8,
    "visit_pv": 49,
    "visit_uv": 4,
    "visit_uv_new": 1,
    "stay_time_uv": 73.75,
    "stay_time_session": 36.875,
    "visit_depth": 3.25
  },
  {
    
    
    "ref_date": "20170702",
    "session_cnt": 10,
    "visit_pv": 81,
    "visit_uv": 8,
    "visit_uv_new": 2,
    "stay_time_uv": 351.25,
    "stay_time_session": 281,
    "visit_depth": 3.5
  },
  {
    
    
    "ref_date": "20170703",
    "session_cnt": 17,
    "visit_pv": 58,
    "visit_uv": 10,
    "visit_uv_new": 4,
    "stay_time_uv": 187.3,
    "stay_time_session": 110.1765,
    "visit_depth": 2.4706
  },
  {
    
    
    "ref_date": "20170704",
    "session_cnt": 2,
    "visit_pv": 6,
    "visit_uv": 2,
    "visit_uv_new": 0,
    "stay_time_uv": 17.5,
    "stay_time_session": 17.5,
    "visit_depth": 3
  },
  {
    
    
    "ref_date": "20170705",
    "session_cnt": 9,
    "visit_pv": 78,
    "visit_uv": 5,
    "visit_uv_new": 2,
    "stay_time_uv": 90.2,
    "stay_time_session": 50.1111,
    "visit_depth": 4.6667
  },
  {
    
    
    "ref_date": "20170706",
    "session_cnt": 21,
    "visit_pv": 155,
    "visit_uv": 10,
    "visit_uv_new": 4,
    "stay_time_uv": 173.8,
    "stay_time_session": 82.7619,
    "visit_depth": 3.4286
  },
  {
    
    
    "ref_date": "20170707",
    "session_cnt": 17,
    "visit_pv": 118,
    "visit_uv": 11,
    "visit_uv_new": 4,
    "stay_time_uv": 67.7273,
    "stay_time_session": 43.8235,
    "visit_depth": 3.8824
  },
  {
    
    
    "ref_date": "20170708",
    "session_cnt": 32,
    "visit_pv": 197,
    "visit_uv": 18,
    "visit_uv_new": 10,
    "stay_time_uv": 90.7222,
    "stay_time_session": 51.0313,
    "visit_depth": 3.5313
  },
  {
    
    
    "ref_date": "20170709",
    "session_cnt": 25,
    "visit_pv": 138,
    "visit_uv": 11,
    "visit_uv_new": 6,
    "stay_time_uv": 80.8182,
    "stay_time_session": 35.56,
    "visit_depth": 3.64
  },
  {
    
    
    "ref_date": "20170710",
    "session_cnt": 20,
    "visit_pv": 141,
    "visit_uv": 13,
    "visit_uv_new": 4,
    "stay_time_uv": 270.5385,
    "stay_time_session": 175.85,
    "visit_depth": 3.3
  },
  {
    
    
    "ref_date": "20170711",
    "session_cnt": 11,
    "visit_pv": 116,
    "visit_uv": 9,
    "visit_uv_new": 3,
    "stay_time_uv": 116.8889,
    "stay_time_session": 95.6364,
    "visit_depth": 4.6364
  },
  {
    
    
    "ref_date": "20170712",
    "session_cnt": 12,
    "visit_pv": 90,
    "visit_uv": 7,
    "visit_uv_new": 2,
    "stay_time_uv": 122,
    "stay_time_session": 71.1667,
    "visit_depth": 3
  },
  {
    
    
    "ref_date": "20170713",
    "session_cnt": 27,
    "visit_pv": 214,
    "visit_uv": 12,
    "visit_uv_new": 5,
    "stay_time_uv": 72,
    "stay_time_session": 32,
    "visit_depth": 4.2593
  },
  {
    
    
    "ref_date": "20170714",
    "session_cnt": 73,
    "visit_pv": 627,
    "visit_uv": 29,
    "visit_uv_new": 23,
    "stay_time_uv": 123.2759,
    "stay_time_session": 48.9726,
    "visit_depth": 4.0959
  },
  {
    
    
    "ref_date": "20170715",
    "session_cnt": 48,
    "visit_pv": 394,
    "visit_uv": 18,
    "visit_uv_new": 11,
    "stay_time_uv": 139.7222,
    "stay_time_session": 52.3958,
    "visit_depth": 3.75
  },
  {
    
    
    "ref_date": "20170716",
    "session_cnt": 34,
    "visit_pv": 289,
    "visit_uv": 18,
    "visit_uv_new": 9,
    "stay_time_uv": 91.2222,
    "stay_time_session": 48.2941,
    "visit_depth": 4.3529
  },
  {
    
    
    "ref_date": "20170717",
    "session_cnt": 55,
    "visit_pv": 595,
    "visit_uv": 24,
    "visit_uv_new": 16,
    "stay_time_uv": 235.8333,
    "stay_time_session": 102.9091,
    "visit_depth": 4.3636
  },
  {
    
    
    "ref_date": "20170718",
    "session_cnt": 18,
    "visit_pv": 82,
    "visit_uv": 12,
    "visit_uv_new": 3,
    "stay_time_uv": 57.3333,
    "stay_time_session": 38.2222,
    "visit_depth": 2.7778
  },
  {
    
    
    "ref_date": "20170719",
    "session_cnt": 57,
    "visit_pv": 413,
    "visit_uv": 20,
    "visit_uv_new": 8,
    "stay_time_uv": 136.4,
    "stay_time_session": 47.8596,
    "visit_depth": 3.8772
  },
  {
    
    
    "ref_date": "20170720",
    "session_cnt": 41,
    "visit_pv": 299,
    "visit_uv": 14,
    "visit_uv_new": 10,
    "stay_time_uv": 103.1429,
    "stay_time_session": 35.2195,
    "visit_depth": 3.5366
  },
  {
    
    
    "ref_date": "20170721",
    "session_cnt": 43,
    "visit_pv": 349,
    "visit_uv": 27,
    "visit_uv_new": 13,
    "stay_time_uv": 80.8519,
    "stay_time_session": 50.7674,
    "visit_depth": 3.6744
  },
  {
    
    
    "ref_date": "20170722",
    "session_cnt": 76,
    "visit_pv": 565,
    "visit_uv": 35,
    "visit_uv_new": 20,
    "stay_time_uv": 76.5429,
    "stay_time_session": 35.25,
    "visit_depth": 3.75
  },
  {
    
    
    "ref_date": "20170723",
    "session_cnt": 75,
    "visit_pv": 509,
    "visit_uv": 34,
    "visit_uv_new": 18,
    "stay_time_uv": 122.6765,
    "stay_time_session": 55.6133,
    "visit_depth": 3.3733
  },
  {
    
    
    "ref_date": "20170724",
    "session_cnt": 74,
    "visit_pv": 552,
    "visit_uv": 34,
    "visit_uv_new": 18,
    "stay_time_uv": 106.5294,
    "stay_time_session": 48.9459,
    "visit_depth": 3.8514
  },
  {
    
    
    "ref_date": "20170725",
    "session_cnt": 33,
    "visit_pv": 348,
    "visit_uv": 21,
    "visit_uv_new": 9,
    "stay_time_uv": 109.9048,
    "stay_time_session": 69.9394,
    "visit_depth": 4.2424
  },
  {
    
    
    "ref_date": "20170726",
    "session_cnt": 93,
    "visit_pv": 663,
    "visit_uv": 27,
    "visit_uv_new": 12,
    "stay_time_uv": 172.9259,
    "stay_time_session": 50.2043,
    "visit_depth": 3.3871
  },
  {
    
    
    "ref_date": "20170727",
    "session_cnt": 117,
    "visit_pv": 900,
    "visit_uv": 44,
    "visit_uv_new": 21,
    "stay_time_uv": 311.5909,
    "stay_time_session": 117.1795,
    "visit_depth": 3.6496
  },
  {
    
    
    "ref_date": "20170728",
    "session_cnt": 83,
    "visit_pv": 566,
    "visit_uv": 41,
    "visit_uv_new": 21,
    "stay_time_uv": 154.9024,
    "stay_time_session": 76.5181,
    "visit_depth": 3.4699
  },
  {
    
    
    "ref_date": "20170729",
    "session_cnt": 109,
    "visit_pv": 786,
    "visit_uv": 52,
    "visit_uv_new": 35,
    "stay_time_uv": 264.5577,
    "stay_time_session": 126.211,
    "visit_depth": 3.4495
  },
  {
    
    
    "ref_date": "20170730",
    "session_cnt": 86,
    "visit_pv": 554,
    "visit_uv": 42,
    "visit_uv_new": 19,
    "stay_time_uv": 80.1667,
    "stay_time_session": 39.1512,
    "visit_depth": 3.0581
  },
  {
    
    
    "ref_date": "20170731",
    "session_cnt": 109,
    "visit_pv": 850,
    "visit_uv": 49,
    "visit_uv_new": 32,
    "stay_time_uv": 95.0408,
    "stay_time_session": 42.7248,
    "visit_depth": 3.6514
  }
]

var visitDistribution = [
  {
    
    
    key: 16,
    value: 175
  },
  {
    
    
    key: 15,
    value: 333
  },
  {
    
    
    key: 14,
    value: 87
  },
  {
    
    
    key: 13,
    value: 67
  },
  {
    
    
    key: 12,
    value: 230
  },
  {
    
    
    key: 11,
    value: 111
  },
  {
    
    
    key: 10,
    value: 99
  },
  {
    
    
    key: 9,
    value: 10
  },
  {
    
    
    key: 8,
    value: 44
  },
  {
    
    
    key: 7,
    value: 33
  },
  {
    
    
    key: 6,
    value: 22
  },
  {
    
    
    key: 4,
    value: 6
  },
  {
    
    
    key: 3,
    value: 322
  },
  {
    
    
    key: 2,
    value: 16
  },
  {
    
    
    key: 1,
    value: 164
  }]

var userPortraitForGender = [
  {
    
    
    id: 0,
    name: "未知",
    ref_date: "20170731",
    value: 1
  },
  {
    
    
    id: 1,
    name: "男",
    ref_date: "20170731",
    value: 14
  },
  {
    
    
    id: 2,
    name: "女",
    ref_date: "20170731",
    value: 6
  }
]

var userPortraitForAge = [
  {
    
    
    id: 0,
    name: "未知",
    ref_date: "20170801",
    value: 1
  },
  {
    
    
    id: 1,
    name: "17岁以下",
    ref_date: "20170801",
    value: 0
  },
  {
    
    
    id: 2,
    name: "18-24岁",
    ref_date: "20170801",
    value: 35
  },
  {
    
    
    id: 3,
    name: "25-29岁",
    ref_date: "20170801",
    value: 32
  },
  {
    
    
    id: 4,
    name: "30-39岁",
    ref_date: "20170801",
    value: 36

  },
  {
    
    
    id: 5,
    name: "40-49岁",
    ref_date: "20170801",
    value: 6
  },
  {
    
    
    id: 6,
    name: "50岁以上",
    ref_date: "20170801",
    value: 4
  }]

module.exports = {
    
    
  visitTrend: visitTrend,
  visitDistribution: visitDistribution,
  userPortraitForGender: userPortraitForGender,
  userPortraitForAge: userPortraitForAge
}

3.5、回到最开始创建的那个page,实现对应的wxml跟wxss来展示数据。

<view class="margin-left__20 margin-right__20">
  <view class="margin-top__20 margin-bottom__20 font-size__large">
    <text>30天访问趋势</text>
  </view>
  <view class="flex__row">
    <view class="flex__row align-items__center margin-bottom__20 margin-right__20">
      <view class="width__30 height__30  margin-right__10 radius__30 bord__white bg-color__27A5C2"></view>
      <text>访问人数</text>
    </view>
    <view class="flex__row align-items__center margin-bottom__20">
      <view class="width__30 height__30 margin-right__10 radius__30  bord__white bg-color__1E3A50 "></view>
      <text>新用户数</text>
    </view>
  </view>
  <canvas canvas-id="line-canvas" id="line-canvas"></canvas>
</view>
#line-canvas {
      
      
  width: 710rpx;
  height: 400rpx;
  background: #192429;
}
#navigationBarLine {
      
      
  position: fixed;
  height: 1px;
  top: 0px;
  width: 100%;
  background-color: #e5e5e5;
  z-index: 100;
}

#tabBarLine {
      
      
  position: fixed;
  height: 1px;
  bottom: 0px;
  width: 100%;
  background-color: #e5e5e5;
}

.divider__solid {
    
    
  height: 0;
  border-bottom: 1px solid #e5e5e5;
}

.divider__dashed {
    
    
  height: 0;
  border-bottom: 1px dashed #e5e5e5;
}
.cell-hover {
    
    
  /*background-color: rgba(0, 0, 0, 0.1);*/
  opacity: 0.7;
}

.icon-hover {
    
    
  opacity: 0.7;
}

.hot__article-hover {
    
    
  /*color: #1e6bc4;*/
  opacity: 0.7;
}
.widget__arrow {
    
    
  width: 15rpx;
  height: 26rpx;
  flex-shrink: 0;
  padding-left: 20rpx;
}

.overflow-y__auto {
    
    
  overflow-y: auto;
}

3.6、实现对应的JS,这里记得要在onLoad函数初始化画布的宽高。

在这里插入图片描述

  onLoad: function () {
    
    
    var that = this;
    wx.getSystemInfo({
    
    
      success: function (res) {
    
    
        dimen.init(res.windowWidth);
        canvasWidth_line = dimen.rpx2px(710);    // 折线图的画布宽度
        canvasHeight_line = dimen.rpx2px(400);   // 折线图的画布高度
      }
    });

    this.loadForVisitTrend();
  },
   /* 画访问人数的折线 */
  drawVisitUvLine: function (list, count) {
    
    
    list.forEach(function (data, i, array) {
    
    
      if (data.visit_uv > maxUV) {
    
    
        maxUV = data.visit_uv;
      }
    });

    ratioX = (canvasWidth_line - dimen.rpx2px(30)) / list.length;
    ratioY = (canvasHeight_line - dimen.rpx2px(80)) / maxUV;

    if (count < list.length - 1) {
    
    
      // 当前点坐标
      var currentPoint = {
    
    
        x: count * ratioX + dimen.rpx2px(40),
        y: (canvasHeight_line - list[count].visit_uv * ratioY) - dimen.rpx2px(40)
      };
      // 下一个点坐标
      var nextPoint = {
    
    
        x: (count + dimen.rpx2px(2)) * ratioX + dimen.rpx2px(40),
        y: (canvasHeight_line - list[count + 1].visit_uv * ratioY) - dimen.rpx2px(40)
      }

      // 开始路径
      context_line.beginPath();

      // 画线:移动到当前点
      context_line.moveTo(currentPoint.x, currentPoint.y);
      // 画线:画线到下个点
      context_line.lineTo(nextPoint.x, nextPoint.y);
      // 设置线宽度
      context_line.setLineWidth(dimen.rpx2px(2));
      // 设置线颜色
      context_line.setStrokeStyle('white');
      // 描线
      context_line.stroke();

      // 填充内容:竖直往下,至x轴
      context_line.lineTo(nextPoint.x, canvasHeight_line - dimen.rpx2px(40));
      // 填充内容:水平往左,至上一个点的在x轴的垂点
      context_line.lineTo(currentPoint.x, canvasHeight_line - dimen.rpx2px(40));
      // 设置填充颜色
      context_line.setFillStyle('#27A5C2');

      // 实现闭合与x轴之前的区域
      context_line.fill();
    }
  },
  /* 画访问人数的圆圈 */
  drawVisitUvDot: function (list, count) {
    
    
    if (count < list.length) {
    
    
      // 当前点坐标
      var currentPoint = {
    
    
        x: count * ratioX + dimen.rpx2px(40),
        y: (canvasHeight_line - list[count].visit_uv * ratioY) - dimen.rpx2px(40)
      };

      context_line.beginPath();
      context_line.arc(currentPoint.x, currentPoint.y, 2, 0, 2 * Math.PI);
      context_line.setStrokeStyle('#05DBCE');
      context_line.setFillStyle('white');
      context_line.stroke();
      context_line.fill();
    }
  },
  /* 画新用户数的折线 */
  drawVisitUvnLine: function (list, count) {
    
    
    list.forEach(function (data, i, array) {
    
    
      if (data.visit_uv > maxUV) {
    
    
        maxUV = data.visit_uv_new;
      }
    });

    ratioX = (canvasWidth_line - dimen.rpx2px(30)) / list.length;
    ratioY = (canvasHeight_line - dimen.rpx2px(80)) / maxUV;

    if (count < list.length - 1) {
    
    
      var currentPoint = {
    
    
        x: count * ratioX + dimen.rpx2px(40),
        y: (canvasHeight_line - list[count].visit_uv_new * ratioY) - dimen.rpx2px(40)
      };
      var nextPoint = {
    
    
        x: (count + dimen.rpx2px(2)) * ratioX + dimen.rpx2px(40),
        y: (canvasHeight_line - list[count + 1].visit_uv_new * ratioY) - dimen.rpx2px(40)
      }
      context_line.beginPath();
      context_line.moveTo(currentPoint.x, currentPoint.y);
      context_line.lineTo(nextPoint.x, nextPoint.y);
      context_line.setLineWidth(dimen.rpx2px(2));
      context_line.setStrokeStyle('#1E3A50');
      context_line.stroke();
      context_line.lineTo(nextPoint.x, canvasHeight_line - dimen.rpx2px(40));
      context_line.lineTo(currentPoint.x, canvasHeight_line - dimen.rpx2px(40));
      context_line.setFillStyle('#1E3A50');
      context_line.fill();
    }
  },
  /* 画新用户数的圆点 */
  drawVisitUvnDot: function (list, count) {
    
    
    if (count < list.length) {
    
    
      var currentPoint = {
    
    
        x: count * ratioX + dimen.rpx2px(40),
        y: (canvasHeight_line - list[count].visit_uv_new * ratioY) - dimen.rpx2px(40)
      };
      context_line.beginPath();
      context_line.arc(currentPoint.x, currentPoint.y, 2, 0, 2 * Math.PI);
      context_line.setStrokeStyle('#191970');
      context_line.setFillStyle('white');
      context_line.stroke();
      context_line.fill();
    }
  },
  /* 画横向参照线 */
  drawVisitBackground: function () {
    
    
    var lineCount = 5;
    var estimateRatio = 2;
    var ratio = (canvasHeight_line + dimen.rpx2px(30)) / lineCount;
    var maxPeople = ((Math.floor(Math.floor(148 / 10) / 4) + 1) * 4) * 10;
    for (var i = 0; i < lineCount; i++) {
    
    
      context_line.beginPath();
      var currentPoint = {
    
    
        x: dimen.rpx2px(40),
        y: (canvasHeight_line - i * ratio) - dimen.rpx2px(40)
      };
      // 移动到原点
      context_line.moveTo(currentPoint.x, currentPoint.y);
      // 向Y正轴方向画线
      context_line.lineTo(canvasWidth_line - dimen.rpx2px(10), (canvasHeight_line - i * ratio) - dimen.rpx2px(40));
      // 设置属性
      context_line.setLineWidth(dimen.rpx2px(2));
      // 设置颜色
      context_line.setStrokeStyle(lightGray);
      context_line.stroke();
      // 标注数值
      context_line.setFillStyle(gray);
      // 底部时间文字
      context_line.fillText(i * maxPeople / (lineCount - 1), currentPoint.x - dimen.rpx2px(40), currentPoint.y);
    }
  },
  /* 画底部日期 */
  drawDate: function (list) {
    
    
    var ref_date = "";
    var temp_ref_date1 = "";
    var temp_ref_date2 = "";

    list.forEach(function (data, i, array) {
    
    
      if (i < array.length - 1) {
    
    
        context_line.setFillStyle(gray);

        ref_date = data.ref_date.toString();
        temp_ref_date1 = ref_date.substring(4, 6) + ".";
        temp_ref_date2 = ref_date.substring(6, ref_date.length);
        ref_date = temp_ref_date1 + temp_ref_date2;

        if (i % 4 == 0) {
    
    
          context_line.fillText(ref_date, i * ratioX + dimen.rpx2px(10), canvasHeight_line - dimen.rpx2px(10));
        }
      }
    });
  },

3.7、保存编译后,即可实现对应的折线图效果。

2、柱状图

在这里插入图片描述

3.8、在pages文件夹下面再单独创建一个新的page,用于实现柱状图。
在这里插入图片描述

<view class="margin-left__20 margin-right__20">
  <view class="color__white font-size__medium margin-top__10">
    <text>用户年龄分布</text>
  </view>
  <canvas canvas-id="age-canvas" id="age-canvas" />
</view>

3.9、实现对应的wxml及wxss,部分通用的css内容可以封装一个共用的里面。

#age-canvas {
      
      
	width: 710rpx;
	height: 400rpx;
	background: #192429;
}
.flex-wrap__nowrap {
    
    
  flex-wrap: nowrap;
}

.justify-content__center {
    
    
  justify-content: center;
}

.justify-content__flex-start {
    
    
  justify-content: flex-start;
}

.justify-content__flex-end {
    
    
  justify-content: flex-end;
}

.justify-content__space-between {
    
    
  justify-content: space-between;
}

.align-items__center {
    
    
  align-items: center;
}

.text-align__center {
    
    
  text-align: center;
}

.text-align__end {
    
    
  text-align: end;
}

.display__inline-block {
    
    
  display: inline-block;
}

3.10、在js中需要引入存放数据以及数据处理的外部JS。
在这里插入图片描述

var data = require('../../../data/jsonData.js');
var dimen = require("../../../utils/loadPage.js");

3.11、需要在顶部定义画布变量及x轴及y轴的放大倍数。

const context_age = wx.createCanvasContext('age-canvas');
var canvasWidth = 0;
var canvasHeight = 0;
var ratioX = 0; // x轴放大倍数
var ratioY = 0; // y轴放大倍数
var royalBlue = '#4169E1';
var gray = '#cccccc';
var count = 0;

3.12、实现对应的JS。
在这里插入图片描述

  // 画总年龄百分比
  drawPercent: function (list) {
    
    
    // 计算全部年龄总和
    var totalAge = 0;
    list.forEach(function (data, i, array) {
    
    
      totalAge += data.value;
    });

    context_age.setFillStyle('white');
    context_age.setFontSize(dimen.rpx2px(24));
    list.forEach(function (data, i, array) {
    
    
      context_age.fillText(
        Math.floor(data.value * 10000 / totalAge) / 100 + '%',
        i * ratioX + (i == 0 ? dimen.rpx2px(50) : dimen.rpx2px(30)),
        canvasHeight - dimen.rpx2px(80) + (-data.value * dimen.rpx2px(8)));
    });
  },
  // 画柱状图 
  drawColumn: function (list, process) {
    
    
    context_age.setFillStyle(royalBlue);
    list.forEach(function (data, i, array) {
    
    
      var height = - data.value * dimen.rpx2px(8);
      height *= process;
      context_age.fillRect(
        i * ratioX + (i == 0 ? dimen.rpx2px(30) : dimen.rpx2px(14)),
        canvasHeight - dimen.rpx2px(40),
        dimen.rpx2px(50), height)
    });
  },
  // 画柱状图上面的年龄
  drawColumnNumber: function (list) {
    
    
    context_age.setFillStyle(royalBlue);
    context_age.setFontSize(dimen.rpx2px(24));
    list.forEach(function (data, i, array) {
    
    
      context_age.fillText(
        data.value, 
        i * ratioX + (i == 0 ? dimen.rpx2px(50) : dimen.rpx2px(30)), 
        canvasHeight - dimen.rpx2px(50) + (-data.value * dimen.rpx2px(8)));
    });
  },
  // 画线
  drawLine: function (list) {
    
    
    context_age.beginPath();
    context_age.setStrokeStyle(gray);
    context_age.setLineWidth(dimen.rpx2px(2));
    context_age.moveTo(0, canvasHeight - dimen.rpx2px(40));
    context_age.lineTo(canvasWidth, canvasHeight - dimen.rpx2px(40));
    context_age.stroke();  // 这行必须要写,不然线就出不来
  },
  // 画年龄文字
  drawText: function (list) {
    
    
    context_age.setFillStyle(gray);
    context_age.setFontSize(dimen.rpx2px(24));
    list.forEach(function (data, i, array) {
    
    
      context_age.fillText(
        data.name, 
        i * ratioX + (i == 0 ? dimen.rpx2px(30) : 0), 
        canvasHeight - dimen.rpx2px(10));
    });
  },

3.13、实现后可以加上动态渲染效果。
在这里插入图片描述

var Timing = {
    
    
  easeIn: function easeIn(pos) {
    
    
    return Math.pow(pos, 3);
  },

  easeOut: function easeOut(pos) {
    
    
    return Math.pow(pos - 1, 3) + 1;
  },

  easeInOut: function easeInOut(pos) {
    
    
    if ((pos /= 0.5) < 1) {
    
    
      return 0.5 * Math.pow(pos, 3);
    } else {
    
    
      return 0.5 * (Math.pow(pos - 2, 3) + 2);
    }
  },

  linear: function linear(pos) {
    
    
    return pos;
  }
};
this.Animation({
    
    
  timing: 'easeIn',
  duration: 1000,
  onProcess: function onProcess(process) {
    
    
    count++;
    that.drawColumn(list, process);
    that.draw();
  },
  onAnimationFinish: function onAnimationFinish() {
    
    
    that.drawColumnNumber(list);
    that.drawPercent(list);
    that.draw();
  }
});

3、条形图

3.14、重复上面的步骤,再次创建一个page。

<view class="margin-left__20 margin-right__20">
  <view class="margin-top__30 margin-bottom__20 font-size__large">
    <text>30天访问来源</text>
  </view>
  <canvas canvas-id="striptype-canvas" id="striptype-canvas" style="height:{
    
    {canvasHeight_striptype}}px;"/> 
</view>

在这里插入图片描述
3.15、实现对应的JS及WXML。

 // 画左侧文字
  drawText: function (list){
    
    
    var source = '';
    context_striptype.setFillStyle('#5A8DA7');
    context_striptype.setFontSize(dimen.rpx2px(24));
    list.forEach(function (data, i, array) {
    
    
      switch (data.key) {
    
    
        case 1:
          source = '小程序历史列表';
          break;
        case 2:
          source = '搜索';
          break;
        case 3:
          source = '会话';
          break;
        case 4:
          source = '二维码';
          break;
        case 5:
          source = '公众号主页';
          break;
        case 6:
          source = '聊天顶部';
          break;
        case 7:
          source = '系统桌面';
          break;
        case 8:
          source = '小程序主页';
          break;
        case 9:
          source = '附近的小程序';
          break;
        case 10:
          source = '其他';
          break;
        case 11:
          source = '模板消息';
          break;
        case 12:
          source = '客服消息';
          break;
        case 13:
          source = '公众号菜单';
          break;
        case 14:
          source = 'APP分享';
          break;
        case 15:
          source = '支付完成页';
          break;
        case 16:
          source = '长按识别二维码';
        case 17:
          source = '相册选取二维码';
          break;
        case 18:
          source = '公众号文章';
          break;
        default:
          break;
      }
      context_striptype.fillText(source, 0, i * ratioY + dimen.rpx2px(30));
      if (source.toString().length > maxStringLenth) {
    
    
        maxStringLenth = source.toString().length;
      }
    });
  },
  // 画竖线
  drawLine: function (canvasHeight) {
    
    
    context_striptype.beginPath();
    context_striptype.setStrokeStyle(gray);
    context_striptype.setLineWidth(dimen.rpx2px(2));
    context_striptype.moveTo(maxStringLenth * dimen.rpx2px(26), canvasHeight);
    context_striptype.lineTo(maxStringLenth * dimen.rpx2px(26), dimen.rpx2px(10));
    context_striptype.stroke();
  },
  // 画条形图
  drawStricptype: function (list, process) {
    
    
    context_striptype.setFillStyle('#00EFFE');
    list.forEach(function (data, i, array) {
    
    
      var width = data.value < 200 ? data.value : dimen.rpx2px(400);
      width *= process;
      context_striptype.fillRect(
        maxStringLenth * dimen.rpx2px(26) + dimen.rpx2px(2),
        i * ratioY + dimen.rpx2px(12),
        width,
        dimen.rpx2px(20));
    });
  },
  // 画条形图数值
  drawStricptypeNum: function (list) {
    
    
    context_striptype.setFontSize(dimen.rpx2px(24));
    list.forEach(function (data, i, array) {
    
    
      context_striptype.fillText(data.value,
        maxStringLenth * dimen.rpx2px(26) + dimen.rpx2px(10) + (data.value < 200 ? data.value : dimen.rpx2px(400)),
        i * ratioY + dimen.rpx2px(30));
    });
  },
  // 画百分比
  drawpercent: function (list) {
    
    
    var totalSouce = 0;
    list.forEach(function (data, i, array) {
    
    
      totalSouce += data.value;
    });
    context_striptype.setFillStyle('white');
    list.forEach(function (data, i, array) {
    
    
      context_striptype.fillText(
        (Math.floor(data.value * 10000 / totalSouce) / 100).toFixed(1) + '%',
        maxStringLenth * dimen.rpx2px(26) + dimen.rpx2px(60) + (data.value < 200 ? data.value : dimen.rpx2px(400)),
        i * ratioY + dimen.rpx2px(30));
    });
  },

猜你喜欢

转载自blog.csdn.net/weixin_42794881/article/details/127319786