使用canvas实现数据可视化

使用canvas实现数据可视化

绘制折线图

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
    canvas {
        border: 1px solid red;
    }
</style>
</head>
<body>
<canvas id="cas" width="600" height="300"></canvas>
</body>
<script>
var cas=document.getElementById("cas");
var context=cas.getContext('2d');

var points=[
    {x:2,y:97},
    {x:18,y:27},
    {x:21,y:62},
    {x:28,y:44},
    {x:44,y:83},
    {x:61,y:88},
    {x:72,y:45},
    {x:78,y:72},
    {x:84,y:53},
    {x:90,y:42}
];
//定义变量
var leftOffset=20,
        rightOffset=20,
        topOffset=20,
        bottomOffset=20;

//箭头大小
var arrowHeight=20,
        arrowWidth=10;

//坐标轴原点
var x=leftOffset;
var y=cas.height-bottomOffset;

//绘制坐标轴
context.beginPath();
//绘制x轴
context.moveTo(x,y);
context.lineTo(cas.width-rightOffset,y);
//绘制y轴
context.moveTo(x,y);
context.lineTo(x,topOffset);
context.stroke();

//绘制箭头
context.beginPath();
//绘制x轴箭头
context.moveTo(cas.width-rightOffset,y);
context.lineTo(cas.width-rightOffset-arrowHeight,y-arrowWidth/2);
context.lineTo(cas.width-rightOffset-arrowHeight/2,y);
context.lineTo(cas.width-rightOffset-arrowHeight,y+arrowWidth/2);
context.closePath();

//绘制y轴箭头
context.moveTo(x,topOffset);
context.lineTo(x-arrowWidth/2,topOffset+arrowHeight);
context.lineTo(x,topOffset+arrowHeight/2);
context.lineTo(x+arrowWidth/2,topOffset+arrowHeight);
context.closePath();
context.fill();

//绘制点
context.beginPath();
//范围
var rangeWidth=cas.width-leftOffset-rightOffset-arrowHeight;
var rangeHeight=cas.height-topOffset-bottomOffset-arrowHeight;

var maxX=Math.max.apply(null,points.map(function(v){
            return v.x;
        }
));
var maxY=Math.max.apply(null,points.map(function(v){
            return v.y;
        }
));
//比例
var rateX=rangeWidth/maxX;
var rateY=rangeHeight/maxY;

for(var i=0;i<points.length;i++){
    var pointx=x+points[i].x*rateX;
    var pointY=y-points[i].y*rateY;

    context.moveTo(pointx-4,pointY-4);
    context.lineTo(pointx+4,pointY-4);
    context.lineTo(pointx+4,pointY+4);
    context.lineTo(pointx-4,pointY+4);
    context.closePath();
}
context.fillStyle="red";
context.fill();

//绘制折线
context.beginPath();
context.moveTo(x+points[0].x*rateX,pointY=y-points[0].y*rateY)
for(var i=1;i<points.length;i++){
    var pointx=x+points[i].x*rateX;
    var pointY=y-points[i].y*rateY;
    context.lineTo(pointx,pointY);
}
context.strokeStyle="red";
context.stroke();
//绘制坐标
for(var i=0;i<points.length;i++){
    var pointX = x + points[ i ].x * rateX;
    var pointY = y - points[ i ].y * rateY;
    var text="("+points[i].x+","+points[i].y+")";
    context.fillText(text,pointX,pointY);
}
</script>
</html>

效果图

绘制条形图

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
    canvas {
        border: 1px solid red;
    }
</style>
</head>
<body>
<canvas id="cas" width="600" height="300"></canvas>
</body>
<script>
var cas=document.getElementById("cas");
var context=cas.getContext('2d');

var points=[
    {x:50,y:97},
    {x:100,y:27},
    {x:150,y:62},
    {x:200,y:44},
    {x:250,y:83},
    {x:300,y:88},
    {x:350,y:45},
    {x:400,y:72},
    {x:450,y:53},
    {x:500,y:42}
];
var data=[50,100,150,200,250,300,350,400,450,500];

//定义变量
var leftOffset=20,
    rightOffset=20,
    topOffset=20,
    bottomOffset=20;

//箭头大小
var arrowHeight=20,
    arrowWidth=10;

//坐标轴原点
var x=leftOffset;
var y=cas.height-bottomOffset;

//绘制坐标轴
context.beginPath();
//绘制x轴
context.moveTo(x,y);
context.lineTo(cas.width-rightOffset,y);
//绘制y轴
context.moveTo(x,y);
context.lineTo(x,topOffset);
context.stroke();

//绘制箭头
context.beginPath();
//绘制x轴箭头
context.moveTo(cas.width-rightOffset,y);
context.lineTo(cas.width-rightOffset-arrowHeight,y-arrowWidth/2);
context.lineTo(cas.width-rightOffset-arrowHeight/2,y);
context.lineTo(cas.width-rightOffset-arrowHeight,y+arrowWidth/2);
context.closePath();

//绘制y轴箭头
context.moveTo(x,topOffset);
context.lineTo(x-arrowWidth/2,topOffset+arrowHeight);
context.lineTo(x,topOffset+arrowHeight/2);
context.lineTo(x+arrowWidth/2,topOffset+arrowHeight);
context.closePath();
context.fill();

//绘制点
context.beginPath();
//范围
var rangeHeight=cas.height-topOffset-bottomOffset-arrowHeight;


