代码之家  ›  专栏  ›  技术社区  ›  Sparafusile

在HTML5画布上绘制旋转文本

  •  55
  • Sparafusile  · 技术社区  · 16 年前

    • 顺时针标记y轴
    • 将文本旋转90度计数器
    • 线图上的标线

    5 回复  |  直到 16 年前
        1
  •  41
  •   kukuch robertc    7 年前

    正如其他人所提到的,您可能希望考虑重用现有的图形解决方案,但是旋转文本并不太困难。(对我来说)有点让人困惑的是,你把整个上下文循环,然后在上面画:

    ctx.rotate(Math.PI*2/(i*6));
    

    angle is in radians . 代码是 taken from this example transformations part of the MDC canvas tutorial

    请看 the answer below

        2
  •  137
  •   Community Mohan Dere    15 年前

    张贴这篇文章是为了帮助其他有类似问题的人。我用五个步骤解决了这个问题——保存上下文、翻译上下文、旋转上下文、绘制文本,然后将上下文恢复到保存的状态。

    我认为对上下文的翻译和转换就是操纵覆盖在画布上的坐标网格。默认情况下,原点(0,0)从画布的左上角开始。X从左到右增加,Y从上到下增加。如果你用食指和大拇指在左手上做一个“L”,然后把它放在你面前,大拇指朝下,你的大拇指会指向增加Y的方向,食指会指向增加X的方向。我知道这是基本的,但我发现它有助于思考平移和旋转。原因如下:

    转换上下文时,将坐标网格的原点移动到画布上的新位置。旋转上下文时,请考虑以顺时针方向旋转左手所做的“L”,即以弧度表示的相对于原点的角度。当您选择strokeText或fillText时,请指定相对于新对齐的轴的坐标。要确定文本的方向,使其从下到上可读,您需要将文本转换到下面的位置,在该位置上开始标签,旋转-90度并填充或笔划文本,沿旋转的x轴偏移每个标签。这样的方法应该有用:

     context.save();
     context.translate(newx, newy);
     context.rotate(-Math.PI/2);
     context.textAlign = "center";
     context.fillText("Your Label Here", labelXposition, 0);
     context.restore();
    

    .restore()将上下文重置回调用.save()时的状态--用于将内容返回到“正常”状态。


        3
  •  29
  •   dansch    12 年前

    虽然这是对上一个答案的一种补充,但它增加了一点(希望如此)。

    主要我想澄清的是,通常我们想画 draw a rectangle at 10, 3 .

    如果我们这样想: move origin to 10, 3 draw rectangle at 0, 0 .

    另一个要点是文本的对齐。在0,0处绘制文本是最容易的,因此使用正确的对齐方式可以允许我们在不测量文本宽度的情况下进行绘制。

    我们仍然应该将文本移动一定量以使其垂直居中,不幸的是canvas没有很好的行高支持,所以这是一个猜测和检查的事情(如果有更好的东西请纠正我)。

    enter image description here

    var font, lineHeight, x, y;
    
    x = 100;
    y = 100;
    font = 20;
    lineHeight = 15; // this is guess and check as far as I know
    this.context.font = font + 'px Arial';
    
    
    // Right Aligned
    this.context.save();
    this.context.translate(x, y);
    this.context.rotate(-Math.PI / 4);
    
    this.context.textAlign = 'right';
    this.context.fillText('right', 0, lineHeight / 2);
    
    this.context.restore();
    
    this.context.fillStyle = 'red';
    this.context.fillRect(x, y, 2, 2);
    
    
    // Center
    this.context.fillStyle = 'black';
    x = 150;
    y = 100;
    
    this.context.save();
    this.context.translate(x, y);
    this.context.rotate(-Math.PI / 4);
    
    this.context.textAlign = 'center';
    this.context.fillText('center', 0, lineHeight / 2);
    
    this.context.restore();
    
    this.context.fillStyle = 'red';
    this.context.fillRect(x, y, 2, 2);
    
    
    // Left
    this.context.fillStyle = 'black';
    x = 200;
    y = 100;
    
    this.context.save();
    this.context.translate(x, y);
    this.context.rotate(-Math.PI / 4);
    
    this.context.textAlign = 'left';
    this.context.fillText('left', 0, lineHeight / 2);
    
    this.context.restore();
    
    this.context.fillStyle = 'red';
    this.context.fillRect(x, y, 2, 2);
    

    this.context.fillText('right', 0, lineHeight / 2); 基本上是 0, 0 ,除了我们稍微移动文本使其居中靠近点

        4
  •  5
  •   WebWanderer    6 年前

    Funkodebat发布了一个伟大的解决方案,我已经参考了很多次。 不过,我发现自己每次都在写自己的工作模型。 所以,这是我的工作模式。。。更加清晰。

    首先, 文本的高度等于像素字体大小 . 这是我前段时间读到的,在我的计算中得到了结果。我不确定这是否适用于所有字体,但它似乎适用于Arial,sans-serif。

    另外,为了确保你把所有的文本都放在画布上(而且不要把“p”的尾部剪掉),你需要设置 context.text基线* .

    为此,我们需要 以及

    为什么要调整画布的大小? 例如,可以使用此画布绘制图表的所有标签(一个接一个),并将隐藏的画布绘制到需要标签的图表画布上( context.drawImage(hiddenCanvas, 0, 0); ).

    在测量文本之前设置字体,并在调整画布大小后将所有样式重新应用于上下文。调整画布大小时,画布的上下文将完全重置。

    var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    var font, text, x, y;
    
    text = "Mississippi";
    
    //Set font size before measuring
    font = 20;
    ctx.font = font + 'px Arial, sans-serif';
    //Get width of text
    var metrics = ctx.measureText(text);
    //Set canvas dimensions
    c.width = font;//The height of the text. The text will be sideways.
    c.height = metrics.width;//The measured width of the text
    //After a canvas resize, the context is reset. Set the font size again
    ctx.font = font + 'px Arial';
    //Set the drawing coordinates
    x = font/2;
    y = metrics.width/2;
    //Style
    ctx.fillStyle = 'black';
    ctx.textAlign = 'center';
    ctx.textBaseline = "bottom";
    //Rotate the context and draw the text
    ctx.save();
    ctx.translate(x, y);
    ctx.rotate(-Math.PI / 2);
    ctx.fillText(text, 0, font / 2);
    ctx.restore();
    <canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
        5
  •  1
  •   bpeterson76    16 年前

    这里有一个HTML5替代自制程序: http://www.rgraph.net/ 你也许可以对他们的方法进行逆向工程。。。。

    你也可以考虑类似Flot的东西( http://code.google.com/p/flot/ http://www.maxb.net/scripts/jgcharts/include/demo/#1 )它不是很酷,但是完全向后兼容,而且很容易实现。