最近公司项目,需要用到雷达图的效果,echarts的雷达图不太符合公司的需求,所以自己用canvas写了个雷达图的组件。
19-51-37-12-27-25656.gif
奉上代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
body{
width: 100%;
height: 100%;
background: rgba(0,0,0,0.6);
}
#myCanvas{
position: absolute;
top: 50px;
left: 300px;
background: rgba(0,0,0,0.6);
}
img{
border-radius: 50%;
}
.h_box{
padding: 3px 8px;
background: #fff;
color: #333;
font-size: 12px;
position: absolute;
display: none;
}
</style>
</head>
<body>
<canvas id="myCanvas" class="myCanvas">你的浏览器不支持canvas,请升级你的浏览器</canvas>
<div class="h_box"></div>
</body>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
<script src="index.js"></script>
<script>
// 模拟数据
var data = {
"list":[
{
"name":"业务1",
"num":30
},
{
"name":"业务2",
"num":100
},
{
"name":"业务3",
"num":100
},
{
"name":"业务4",
"num":85
},
{
"name":"业务5",
"num":90
},
{
"name":"业务6",
"num":100
}
]
}
var length = data.list.length;
newCanvas.init({
length: length,
data: data.list,
colorStart: 100,
colorMiddle: 90,
colorEnd: 80
});
</script>
</html>
js
var newCanvas = (function(){
var bWidth = $(".box").width();
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext('2d');
var self;
return {
animID: undefined,
init:function(config){
self = this;
self.hResize(config.length,config.data,config.colorStart,config.colorMiddle,config.colorEnd); //设置自适应窗口大小
},
hResize:function(num,data,colorStart,colorMiddle,colorEnd){
var h = $(window).get(0).innerWidth;
if(h<1000){ //在小分辨率下适配
canvas.width = "300";
canvas.height = "300";
var cWidth = canvas.width;
var cHeight = canvas.height;
console.log(cWidth,cHeight);
// 中心点
var centerX = cWidth/2;
var centerY = cWidth/2;
// 半径
var radius = centerX*0.95;
self.animate(centerX,centerY,radius,cWidth,cHeight,num,data,colorStart,colorMiddle,colorEnd);
}else{
canvas.width = "500";
canvas.height = "500";
var cWidth = canvas.width;
var cHeight = canvas.height;
console.log(cWidth,cHeight);
// 中心点
var centerX = cWidth/2;
var centerY = cWidth/2;
// 半径
var radius = centerX*1;
self.animate(centerX,centerY,radius,cWidth,cHeight,num,data,colorStart,colorMiddle,colorEnd);
$("#myCanvas").mousemove(function (event) {
let e = event || window.event;
let scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
let scrollY = document.documentElement.scrollTop || document.body.scrollTop;
let x = e.pageX || e.clientX + scrollX;
let y = e.pageY || e.clientY + scrollY;
var canvasOffset = $("#myCanvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
mouseX =x - offsetX;
mouseY = y - offsetY;
$(".h_box").css({
"display":"none"
});
for(var i=0,j=1;i<data.length,j<2*num;i++,j+=2){
var dx = mouseX - (centerX+centerX/10*(data[i].num/10-1)*Math.sin(Math.PI*j/num));
var dy = mouseY - (centerY+centerX/10*(data[i].num/10-1)* Math.cos(Math.PI*j/num));
var dz = 6*6;
if(dx*dx+dy*dy<dz){
var font = data[i].name + '<br/>'+ '业务百分比:' + '<b>' +data[i].num + '</b>';
$(".h_box").html(font);
$(".h_box").css({
"top":y+10,
"left":x-30,
"display":"block"
})
// 给tooltip做适配,不超出
var b_left = $(".h_box").position().left;
var c_left = $("#myCanvas").position().left;
var b_top = $(".h_box").position().top;
var c_top = $("#myCanvas").position().top;
if(b_left+$(".h_box").width()>c_left+$(".myCanvas").width()){
console.log(4656);
$(".h_box").css({
"left":x-$(".h_box").width()
})
}
if(b_top+$(".h_box").height()>c_top+$(".myCanvas").height()){
$(".h_box").css({
"top":y-$(".h_box").height()
})
}
}
}
});
}
},
drawCircle:function(centerX,centerY,r,lineWidth=1,color="#303079"){ //画圆
ctx.beginPath();
ctx.arc(centerX,centerY,r,0,2*Math.PI);
ctx.setLineDash([]);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = color;
ctx.stroke();
},
drawCircleZ:function(centerX,centerY,r,lineWidth=1,color="#303079"){ //画最外层的圆
ctx.beginPath();
ctx.arc(centerX,centerY,r,0,2*Math.PI);
ctx.setLineDash([]);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = color;
ctx.stroke();
var linearGradient = ctx.createRadialGradient(centerX,centerY,r*0.3,centerX,centerY,r);
linearGradient.addColorStop(0,'rgba(1,1,118,0.9)');
linearGradient.addColorStop(1,'rgba(2,2,55,0.8)');
ctx.fillStyle = linearGradient;
ctx.fill();
},
drawDian:function(centerX,centerY,r,lineWidth=1,num,colorStart,colorMiddle,colorEnd){ //画点
ctx.beginPath();
ctx.arc(centerX,centerY,r,0,2*Math.PI);
ctx.setLineDash([]);
ctx.lineWidth = lineWidth;
if(num<=colorStart && num>colorMiddle){
ctx.strokeStyle = "#4ac097";
ctx.stroke();
ctx.fillStyle = "#4ac097";
ctx.fill();
}else if(num<colorMiddle&& num>colorEnd){
ctx.strokeStyle = "#E9AA3D";
ctx.stroke();
ctx.fillStyle = "#E9AA3D";
ctx.fill();
}else{
ctx.strokeStyle = "#fc536c";
ctx.stroke();
ctx.fillStyle = "#fc536c";
ctx.fill();
}
},
drawFont:function(centerX,centerY,r,font){ //绘制点旁边的文字
ctx.beginPath();
ctx.arc(centerX,centerY,r,0,2*Math.PI);
ctx.font = "normal 12px 微软雅黑";//字体
ctx.textBaseline = "middle";//竖直对齐
ctx.textAlign = "center";//水平对齐
ctx.fillText(font,centerX,centerY);//绘制文字
ctx.fillStyle = "transparent";
ctx.fill();
},
drawPoint:function(centerX,centerY,r,num,colorStart,colorMiddle,colorEnd){ //画点外环动态效果
ctx.beginPath();
ctx.arc(centerX,centerY,r,0,2*Math.PI);
ctx.lineWidth = 0.5;
if(num<=colorStart && num>colorMiddle){
ctx.strokeStyle = "#4ac097";
ctx.stroke();
}else if(num<colorMiddle&& num>colorEnd){
ctx.strokeStyle = "#E9AA3D";
ctx.stroke();
}else{
ctx.strokeStyle = "#fc536c";
ctx.stroke();
}
},
drawCircleNew:function(centerX,centerY,r,lineWidth=1,color="red"){ //画圆
ctx.beginPath();
ctx.arc(centerX,centerY,r,0,2*Math.PI);
ctx.setLineDash([5,3]);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = color;
ctx.stroke();
},
drawLine:function (centerX,centerY,x, y, color, lineWidth=1,lineDash=[]) { //画线
ctx.beginPath();
ctx.setLineDash(lineDash);
ctx.moveTo(centerX,centerY);
ctx.lineTo(x,y);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = color='rgba(6,73,150,0.6)';
ctx.stroke();
},
drawLineZ:function (centerX,centerY,x, y, color, lineWidth=1,lineDash=[]) { //画边框线
ctx.beginPath();
ctx.setLineDash(lineDash);
ctx.moveTo(centerX,centerY);
ctx.lineTo(x,y);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = color='rgba(6,73,150,1)';
ctx.stroke();
},
drawSector:function (centerX,centerY,radius,sAngle, eAngle) { //画扇形
let blob = 60;
let increase = 0;
if(sAngle < eAngle) {
increase = (eAngle - sAngle)/blob;
}
else if(sAngle > eAngle) {
increase = (Math.PI*2 - sAngle + eAngle)/blob;
}
else {
return;
}
let angle1 = sAngle;
let angle2 = sAngle + increase;
for(let i = 0; i < blob; i++){
ctx.beginPath();
ctx.moveTo(centerX,centerY);
ctx.arc(centerX, centerY, radius, angle1, angle2);
ctx.fillStyle = "rgba(0,255,255,"+ i/blob +")";
ctx.fill();
angle1 = angle2;
angle2 = angle1 + increase;
if(angle2 >= Math.PI*2){
ctx.beginPath();
ctx.moveTo(centerX,centerY);
ctx.arc(centerX, centerY, radius, angle1, Math.PI*2);
ctx.fillStyle = "rgba(0,255,255,"+ i/blob +")";
ctx.fill();
angle1 = 0;
angle2 = angle1 + increase;
}
}
},
drawLastY:function(x,y){ //绘制中间空出来的圆
ctx.beginPath();
ctx.arc(x,y,x*0.05,0,2*Math.PI);
ctx.lineWidth = 0;
ctx.fillStyle="#333";
ctx.fill();
},
animate:function(x,y,radius,cWidth,cHeight,num,data,colorStart,colorMiddle,colorEnd){
var aa = window.requestAnimFrame = (function(){ //设置兼容性
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function */ callback, /* DOMElement */ element){
window.setTimeout(callback, 1000 / 100);
};
})();
var angle = Math.PI/4; //画扇形
var scanBegin = 0;
var scanEnd = angle;
var pointRadius = 0.5;
function move() {
ctx.clearRect(0,0,cWidth,cHeight); // 清除画布
for(var i=0;i<=100;i++){
self.drawLineZ(x,y,x + Math.sin(Math.PI*i/100*2)*(x*0.95),
y + Math.cos(Math.PI*i/100*2)*(x*0.95),1);
}
for(var i=0;i<=num;i++){
self.drawLine(x,y,x + Math.sin(Math.PI*i/num*2)*(x*0.99),
y + Math.cos(Math.PI*i/num*2)*(x*0.99),4);
}
self.drawCircleZ(x,y,x*0.92,3); //画圆
self.drawCircle(x,y,x*0.6,3);
self.drawCircle(x,y,x*0.3,3);
for(var i = 1; i<=num; i++){ //画线
self.drawLine(x,y,x + Math.sin(Math.PI*i/num*2)*radius,
y + Math.cos(Math.PI*i/num*2)*radius);
}
self.drawSector(x,y,radius,scanBegin,scanEnd); // 绘制扇形扫描区域
// 改变点的半径以及扇形的角度
scanBegin += angle/25;
scanEnd = scanBegin + angle;
// 超过阈值变为初始值
if(scanBegin >= Math.PI*2) {
scanBegin = 0;
scanEnd = scanBegin + angle;
}
pointRadius +=0.02;
self.drawLastY(x,y); //画最后一个圆
for(var i=0,j=1;i<data.length,j<2*num;i++,j+=2){
self.drawDian(x+x/10*(data[i].num/10-1)*Math.sin(Math.PI*j/num),x/10*(data[i].num/10-1)* Math.cos(Math.PI*j/num)+y,3,1,data[i].num,colorStart,colorMiddle,colorEnd);
self.drawPoint(x+x/10*(data[i].num/10-1)*Math.sin(Math.PI*j/num),x/10*(data[i].num/10-1)* Math.cos(Math.PI*j/num)+y,4+pointRadius,data[i].num,colorStart,colorMiddle,colorEnd);
self.drawFont(x+x/10*(data[i].num/10-2)*Math.sin(Math.PI*j/num),x/10*(data[i].num/10-2)* Math.cos(Math.PI*j/num)+y,8,data[i].name);
}
if(pointRadius >= 5) pointRadius = 0;
// 再次绘制
window.requestAnimFrame(move);
}
animID = window.requestAnimFrame(move);
}
}
})()
网友评论