var maxY=Math.max.apply(null,points.map(function(v){
            return v.y;
        }
));
//比例
var rateY=rangeHeight/maxY;
context.fillStyle="red";
context.fill();
//绘制折线
context.beginPath();
for(var i=0;i<points.length;i++){
    var pointY=y-points[i].y*rateY;

    context.moveTo(points[i].x-6,pointY-6);
    context.lineTo(points[i].x+6,pointY-6);
    context.lineTo(points[i].x+6,y);
    context.lineTo(points[i].x-6,y);
    context.closePath();
    
    context.fillText(points[i].y,points[i].x-6,pointY-8);
}
context.fillStyle="red";
context.fill();

效果图

绘制饼图

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
    canvas {
        border: 1px solid red;
    }
</style>
	</head>
<body>
<canvas id="cas" width="600" height="300"></canvas>
</body>
<script>
var cas=document.getElementById("cas");
var context=cas.getContext('2d');
// 准备绘图的颜色
var colors =
        ( "aliceblue,antiquewhite,aqua,aquamarine,azure,beige,bisque,black,blanchedalmond,blue," +
        "blueviolet,brown,burlywood,cadetblue,chartreuse,chocolate,coral,cornflowerblue,cornsilk," +
        "crimson,cyan,darkblue,darkcyan,darkgoldenrod,darkgray,darkgreen,darkgrey,darkkhaki,darkmagenta," +
        "darkolivegreen,darkorange,darkorchid,darkred,darksalmon,darkseagreen,darkslateblue,darkslategray," +
        "darkslategrey,darkturquoise,darkviolet,deeppink,deepskyblue,dimgray,dimgrey,dodgerblue,firebrick," +
        "floralwhite,forestgreen,fuchsia,gainsboro,ghostwhite,gold,goldenrod,gray,green,greenyellow,grey," +
        "honeydew,hotpink,indianred,indigo,ivory,khaki,lavender,lavenderblush,lawngreen,lemonchiffon," +
        "lightblue,lightcoral,lightcyan,lightgoldenrodyellow,lightgray,lightgreen,lightgrey,lightpink," +
        "lightsalmon,lightseagreen,lightskyblue,lightslategray,lightslategrey,lightsteelblue,lightyellow," +
        "lime,limegreen,linen,magenta,maroon,mediumaquamarine,mediumblue,mediumorchid,mediumpurple," +
        "mediumseagreen,mediumslateblue,mediumspringgreen,mediumturquoise,mediumvioletred,midnightblue," +
        "mintcream,mistyrose,moccasin,navajowhite,navy,oldlace,olive,olivedrab,orange,orangered,orchid," +
        "palegoldenrod,palegreen,paleturquoise,palevioletred,papayawhip,peachpuff,peru,pink,plum,powderblue," +
        "purple,rebeccapurple,red,rosybrown,royalblue,saddlebrown,salmon,sandybrown,seagreen,seashell,sienna," +
        "silver,skyblue,slateblue,slategray,slategrey,snow,springgreen,steelblue,tan,teal,thistle,transparent," +
        "tomato,turquoise,violet,wheat,white,whitesmoke,yellow,yellowgreen" ).split( ',' );
//角度转换成弧度
function atr(angle){
    return angle*Math.PI/180;
}
//获取随机数
function random(min,max){
    if(max===undefined){
        max=min;
        min=0;
    }
    return parseInt(Math.random()*(max-min))+min;
}
var data=[];
var count=random(6);
for(var i= 0;i<count;i++){
    data.push(random(100));
}
var sum=0;
for(var i=0;i<data.length;i++){
    sum+=data[i];
}
//把随机生成的数组转化成角度
var newDatas=data.map(function(v){
    return v*360/sum;
});
//定义变量
var x=cas.width/ 2,
        y=cas.height/ 2,
        r=100;
var angle=-90;
for(var i=0;i<newDatas.length;i++){
    context.beginPath();
    context.moveTo(x,y);
    context.arc(x,y,r,atr(angle),atr(angle+newDatas[i]));
    context.fillStyle=colors[i+8];
    context.fill();

    context.beginPath();
    var alpha=angle+newDatas[i]/2;
    context.moveTo(x,y);
    context.lineTo(
            x+(r+20)*Math.cos(atr(alpha)),
            y+(r+20)*Math.sin(atr(alpha))
    );

    if(x+(r+20)*Math.cos(atr(alpha))>=cas.width/2){

        context.lineTo( x+(r+20)*Math.cos(atr(alpha))+20,y+(r+20)*Math.sin(atr(alpha)));
        context.fillStyle='black';
        context.fillText(data[i],x+(r+20)*Math.cos(atr(alpha))+20,y+(r+20)*Math.sin(atr(alpha)));

    }else{
        context.lineTo( x+(r+20)*Math.cos(atr(alpha))-20,y+(r+20)*Math.sin(atr(alpha)));
        context.textAlign='right';
        context.fillStyle='black';
        context.fillText(data[i],x+(r+20)*Math.cos(atr(alpha))-20,y+(r+20)*Math.sin(atr(alpha)));

    }

    context.strokeStyle=colors[i+8];
    context.stroke();
    angle=angle+newDatas[i];
}

效果图

posted @ 2016-11-08 01:04  小虫真不知  阅读(3566)  评论(0编辑  收藏  举报