如何在画布html5中旋转此文本?

时间:2016-02-29 10:53:32

标签: javascript jquery html5 canvas

我写了这段代码。之前我用纯js,css,html5编程了它,但它在iDevices上看起来很怪异所以我想我也可以在画布上轻松制作它。但我遇到了以下问题。

您可以看到检查文字角度的情况。我试了很多东西,但仍然无法将文字颠倒在“图表”的另一边。有人可以帮我吗?

$(document).ready(function() {
  var orange = "#ef5e09";
  var c = $("#myChart");
  var ctx = c.get(0).getContext("2d");

  var dData = function() {
    return Math.round(Math.random() * 90) + 10
  };

  var data = {
    labels: ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10"],
    data: [dData(), dData(), dData(), dData(), dData(), dData(), dData(), dData(), dData(), dData()]
  }

  function draw() {
    //check canvas parent width and calculate dimensions
    c.css("width", c.parent().width());
    c.css("height", c.parent().width());
    ctx.canvas.width = c.parent().width();
    ctx.canvas.height = ctx.canvas.width;
    var d = {
      cX: ctx.canvas.width / 2,
      cY: ctx.canvas.width / 2,
      width: ctx.canvas.width,
      height: ctx.canvas.height,
      lineWidth: ctx.canvas.width * 0.00934579,
      radius: ctx.canvas.width * 0.03,
      cW: ctx.canvas.width * 0.002,
      fW: ctx.canvas.width * 0.28
    };

    // draw bg circles
    for (var i = 10; i > 0; i--) {
      ctx.beginPath();
      ctx.arc(d.cX, d.cY, i * d.radius, 0, 2 * Math.PI, false);
      if (i % 2) {
        ctx.fillStyle = '#f6f7f8';
        ctx.fill();
      } else {
        ctx.fillStyle = '#fff';
        ctx.fill();
      }
      ctx.lineWidth = d.cW;
      ctx.strokeStyle = '#babbbc';
      ctx.stroke();
    }
    var sa = 2 * Math.PI / data.data.length;
    var font = d.width * (18 / 1000) + 'px Verdana';

    for (var i = 0; i < data.data.length; i++) {
      var v = 10 * d.radius * (data.data[i] / 100);
      var nX = d.cX + v * Math.cos(i * sa);
      var nY = d.cY + v * Math.sin(i * sa);
      ctx.beginPath();
      ctx.moveTo(d.cX, d.cY);
      ctx.lineTo(nX, nY);
      ctx.strokeStyle = orange;
      ctx.lineWidth = d.lineWidth;
      ctx.stroke();

      var l = data.labels[i];

      var nX = Math.floor(d.cX + 11 * d.radius * Math.cos(i * sa));
      var nY = Math.floor(d.cY + 11 * d.radius * Math.sin(i * sa));
      console.log(l + " [" + nX + ":" + nY + "]");
      ctx.save();

      var origAlign = ctx.textAlign;

      if (i * sa > Math.PI / 2 && i * sa < 1.5 * Math.PI) {
      //here's the edited part where I tried to rotate the text in place
      ctx.translate(-ctx.measureText(l).width,d.width*(18/1000)/2);
      ctx.rotate(Math.PI);
      //end of edited part
        ctx.translate(d.cX, d.cY);
        ctx.rotate((10 - i) * sa);
        ctx.font = font;
        ctx.fillStyle = orange;
        ctx.fillText(l, 10.5 * d.radius, 5);
      } else {
        ctx.translate(d.cX, d.cY);
        ctx.rotate((10 - i) * sa);
        ctx.font = font;
        ctx.fillStyle = orange;
        ctx.fillText(l, 10.5 * d.radius, 5);
      }

      ctx.restore();
    }
  }

  draw();
  $(window).resize(draw);
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="col-xs-6">
  <canvas id="myChart"></canvas>
</div>

2 个答案:

答案 0 :(得分:1)

测量文字时,需要在测量文字之前设置字体。

当围绕非原点的点(例如文本中间)旋转时,您需要翻译,旋转,翻译。

在您的代码中,尝试替换...

  if (i * sa > Math.PI / 2 && i * sa < 1.5 * Math.PI) {
  //here's the edited part where I tried to rotate the text in place
  ctx.translate(-ctx.measureText(l).width,d.width*(18/1000)/2);
  ctx.rotate(Math.PI);
  //end of edited part
    ctx.translate(d.cX, d.cY);
    ctx.rotate((10 - i) * sa);
    ctx.font = font;
    ctx.fillStyle = orange;
    ctx.fillText(l, 10.5 * d.radius, 5);
  } else {

...与

  if (i * sa > Math.PI / 2 && i * sa < 1.5 * Math.PI) {
    ctx.translate(d.cX, d.cY);
    ctx.rotate((10 - i) * sa);
    ctx.font = font;
    ctx.translate(10.5 * d.radius + ctx.measureText(l).width / 2, 0);
    ctx.rotate(Math.PI);
    ctx.translate(-10.5 * d.radius - ctx.measureText(l).width / 2, 0);
    ctx.fillStyle = orange;
    ctx.fillText(l, 10.5 * d.radius, 5);
  } else {

答案 1 :(得分:1)

以下是如何使用转换围绕中心点旋转文本,同时使文本保持任意角度。

  • 您可以使用context.translate + context.rotate以一定角度从中心点向外推送文字。

  • 您可以使用context.scale根据需要垂直或水平翻转文字。

  • 您可以使用context.textBaseline将文本显示与中心点保持一致的距离,无论其角度如何。

以下是示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var angle=0;
var angleIncrement=Math.PI/180;
var count=0;
var cx=75;
var cy=75;
var radius=3;
var PI2=Math.PI*2;
ctx.beginPath();
ctx.arc(cx,cy,3,0,PI2);
ctx.fill();

requestAnimationFrame(animate);


function animate(time){
    var PI2=Math.PI*2;
       
    ctx.clearRect(0,0,cw,ch);   
    ctx.beginPath();
    ctx.arc(cx,cy,3,0,PI2);
    ctx.fill();
    
    drawLabelAtAngle('Label #'+count,cx,cy,angle,radius);
   
    angle+=angleIncrement;
    angle=(angle+PI2)%PI2;

    count++;
    
    requestAnimationFrame(animate);
}


function drawLabelAtAngle(text,x,y,angle,offset){

    // calc the angle clampled between 0 & PI*2
    var normA=(angle+Math.PI*2)%(Math.PI*2);
    
    // get ready to flip the text if it is on the left side
    if(normA>=Math.PI*3/2 || normA<=Math.PI/2){
        ctx.textAlign='left';
        var flip=1;
        offset+=5;
    }else{
        ctx.textAlign='right';
        var flip=-1;
        offset-=10;
        
    }
    
    // set the baseline to middle
    ctx.textBaseline='middle';

    // set [0,0] to [x,y]
    ctx.translate(x,y);

    // rotate 
    ctx.rotate(angle);

    // if the text is on the left side, flip it for readability
    ctx.scale(flip,flip);

    // draw the text
    ctx.fillText(text,offset,0);

    // always clean up! 
    // reset transforms & text styling
    ctx.setTransform(1,0,0,1,0,0);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=150 height=150></canvas>