HTML5 Canvas制作雷达图实战

雷达图又叫蜘蛛网图,是一种对各项数据查看很明显的表现图,在很多游戏中,对游戏中的每个角色的分析图一般也用这种图。

下面,用HTML5的Cavas来实现雷达图。

效果

一、创建Canvas

var mW = 400;var mH = 400;var mCtx = null;var canvas = document.createElement('canvas');document.body.appendChild(canvas);canvas.height = mH;canvas.width = mW;mCtx = canvas.getContext('2d');

二、制作多边形背景

var mCount = 6; //边数var mCenter = mW /2; //中心点var mRadius = mCenter - 50; //半径(减去的值用于给绘制的文本留空间)var mAngle = Math.PI * 2 / mCount; //角度var mColorPolygon = '#B8B8B8'; //多边形颜色// 绘制多边形边function drawPolygon(ctx){    ctx.save();    ctx.strokeStyle = mColorPolygon;    var r = mRadius/ mCount; //单位半径    //画6个圈    for(var i = 0; i < mCount; i ++){        ctx.beginPath();                var currR = r * ( i + 1); //当前半径        //画6条边        for(var j = 0; j < mCount; j ++){            var x = mCenter + currR * Math.cos(mAngle * j);            var y = mCenter + currR * Math.sin(mAngle * j);            ctx.lineTo(x, y);        }        ctx.closePath()        ctx.stroke();    }    ctx.restore();}

效果:

三、连接顶点线

var mColorLines = '#B8B8B8'; //顶点连线颜色//顶点连线function drawLines(ctx){    ctx.save();    ctx.beginPath();    ctx.strokeStyle = mColorLines;    for(var i = 0; i < mCount; i ++){        var x = mCenter + mRadius * Math.cos(mAngle * i);        var y = mCenter + mRadius * Math.sin(mAngle * i);        ctx.moveTo(mCenter, mCenter);        ctx.lineTo(x, y);    }    ctx.stroke();    ctx.restore();}效果:![](http://img.blog.csdn.net/20170305133430976?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGVjZXBpbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)## 四、绘制数据文本```javascriptvar mData = [['速度', 77],            ['力量', 72],            ['防守', 46],            ['射门', 50],            ['传球', 80],            ['耐力', 60]]; //数据var mColorText = '#000000';//绘制文本function drawText(ctx){    ctx.save();    var fontSize = mCenter / 12;    ctx.font = fontSize + 'px Microsoft Yahei';    ctx.fillStyle = mColorText;    for(var i = 0; i < mCount; i ++){        var x = mCenter + mRadius * Math.cos(mAngle * i);        var y = mCenter + mRadius * Math.sin(mAngle * i);        //通过不同的位置,调整文本的显示位置        if( mAngle * i >= 0 && mAngle * i <= Math.PI / 2 ){            ctx.fillText(mData[i][0], x, y + fontSize);         }else if(mAngle * i > Math.PI / 2 && mAngle * i <= Math.PI){            ctx.fillText(mData[i][0], x - ctx.measureText(mData[i][0]).width, y + fontSize);            }else if(mAngle * i > Math.PI && mAngle * i <= Math.PI * 3 / 2){            ctx.fillText(mData[i][0], x - ctx.measureText(mData[i][0]).width, y);           }else{            ctx.fillText(mData[i][0], x, y);        }    }    ctx.restore();}<div class="se-section-delimiter"></div>

效果:

五、绘制数据覆盖区域

//绘制数据区域function drawRegion(ctx){    ctx.save();    ctx.beginPath();    for(var i = 0; i < mCount; 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;        ctx.lineTo(x, y);    }    ctx.closePath();    ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';    ctx.fill();    ctx.restore();}<div class="se-section-delimiter"></div>

效果:

六、绘制数据点

把每个数据与线的焦点绘制出来。

//画点function drawCircle(ctx){    ctx.save();    var r = mCenter / 18;    for(var i = 0; i < mCount; 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;        ctx.beginPath();                    ctx.arc(x, y, r, 0, Math.PI * 2);        ctx.fillStyle = 'rgba(255, 0, 0, 0.8)';        ctx.fill();    }           ctx.restore();}<div class="se-section-delimiter"></div>

