原生js自定义雷达图
完整代码:
<head>
<style>
body{
background-color: #292929;
}
.tab{
margin-top: 50px;
background-color: #fff;
font-size: 15px;
margin-left: 50%;
transform: translateX(-50%);
display: inline-block;
box-sizing: border-box;
}
.tab_header{
position: relative;
background: url('//img.mukewang.com/610ca5cc000190ed03000250.jpg');
background-size:auto 100%;
}
.tab_header a{
width: 64px;
height: 64px;
position: absolute;;
left: 50%;
top: 50%;
margin-left: -32px;;
margin-top: -30px;
display: block;
z-index: 1;
background-size: 100%;
}
.tab_header>a>img{
width: 100%;
height: 100%;
display: block;
}
.tab_main{
padding: 5px 10px;
box-sizing: border-box;
}
.tab_main>p{
color: #848484;
box-sizing: border-box;
}
#controlBar{
}
#myCanvas{
margin: 0 auto;
}
input{
width: 100px;
border: none;
background-color: #eee;;
padding: 5px;
}
#controlBar label{
margin: 0 10px;
}
#controlBar div{
padding: 5px;
}
.tab_main button{
width: 100%;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab_header">
<canvas id="myCanvas"></canvas>
</div>
<div class="tab_main">
<h3>修改值来查看实时效果:</h3>
<div id="controlBar"></div>
<button id="load">加载</button>
</div>
</div>
<script>
(function(){
class Radar{
fontSyle="12px Arial";
speed = 2;
startVal = 0;
maxValue = 80;
textColor = "rgba(255,255,255,1)";
background={
rect:[
{
color:"rgba(56,60,63,0.4)",
size:80,
},
{
color:"rgba(115,115,116,0.3)",
size:75,
},
],
circle:[
{
color:"rgba(66,139,234,0.1)",
size:4
},
{
color:"rgba(66,139,234,1)",
size:2
}
]
}
customizeBackground = (data)=>{
this.background = data;
}
setFontStyle = (fontSyle)=>{
this.fontSyle = fontSyle.style;
this.textColor = fontSyle.color;
}
setContextSize = (width,height)=>{
this.el.width=width;
this.el.height=height;//设置好canvas的宽高
this.c= {x:width/2,y:height/2};
}
setIndex = (index)=>{
this.index = index;
}
getIndex = function(){
return this.index;
}
constructor(options){
this.index = options.data;
this.el = document.querySelector(options.el);
this.ctx = this.el.getContext("2d");
this.maxValue = options.size;
}
};
Radar.prototype.solveEquations=function(tan,isRight,val){ //解出x位置
var sec2=Math.pow(tan,2)+1;
var b2 = 4*Math.pow(sec2,2)*Math.pow(this.c.x,2) ;
var ac4 = 4*sec2*(sec2*Math.pow(this.c.x,2)-Math.pow(val,2))
var delta =b2 - ac4;
return isRight?(2*sec2*this.c.x+ Math.sqrt(delta))/(2*sec2):(2*sec2*this.c.x- Math.sqrt(delta))/(2*sec2);
}
Radar.prototype.getPonit=function(n,val){ //get liner equation that we can calculate the position of points
var length = this.index.length;
var alpha = 360/length; //获得内角度数
if(n==0)return {x:this.c.x,y:this.c.y- val}; // this.defaultValue暂时作为测试数据
var angel=alpha*n+90; //每条直线的角度
// console.log('angel: ',angel);
var k = Math.tan(angel*Math.PI/180); //斜率k&tan值
// 分布规则
// 把中心点x做为分界线
var isRight = false; //标记x是否在中心点右边
var cindex = length/2;
//偶数情况
if(length%2==0){
if(n==cindex) return {x:this.c.x,y:this.c.y + val};
if(n<cindex)
isRight = true;
}else{ // 奇数情况
cindex=parseInt(cindex);
if(n<=cindex)
isRight = true;
}
var x = this.solveEquations(k,isRight,val);
var y = k*(x-this.c.x) + this.c.y;
return {x: x, y:y }
// 计算出的x值会有两个 , 需要定一个分布规则排除其中一个
// 只要算出x就可以得到y
}
Radar.prototype.creatPointArr = function(val){
var len = this.index.length;
var pointArr =new Array();
for( var i =0 ;i<len ;i++){
pointArr.push(this.getPonit(i,val));
}
return pointArr;
}
Radar.prototype.setBackground=function(){
for(var i = 0;i<this.background.rect.length ;i++){
var gap = 0;
if(i>0) gap = Math.abs(this.background.rect[i].size-this.background.rect[i-1].size);
this.rectangle(this.creatPointArr(this.startVal-gap));
this.rectangleFill(this.background.rect[i].color);
}
var pointArr =this.creatPointArr(this.startVal);
// //点
this.drawCircle(pointArr)
//文本
var pointArr = this.creatPointArr(this.maxValue+10);
for( var i =0 ;i<pointArr.length ;i++){
this.setText(this.index[i].name,pointArr[i]);
}
if(this.startVal < this.maxValue){
this.startVal += this.speed;
return false;
}else return true;
}
Radar.prototype.init = function(){
var that = this;
requestAnimationFrame(function(){
that.ctx.clearRect(0,0,that.el.width,that.el.height); //清除画布
if(!that.setBackground()||!that.renderData())requestAnimationFrame(arguments.callee); // 一个内在机制,或门的右边通常会在左边为true的时候不执行 就会出现背景先加载后再渲染数据
});
}
Radar.prototype.renderData = function(){
var pointArr = new Array();
var ready = 0;
// console.log(Math.abs(this.index[0].startVal-this.index[0].value));
for( var i =0 ;i<this.index.length ;i++){
if((Math.abs(this.index[i].startVal-this.index[i].value)==0)||(Math.abs(this.index[i].startVal-this.index[i].value)==1)){
ready++;
}
else if(this.index[i].startVal<this.index[i].value)
{
this.index[i].startVal+=this.speed;
}
else if(this.index[i].startVal>this.index[i].value){
this.index[i].startVal-=this.speed;
}
pointArr.push(this.getPonit(i,this.index[i].startVal));
}
// console.log(pointArr)
this.rectangle(pointArr);
this.rectangleFill("rgba(66,139,234,1)",'rgba(66,139,234,0.5)');
if(ready == this.index.length){
return true;
}else{
return false;
}
}
Radar.prototype.rectangle=function(pointArr){ //矩形的线条结构
var ctx = this.ctx;
ctx.beginPath();
for( var i=0;i<pointArr.length;i++){
if(i==0) ctx.moveTo(pointArr[i].x,pointArr[i].y);
else
ctx.lineTo(pointArr[i].x,pointArr[i].y);
}
ctx.closePath();
}
Radar.prototype. rectangleFill=function(stroke,fill=stroke){ //矩形一的填充
var ctx = this.ctx;
ctx.strokeStyle=stroke;
ctx.stroke();
ctx.closePath();
ctx.fillStyle = fill;
ctx.fill();
}
Radar.prototype.circle = function(postion,size,stroke,fill=stroke){
var ctx = this.ctx;
ctx.beginPath();
ctx.strokeStyle=stroke;
ctx.arc(postion.x,postion.y,size,0,2*Math.PI);
ctx.stroke();
ctx.closePath();
ctx.fillStyle = fill;
ctx.fill();
}
Radar.prototype.drawCircle=function(pointArr){
for( var i =0 ;i<pointArr.length ;i++){
for(var j = 0;j < this.background.circle.length ; j++)
this.circle(pointArr[i],this.background.circle[j].size,this.background.circle[j].color);
}
}
Radar.prototype.setText = function (text,postion){
var ctx = this.ctx;
var dimension = ctx.measureText(text); // 测量文字
console.log(dimension.width)
var x=postion.x,y=postion.y;
if(postion.x==this.c.x){
x=postion.x-dimension.width/2;
}else if(postion.x<this.c.x){
x=postion.x-dimension.width;
}
if(postion.y>this.c.y){
y=postion.y + 12;
}
ctx.font=this.fontSyle;
ctx.beginPath();
ctx.fillStyle =this.textColor;
ctx.fillText(text,x,y);
}
window.Radar=Radar;
})()
</script>
<script>
var data =[{name:"标题一",value:50,startVal:0},{name:"标题二",value:50,startVal:0},{name:"标题三",value:70,startVal:0},{name:"标题四",value:25,startVal:0},{name:"标题五",value:33,startVal:0},{name:"标题六",value:55,startVal:0},{name:"标题七",value:33,startVal:0} ];
var radar=new Radar({
el:"#myCanvas",
data:data,
size:80,
});
radar.customizeBackground({
rect:[
{
color:"rgba(56,60,63,0.4)",
size:80,
},
{
color:"rgba(115,115,116,0.3)",
size:75,
},
],
circle:[
{
color:"rgba(66,139,234,0.1)",
size:4
},
{
color:"rgba(66,139,234,1)",
size:2
}
]
})
radar.setFontStyle({
style:"12px Arial",
color:"rgba(200,255,255,1)"
})
radar.setContextSize(300,250);
radar.init();
var controlBar = document.querySelector('#controlBar');
for(var i = 0;i<data.length;i++){
var el = document.createElement('input');
var val = document.createElement('input');
var label =document.createElement('label');
el.value = data[i].value
label.innerText = "值:"
val.value= data[i].name;
var div = document.createElement('div');
div.appendChild(val)
div.appendChild(label)
div.appendChild(el)
div.setAttribute("class","questionText");
controlBar.appendChild(div);
// el.set
}
document.getElementById('load').onclick = function(){
var obj = controlBar.getElementsByTagName("div");
// console.log(obj.length);
for(var i = 0;i < obj.length;i++){
data[i].name = obj[i].getElementsByTagName('input')[0].value;
data[i].value = obj[i].getElementsByTagName('input')[1].value;
}
// console.log(data)
radar.init();
}
</script>
</body>电脑在线的朋友可以点击上面的【运行代码】观看效果
描述:
自定义的雷达图,轻量级可根据数据变化做出相应变化,颜色、尺寸、背景可自定义
数据格式如下
var data = [{
name: "标题一",
value: 50,
startVal: 0
}, {
name: "标题二",
value: 50,
startVal: 0
}, {
name: "标题三",
value: 70,
startVal: 0
}, {
name: "标题四",
value: 25,
startVal: 0
}, {
name: "标题五",
value: 33,
startVal: 0
}, {
name: "标题六",
value: 55,
startVal: 0
}, {
name: "标题七",
value: 33,
startVal: 0
}];
var radar = new Radar({
el: "#myCanvas", //canvas标签的id
data: data,
size: 80, //雷达图的大小
});根据以下方法对背景自定义( 可不执行):
radar.customizeBackground({
rect: [{
color: "rgba(56,60,63,0.4)",
size: 80,
}, {
color: "rgba(115,115,116,0.3)",
size: 75,
}, ],
circle: [{
color: "rgba(66,139,234,0.1)",
size: 4
}, {
color: "rgba(66,139,234,1)",
size: 2
}]
})自定义文字样式( 可不执行):
radar.setFontStyle({
style: "12px Arial",
color: "rgba(200,255,255,1)"
})设置canvas尺寸( 必须执行):
radar.setContextSize(300, 250);
初始化( 必须执行):
radar.init();
版权声明:本文由 LzxBlog 发布,如需转载请注明出处。










赞助云储存