Javascript 在仪表上布置标签的策略
我构建了这个javascript/canvas仪表库,它可以有效地让您创建阈值和目标值,并围绕这些指标呈现仪表 我的问题不是javascript中画布绘制等的具体内容,而是标签放置的策略。当前,我在计算的角度上打印距离弧中心的标签。这似乎是可行的,但是我遇到了一个问题,标签文本可能与另一个标签重叠(如果下限和目标太接近),或者标签与弧本身重叠 一旦我能得到标签的位置下来,我总是可以很容易地画一条线,它需要在仪表上的点本身。(如本例所示) 我一直在考虑在内存中创建一个粗略的guestimate,然后沿圆弧调整值,直到它们不再重叠。(这似乎效率极低) 我希望有人能提供一个指针,填补我高中数学的空白,以及它在这里的应用=)Javascript 在仪表上布置标签的策略,javascript,canvas,drawing,Javascript,Canvas,Drawing,我构建了这个javascript/canvas仪表库,它可以有效地让您创建阈值和目标值,并围绕这些指标呈现仪表 我的问题不是javascript中画布绘制等的具体内容,而是标签放置的策略。当前,我在计算的角度上打印距离弧中心的标签。这似乎是可行的,但是我遇到了一个问题,标签文本可能与另一个标签重叠(如果下限和目标太接近),或者标签与弧本身重叠 一旦我能得到标签的位置下来,我总是可以很容易地画一条线,它需要在仪表上的点本身。(如本例所示) 我一直在考虑在内存中创建一个粗略的guestimate,然
这里有一个策略来展示你的语言 示例代码和演示:
正文{背景色:象牙;}
#包装器{位置:相对;}
画布{位置:绝对;左:40px;顶部:5px;边框:1px纯红色;}
#金额{位置:绝对;左侧:1px;顶部:5px;页边距底部:15px;宽度:23px;边框:0;颜色:#f6931f;字体重量:粗体;}
#滑块垂直{位置:绝对;左侧:5px;顶部:40px;宽度:15px;高度:225px;边框:0px;颜色:#f6931f;字体重量:粗体;}
$(函数(){
var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”);
var-PI=Math.PI;
var-cx=200;
var-cy=200;
var半径=100;
var min=0;
var max=1000;
var minBound=250;
var maxBound=750;
弧宽=40;
宽度=4;
var值=400;
var tickColor=“黑色”;
$(“#滑块垂直”)。滑块({
方向:“垂直”,
射程:“分钟”,
敏:敏,,
马克斯:马克斯,
值:tickValue,
幻灯片:功能(事件、用户界面){
美元(“#金额”).val(ui.value);
绘制(ui.value);
}
});
$(“金额”).val($(“垂直滑块”).slider(“值”);
绘制(数值);
函数绘制(值){
价值=价值;
tickColor=“绿色”;
如果(tickValuemaxBound){tickColor=“red”;}
//
clearRect(0,0,canvas.width,canvas.height);
drawArc();
抽虱(绞碎的,“灰色”);
抽签(最大绑定,“灰色”);
drawTick(tickValue,tickColor,10);
drawLabel(minBound,“灰色”,20,18);
drawLabel(最大绑定,“灰色”,20,18);
drawLabel(tickValue,tickColor,55,24);
}
函数drawArc(){
ctx.beginPath();
ctx.弧(cx,cy,半径,0,π,真);
ctx.线宽=弧宽;
ctx.strokeStyle=“浅灰色”;
ctx.stroke();
}
函数drawTick(值、颜色、扩展名){
var plus=扩展| | 0;
var角度=PI+tickValue/(最大-最小)*PI;
var x1=cx+(半径弧宽/2)*数学cos(角度);
变量y1=cy+(半径弧宽/2)*数学sin(角度);
var x2=cx+(半径+弧宽/2+加号)*数学cos(角度);
变量y2=cy+(半径+弧宽/2+加号)*数学sin(角度);
ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.lineWidth=tickWidth;
ctx.strokeStyle=颜色;
ctx.stroke();
}
函数drawLabel(值、颜色、扩展名、字体大小){
var角度=PI+tickValue/(最大-最小)*PI;
var x=cx+(半径+弧宽/2+延伸)*数学cos(角度);
变量y=cy+(半径+弧宽/2+延伸)*数学sin(角度);
ctx.textAlign=“中心”;
ctx.fillStyle=颜色;
ctx.font=fontsize+“px arial”;
ctx.fillText(tickValue,x,y);
}
}); // end$(函数(){});
您必须更改数字的布局。只要250针在灰色针的外侧居中,那么250针在靠近1针或1000针时将始终与1针或1000针重叠。也许将1和1000移动到灰色弧内的白色区域,使它们变小。这就是问题的关键,我可以检测标签的碰撞,并将它们移动一部分,直到它们不再重叠(然后只画线指向仪表上的适当位置),但我认为这非常低效。我希望有人有一些数学技巧,可以帮助我明智地说,哦,0和5标签将重叠,将它们放置在碰撞检查循环以外的其他位置
<!doctype html>
<html lang="en">
<head>
<style>
body{ background-color: ivory; }
#wrapper{ position:relative; }
canvas{ position:absolute; left:40px; top:5px; border:1px solid red;}
#amount{ position:absolute; left:1px; top:5px; margin-bottom:15px; width:23px; border:0; color:#f6931f; font-weight:bold; }
#slider-vertical{ position:absolute; left:5px; top:40px; width:15px; height:225px; border:0px; color:#f6931f; font-weight:bold; }
</style>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script>
$(function() {
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var PI=Math.PI;
var cx=200;
var cy=200;
var radius=100;
var min=0;
var max=1000;
var minBound=250;
var maxBound=750;
var arcWidth=40;
var tickWidth=4;
var tickValue=400;
var tickColor="black";
$( "#slider-vertical" ).slider({
orientation: "vertical",
range: "min",
min: min,
max: max,
value:tickValue,
slide:function( event, ui ) {
$( "#amount" ).val(ui.value);
draw(ui.value);
}
});
$( "#amount" ).val( $( "#slider-vertical" ).slider( "value" ) );
draw(tickValue);
function draw(value){
tickValue=value;
tickColor="green";
if(tickValue<minBound){tickColor="blue";}
if(tickValue>maxBound){tickColor="red";}
//
ctx.clearRect(0,0,canvas.width,canvas.height);
drawArc();
drawTick(minBound,"gray");
drawTick(maxBound,"gray");
drawTick(tickValue,tickColor,10);
drawLabel(minBound,"gray",20,18);
drawLabel(maxBound,"gray",20,18);
drawLabel(tickValue,tickColor,55,24);
}
function drawArc(){
ctx.beginPath();
ctx.arc(cx,cy,radius,0,PI,true);
ctx.lineWidth=arcWidth;
ctx.strokeStyle="lightgray";
ctx.stroke();
}
function drawTick(tickValue,color,extension){
var plus=extension||0;
var angle=PI+tickValue/(max-min)*PI;
var x1=cx+(radius-arcWidth/2)*Math.cos(angle);
var y1=cy+(radius-arcWidth/2)*Math.sin(angle);
var x2=cx+(radius+arcWidth/2+plus)*Math.cos(angle);
var y2=cy+(radius+arcWidth/2+plus)*Math.sin(angle);
ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.lineWidth=tickWidth;
ctx.strokeStyle=color;
ctx.stroke();
}
function drawLabel(tickValue,color,extension,fontsize){
var angle=PI+tickValue/(max-min)*PI;
var x=cx+(radius+arcWidth/2+extension)*Math.cos(angle);
var y=cy+(radius+arcWidth/2+extension)*Math.sin(angle);
ctx.textAlign="center";
ctx.fillStyle=color;
ctx.font=fontsize+"px arial";
ctx.fillText(tickValue,x,y);
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="wrapper">
<input type="text" id="amount" />
<div id="slider-vertical"></div>
<canvas id="canvas" width=425 height=300></canvas>
</div>
</body>
</html>