当前位置: 首页 > Web前端 > HTML5

记录一个使用canvas解决数据可视化问题:将boxplot转换成对应的圆

时间:2023-04-05 19:31:50 HTML5

先看最终渲染的要求:boxplot中的每个box都有自己对应的圆心和半径,以及对应的y-axis在当前地图上的值范围(可缩放),根据这三个值,在同一垂直线上画一个圆心一一对应的圆,然后想办法把它移动到标准笛卡尔坐标系中去看到所有圆的圆心坐标都是(0,?),此时y在笛卡尔坐标系中的最大值和最小值可以任意给定,而且是对称的。我们给600.-600,这时候我们只需要计算出右边坐标系中每个圆的真实圆心坐标和半径长度,就可以用canvas画圆了。难点在于坐标的转换。这里我用比例关系来计算:1.首先是半径的计算,列出公式:真实圆的半径/真实范围=坐标系圆的半径/y坐标系的-axis后端传回真实圆的半径,也可以通过左边箱线图的y轴范围得到真实的范围=y_end-y_starty-的范围axisofthecoordinatesystem=1200,(我们设置y轴范围为600到-600)来计算坐标系上刻度圆的半径。2.坐标系上圆心的计算。同样,我们可以用圆心到垂直中心的距离列出比例公式:(实圆心坐标-实测距中心)/实测距=(坐标系圆心y坐标-坐标系测距中心ycoordinate)/坐标系y轴范围后端传回的实圆半径,realrange=y_end-y_startrealRangecenter=(y_end-y_start)/2+y_start坐标系范围中心y坐标=0坐标systemy-axisrange=1200可以得到缩放圆心y坐标在坐标系上的坐标。知道了这两个,我们只需要用canvas画上面的圆就行了,我们创建一个大小为1200的canvas,pencil?.clearRect(0,0,1200,1200);而canvas自带的坐标系是这样的,所以我们坐标系的原点对应的canvas画布的坐标是(600,600),圆心的坐标还是需要进行变换。可以看到原来圆心的y坐标是200,新的是600-200=400,也就是画布上圆心的y。coordinates=600-缩放后圆心的y坐标,那么就可以使用在canvas上画圆的方法画圆了pencil.arc(600,圆心在画布上的y坐标canvas,缩放后圆的半径,0,2*Math.PI,);所有的数理逻辑分析和canvas方法分析都完成了。直接输入代码:typeBoxPlotCircleData={diameter:number;意思是:数字;参数X:字符串;测试项目:字符串;};typeCirCleProps={//颜色:Color[];范围:[数字,数字];boxPlotColorDic:{[key:string]:颜色};宽度:数字;data:BoxPlotCircleData[];};//计算缩放直径值的函数,使用保证realRange大于0的数字constcomputerDiameter=(realDiameter:number,realRange:number,computerRange:number)=>{//公式:computerDiameter/realDiameter=computerRange/realRange//if(!realRange)return;constcomputerDiameterRes:number=bignumberFc.multiply(bignumberFc.divide(computerRange,realRange),realDiameter);returncomputerDiameterRes;};//计算缩放圆心Y坐标的函数,使用保证realRange大于0的数字constcomputerCircleCenter=(realCircleCenter:number,realRange:number,realStartPoint:number,computerRange:number,)=>{//公式:中点坐标=realRange/2+range[0]//公式:(realCircleCenter-midpoint)/realRange=(computerCircleCenter-0)/computerRange//if(!realRange)r返回;constrealMiddle:number=bignumberFc.add(bignumberFc.divide(realRange,2),realStartPoint);常量computerCircleCenterRes=bignumberFc.multiply(bignumberFc.divide(bignumberFc.subtract(realCircleCenter,realMiddle),realRange),computerRange,);returncomputerCircleCenterRes;};constAnovaCircle:React.FC=(props:CirCleProps)=>{//console.log(props,'props______-');const{范围,数据,boxPlotColorDic}=道具;constcanvasDom=useRef(null);useEffect(()=>{constpencil=canvasDom.current?.getContext('2d');if(!pencil)return;pencil?.clearRect(0,0,1200,1200);if(!range)return;constrealRange=bignumberFc.subtract(range[1],range[0]);if(!(realRange>0))return;data.map((item)=>{//console.log(computerCircleCenter(item.mean),realRange,range[0],1200),'圆心坐标');//console.log(bignumberFc.divide(computerDiameter(item.diameter,realRange,1200),2),'radius');铅笔.beginPath();pencil.strokeStyle=boxPlotColorDic[item.parameterX]作为字符串;铅笔.lineWidth=12;pencil.arc(600,bignumberFc.subtract(600,computerCircleCenter(item.mean,realRange,range[0],1200)),bignumberFc.divide(computerDiameter(item.diameter,realRange,1200),2),0,2*数学.PI,);。中风();铅笔.closePath();});},[范围,数据]);return(你的浏览器不支持canvas标签,你看不到图形

);};注意:大号。代码中的方法,可以用加减乘除代替bigNumber.add(a,b)isa+bbigNumber.subtract(a,b)isa-bbigNumber.multiply(a,b)isa*bbigNumber.divide(a,b)是a/b