原生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 发布,如需转载请注明出处。