当前位置:首页 > 技术博客 > JavaScript > 原生js自定义雷达图

原生js自定义雷达图

admin2年前 (2021-08-06)JavaScript567


完整代码:

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

本文链接:https://www.liuzhixi.cn/html/140.html

标签: 图表

相关文章

百度地图JavaScript简单标点连线

百度地图JavaScript简单标点连线

背景最近在研究轨迹数据的挖掘,第一步就是把轨迹数据在地图上可视化出来,然后再进行后续的算法研究。从一开始懵懂知道百度地图有免费的 API 可以调用,到后面知道还...

圆形光影mp3音频播放器特效

圆形光影mp3音频播放器特效

原生js css3绘制圆形光影音乐播放器,支持上一首或下一首切换,播放暂停,音量控制,音乐播放进度条控制,音乐列表播放,输入添加音乐播放地址等功能。这是一款很全...

Bilibili头部景深对焦效果

Bilibili头部景深对焦效果

交互式鼠标悬停头图景深对焦效果<head>       <meta n...

js轮播图滑块过渡特效

js轮播图滑块过渡特效

js flipping插件制作简洁时尚的带缩略图的大图轮播幻灯片展示,点击左右箭头按钮,标题,缩略图,大图滑动切换效果。下载链接: https://pan.ba...

前端用法:JavaScript 获取当前GPS地理位置的方法,保姆级代码!

前端用法:JavaScript 获取当前GPS地理位置的方法,保姆级代码!

在网上搜到很多,99%不能用,自己动手将整理记录一下吧,以便后续再使用!<head>     <ti...

整理:JavaScript字符串的截取以及数组的截取

整理:JavaScript字符串的截取以及数组的截取

在编写前端时,截取字符串或者是截取数组的部分元素都是频繁出现的场景,所以在这整理一下:一、截取字符串JS提供三个截取字符串的方法,分别是:slice(),sub...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。
X 要酷!乐于助人,网络是一个神奇的地方,玩得愉快,击掌