效果:

最终代码

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Document</title>  <style type="text/css">    canvas{    }  </style></head><body><script type="text/javascript">     var mW = 400;    var mH = 400;    var mData = [['速度', 77],                            ['力量', 72],                            ['防守', 46],                            ['射门', 50],                            ['传球', 80],                            ['耐力', 60]];    var mCount = mData.length; //边数     var mCenter = mW /2; //中心点    var mRadius = mCenter - 50; //半径(减去的值用于给绘制的文本留空间)    var mAngle = Math.PI * 2 / mCount; //角度    var mCtx = null;    var mColorPolygon = '#B8B8B8'; //多边形颜色    var mColorLines = '#B8B8B8'; //顶点连线颜色    var mColorText = '#000000';    //初始化    (function(){      var canvas = document.createElement('canvas');      document.body.appendChild(canvas);      canvas.height = mH;      canvas.width = mW;      mCtx = canvas.getContext('2d');      drawPolygon(mCtx);      drawLines(mCtx);      drawText(mCtx);      drawRegion(mCtx);      drawCircle(mCtx);    })();      // 绘制多边形边      function drawPolygon(ctx){        ctx.save();        ctx.strokeStyle = mColorPolygon;        var r = mRadius/ mCount; //单位半径        //画6个圈        for(var i = 0; i < mCount; i ++){            ctx.beginPath();                    var currR = r * ( i + 1); //当前半径            //画6条边            for(var j = 0; j < mCount; j ++){                var x = mCenter + currR * Math.cos(mAngle * j);                var y = mCenter + currR * Math.sin(mAngle * j);                ctx.lineTo(x, y);            }            ctx.closePath()            ctx.stroke();        }        ctx.restore();      }    //顶点连线    function drawLines(ctx){        ctx.save();        ctx.beginPath();        ctx.strokeStyle = mColorLines;        for(var i = 0; i < mCount; i ++){            var x = mCenter + mRadius * Math.cos(mAngle * i);            var y = mCenter + mRadius * Math.sin(mAngle * i);            ctx.moveTo(mCenter, mCenter);            ctx.lineTo(x, y);        }        ctx.stroke();        ctx.restore();    }    //绘制文本    function drawText(ctx){        ctx.save();        var fontSize = mCenter / 12;        ctx.font = fontSize + 'px Microsoft Yahei';        ctx.fillStyle = mColorText;        for(var i = 0; i < mCount; i ++){            var x = mCenter + mRadius * Math.cos(mAngle * i);            var y = mCenter + mRadius * Math.sin(mAngle * i);            if( mAngle * i >= 0 && mAngle * i <= Math.PI / 2 ){                ctx.fillText(mData[i][0], x, y + fontSize);             }else if(mAngle * i > Math.PI / 2 && mAngle * i <= Math.PI){                ctx.fillText(mData[i][0], x - ctx.measureText(mData[i][0]).width, y + fontSize);                }else if(mAngle * i > Math.PI && mAngle * i <= Math.PI * 3 / 2){                ctx.fillText(mData[i][0], x - ctx.measureText(mData[i][0]).width, y);               }else{                ctx.fillText(mData[i][0], x, y);            }        }        ctx.restore();    }    //绘制数据区域    function drawRegion(ctx){        ctx.save();        ctx.beginPath();        for(var i = 0; i < mCount; 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;            ctx.lineTo(x, y);        }        ctx.closePath();        ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';        ctx.fill();        ctx.restore();    }    //画点    function drawCircle(ctx){        ctx.save();        var r = mCenter / 18;        for(var i = 0; i < mCount; 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;            ctx.beginPath();                        ctx.arc(x, y, r, 0, Math.PI * 2);            ctx.fillStyle = 'rgba(255, 0, 0, 0.8)';            ctx.fill();        }               ctx.restore();    }</script></body></html>

原文发布于微信公众号 - 京程一灯(jingchengyideng)

原文发表时间:2017-08-05

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

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券