微信小程序-雷达图

作者: 木语先生 | 来源:发表于2018-04-28 15:30 被阅读636次
    知识普及:

    雷达图(Radar Chart),又可称为戴布拉图、蜘蛛网图(Spider Chart),是财务分析报表的一种。即将一个公司的各项财务分析所得的数字或比率,就其比较重要的项目集中划在一个圆形的图表上,来表现一个公司各项财务比率的情况,使用者能一目了然的了解公司各项财务指标的变动情形及其好坏趋向。

    如果你想找到了解H5中怎么制作,可以看一下HTML5 Canvas制作雷达图实战,我也是参考这篇文章,做了小程序的雷达图,并做了一点延伸...

    先来看看效果图
    雷达图
    开始上菜:
    //.wxml ,接下来的操作将在这个Canvas上面绘制
    
    <view class='radarContainer'>
    <canvas class='radarCanvas' canvas-id='radarCanvas'></canvas>
    </view>
    
    //.wxss
    .radarContainer{
       background-color: black;
       width:100%;
       height:420px;
       display: flex;
       justify-content:center;
        align-items: center; 
       position: relative;
       
    }
    .radarCanvas{
       width:400px;
       height:400px;
       margin: 0 auto;
       position: absolute;
    }
    
    //.js
    初始化数据:(我没写在data中)
    var numCount = 6;  //元素个数
    var numSlot = 5;  //一条线上的总节点数
    var mW = 400;  //Canvas的宽度
    var mCenter = mW / 2; //中心点
    var mAngle = Math.PI * 2 / numCount; //角度
    var mRadius = mCenter - 60; //半径(减去的值用于给绘制的文本留空间)
    //获取指定的Canvas
    var radCtx = wx.createCanvasContext("radarCanvas")
    
    //.js  模拟对战两方的数据
      data: {
        chanelArray1:[["战绩",88],["生存",30],["团战",66],["发育",90],["输出",95],["推进",88]],
        chanelArray2: [["战绩", 24], ["生存", 60], ["团战", 88], ["发育", 49], ["输出", 46], ["推进", 92]]
      },
    
    基础数据准备完成,开始画图
     // 第一步:绘制6条边
     drawEdge: function(){
       radCtx.setStrokeStyle("white")
       radCtx.setLineWidth(2)  //设置线宽
       for (var i = 0; i < numSlot; i++) {
         //计算半径
         radCtx.beginPath()
         var rdius = mRadius / numSlot * (i + 1)
         //画6条线段
         for (var j = 0; j < numCount; j++) {
           //坐标
           var x = mCenter + rdius * Math.cos(mAngle * j);
           var y = mCenter + rdius * Math.sin(mAngle * j);
           radCtx.lineTo(x, y);
         }
         radCtx.closePath()
         radCtx.stroke()
       } 
     },
    
    
    第一步.png
      // 第二步:绘制连接点
      drawLinePoint:function(){
        radCtx.beginPath();
        for (var k = 0; k < numCount; k++) {
          var x = mCenter + mRadius * Math.cos(mAngle * k);
          var y = mCenter + mRadius * Math.sin(mAngle * k);
    
          radCtx.moveTo(mCenter, mCenter);
          radCtx.lineTo(x, y);
        }
        radCtx.stroke();
      },
    
    第二步.png
        //第三步:绘制文字(文字位置可能需要微调)
        drawTextCans: function (mData){
    
          radCtx.setFillStyle("white")
          radCtx.font = 'bold 17px cursive'  //设置字体
          for (var n = 0; n < numCount; n++) {
            var x = mCenter + mRadius * Math.cos(mAngle * n);
            var y = mCenter + mRadius * Math.sin(mAngle * n);
            // radCtx.fillText(mData[n][0], x, y);
            //通过不同的位置,调整文本的显示位置
            if (mAngle * n >= 0 && mAngle * n <= Math.PI / 2) {
              radCtx.fillText(mData[n][0], x+5, y+5);
            } else if (mAngle * n > Math.PI / 2 && mAngle * n <= Math.PI) {
              radCtx.fillText(mData[n][0], x - radCtx.measureText(mData[n][0]).width-7, y+5);
            } else if (mAngle * n > Math.PI && mAngle * n <= Math.PI * 3 / 2) {
              radCtx.fillText(mData[n][0], x - radCtx.measureText(mData[n][0]).width-5, y);
            } else {
              radCtx.fillText(mData[n][0], x+7, y+2);
            }
    
          }
        },
    
    第三步.png
      //绘制红色数据区域(数据和填充颜色)
      drawRegion: function (mData,color){
          
          radCtx.beginPath();
          for (var m = 0; m < numCount; m++){
          var x = mCenter + mRadius * Math.cos(mAngle * m) * mData[m][1] / 100;
          var y = mCenter + mRadius * Math.sin(mAngle * m) * mData[m][1] / 100;
    
          radCtx.lineTo(x, y);
          }
          radCtx.closePath();
          radCtx.setFillStyle(color)
          radCtx.fill();
        },
    
    第四步.png
        //画点
        drawCircle: function(mData,color){
           var r = 3; //设置节点小圆点的半径
           for(var i = 0; i<numCount; i ++){
              var x = mCenter + mRadius * Math.cos(mAngle * i) * mData[i][1] / 100;
              var y = mCenter + mRadius * Math.sin(mAngle * i) * mData[i][1] / 100;
    
              radCtx.beginPath();
              radCtx.arc(x, y, r, 0, Math.PI * 2);
              radCtx.fillStyle = color;
              radCtx.fill();
            }
        }
    
    第五步.png

    重复四五步的方法添加另一方的雷达图

    最终效果

    .js文件完整内容如下

    var numCount = 6;
    var numSlot = 5;
    var mW = 400;
    var mH = 400;
    var mCenter = mW / 2; //中心点
    var mAngle = Math.PI * 2 / numCount; //角度
    var mRadius = mCenter - 60; //半径(减去的值用于给绘制的文本留空间)
    //获取Canvas
    var radCtx = wx.createCanvasContext("radarCanvas")
    
    
    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        stepText:5,
        chanelArray1:[["战绩",88],["生存",30],["团战",66],["发育",90],["输出",95],["推进",88]],
        chanelArray2: [["战绩", 24], ["生存", 60], ["团战", 88], ["发育", 49], ["输出", 46], ["推进", 92]]
      },
    
      /**
       * 生命周期函数--监听页面初次渲染完成
       */
      onReady: function () {
    
            //雷达图
            this.drawRadar()
    
      },
      // 雷达图
      drawRadar:function(){
        var sourceData1 = this.data.chanelArray1
        var sourceData2 = this.data.chanelArray2
    
        //调用
        this.drawEdge()
        this.drawLinePoint()
        //设置数据
        this.drawRegion(sourceData1,'rgba(255, 0, 0, 0.5)') //第一个人的
        this.drawRegion(sourceData2, 'rgba(255, 200, 0, 0.5)') //第二个人
        //设置文本数据
        this.drawTextCans(sourceData1)
        //设置节点
        this.drawCircle(sourceData1,'red')
        this.drawCircle(sourceData2,'yellow')
        //开始绘制
        radCtx.draw()
      },
      // 绘制6条边
      drawEdge: function(){
        radCtx.setStrokeStyle("white")
        radCtx.setLineWidth(2)  //设置线宽
        for (var i = 0; i < numSlot; i++) {
          //计算半径
          radCtx.beginPath()
          var rdius = mRadius / numSlot * (i + 1)
          //画6条线段
          for (var j = 0; j < numCount; j++) {
            //坐标
            var x = mCenter + rdius * Math.cos(mAngle * j);
            var y = mCenter + rdius * Math.sin(mAngle * j);
            radCtx.lineTo(x, y);
          }
          radCtx.closePath()
          radCtx.stroke()
        } 
      },
      // 绘制连接点
      drawLinePoint:function(){
        radCtx.beginPath();
        for (var k = 0; k < numCount; k++) {
          var x = mCenter + mRadius * Math.cos(mAngle * k);
          var y = mCenter + mRadius * Math.sin(mAngle * k);
    
          radCtx.moveTo(mCenter, mCenter);
          radCtx.lineTo(x, y);
        }
        radCtx.stroke();
      },
      //绘制数据区域(数据和填充颜色)
      drawRegion: function (mData,color){
          
          radCtx.beginPath();
          for (var m = 0; m < numCount; m++){
          var x = mCenter + mRadius * Math.cos(mAngle * m) * mData[m][1] / 100;
          var y = mCenter + mRadius * Math.sin(mAngle * m) * mData[m][1] / 100;
    
          radCtx.lineTo(x, y);
          }
          radCtx.closePath();
          radCtx.setFillStyle(color)
          radCtx.fill();
        },
    
        //绘制文字
        drawTextCans: function (mData){
    
          radCtx.setFillStyle("white")
          radCtx.font = 'bold 17px cursive'  //设置字体
          for (var n = 0; n < numCount; n++) {
            var x = mCenter + mRadius * Math.cos(mAngle * n);
            var y = mCenter + mRadius * Math.sin(mAngle * n);
            // radCtx.fillText(mData[n][0], x, y);
            //通过不同的位置,调整文本的显示位置
            if (mAngle * n >= 0 && mAngle * n <= Math.PI / 2) {
              radCtx.fillText(mData[n][0], x+5, y+5);
            } else if (mAngle * n > Math.PI / 2 && mAngle * n <= Math.PI) {
              radCtx.fillText(mData[n][0], x - radCtx.measureText(mData[n][0]).width-7, y+5);
            } else if (mAngle * n > Math.PI && mAngle * n <= Math.PI * 3 / 2) {
              radCtx.fillText(mData[n][0], x - radCtx.measureText(mData[n][0]).width-5, y);
            } else {
              radCtx.fillText(mData[n][0], x+7, y+2);
            }
    
          }
        },
        //画点
        drawCircle: function(mData,color){
           var r = 3; //设置节点小圆点的半径
           for(var i = 0; i<numCount; i ++){
              var x = mCenter + mRadius * Math.cos(mAngle * i) * mData[i][1] / 100;
              var y = mCenter + mRadius * Math.sin(mAngle * i) * mData[i][1] / 100;
    
              radCtx.beginPath();
              radCtx.arc(x, y, r, 0, Math.PI * 2);
              radCtx.fillStyle = color;
              radCtx.fill();
            }
    
          }
    
    })
    

    #完结#

    相关文章

      网友评论

      • LemonnYan:可以封装成组件吗?组件内是否可以用wx.createCanvasContext("radarCanvas")的方法
      • 海阳之新:效果不错!
      • zlqinying:膜拜楼主👏👏👏
      • zlqinying:你好,如何将每一层的六边形改成圆形
        木语先生:@zlqinying 已更新一个圆形的画法,请参考
        zlqinying:菜鸟一枚多多指教,自己没改好
      • c9d8c0c30c32:怎么把每一项的字设置不同的颜色
        木语先生:@习惯就好_绘制文本的地方我写注释了,我写的white,换成其他就好了
      • JacksonWen:楼主主题用的什么,很清新啊
      • 15572b1c2b50:请问 如何给雷达 填充底色呢
        木语先生:@15572b1c2b50 你是指,直接修改canvas的背景色???

      本文标题:微信小程序-雷达图

      本文链接:https://www.haomeiwen.com/subject/uweglftx.html