在仪表上布置标签的策略

时间:2014-04-17 22:19:08

标签: javascript canvas drawing

我已经构建了这个javascript / canvas规范库,可以有效地创建阈值和目标值,并围绕这些指标呈现指标。

我的问题不是javascript中特定于画布绘制等的任何内容,而是标签放置的策略。目前,我在标准角度上绘制了与弧心相距一定距离的标签。这似乎有效,但是我有一个问题,标签文本可以与另一个标签重叠(如果下界和目标太近)或标签与弧本身重叠。

只要我可以放下标签,我就可以轻松地画一条线到它需要指向仪表本身的位置。 (如本例所示)

我已经想到了在内存中创建粗略的猜测,然后沿着弧调整值,直到它们不再重叠。 (这看起来非常低效)

我希望有人可以提供一个指针,填补我的高中数学的空白以及它在这里的适用方式=)

label layout problems

1 个答案:

答案 0 :(得分:0)

这是制定衡量标准的一种策略

enter image description here

示例代码和演示:http://jsfiddle.net/m1erickson/v2AaD/

<!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>