2011-05-19 125 views
17

如何用畫布創建圓圈文字(圓形文字)?HTML5 Canvas Circle Text

Like this

+0

這是一個想法,放在一個圓形分隔每個字母,但不能我真的「彎」了嗎? – 2011-05-19 16:40:40

+0

我推薦你使用svg,這是更強大的做這樣的事情 – 2011-05-19 16:42:59

+0

Jeah形象是可能的.. – 2011-05-19 16:52:54

回答

21

信現在應該有正確的取向:

CanvasRenderingContext2D.prototype.fillTextCircle = function(text,x,y,radius,startRotation){ 
    var numRadsPerLetter = 2*Math.PI/text.length; 
    this.save(); 
    this.translate(x,y); 
    this.rotate(startRotation); 

    for(var i=0;i<text.length;i++){ 
     this.save(); 
     this.rotate(i*numRadsPerLetter); 

     this.fillText(text[i],0,-radius); 
     this.restore(); 
    } 
    this.restore(); 
} 

使用示例:

var ctx = document.getElementById('canvas').getContext('2d'); 
ctx.font = "bold 30px Serif"; 
ctx.fillTextCircle("Circle Text ",150,150,75,Math.PI/2); 

字符串末尾的額外空間會添加一些額外的填充。

輸出示例:

Sample Output

+0

我已經想過做這個,謝謝你的開始。它仍然需要我看到的一些改進:P – 2011-05-19 17:03:56

+0

當然可以。只是一個快速代碼作爲概念驗證:) – cmptrgeekken 2011-05-19 17:04:45

+0

爲例!爲了旋轉字母,我修改了cmptrgeekken的代碼,所以現在我們有一個工作示例,它已經成了「全圓」! – 2011-05-19 17:26:30

5

它在技術上可以做到,但存在方式沒有內置。你必須計算一條弧線,並沿弧線逐個繪製每個字母,找出角度並定位。

很多人最終都是爲自己的方法制作自己的方法(如上所述)。哎呀,多行文本甚至不能默認完成!

編輯:這是一個工作的例子,捎帶cmptrgeekken的工作。如果你給予好評我,給予好評他太多:P

http://jsfiddle.net/c3Y8M/1/

它看起來像什麼:

Sample

1

這是我的這個修改:http://jsfiddle.net/Brfp3/3/ 但功能允許您顯示文本順時針和逆時針。

function textCircle(text,x,y,radius,space,top){ 
      space = space || 0; 
      var numRadsPerLetter = (Math.PI - space * 2)/text.length; 
      ctx.save(); 
      ctx.translate(x,y); 
      var k = (top) ? 1 : -1; 
      ctx.rotate(-k * ((Math.PI - numRadsPerLetter)/2 - space)); 
      for(var i=0;i<text.length;i++){ 
       ctx.save(); 
       ctx.rotate(k*i*(numRadsPerLetter)); 
       ctx.textAlign = "center"; 
      ctx.textBaseline = (!top) ? "top" : "bottom"; 
      ctx.fillText(text[i],0,-k*(radius)); 
       ctx.restore(); 
      } 
      ctx.restore(); 
     } 

使用範例:

ctx.font = "bold 30px Courier"; 
textCircle("Half circle Text",150,150,75,Math.PI/12,1); 
textCircle("Half circle Text",150,150,75,Math.PI/12); 
2

計算字符大小的版本。字母之間的空格總是相同的大小。

function drawTextAlongArc(context, str, centerX, centerY, radius, angle) { 
    var len = str.length, s, letterAngle; 

    context.save(); 
    context.textAlign = 'center'; 
    context.translate(centerX, centerY); 
    context.rotate(angle + Math.PI/2); 

    for (var n = 0; n < len; n++) { 
     s = str[n]; 
     letterAngle = 0.5*(context.measureText(s).width/radius); 

     context.rotate(letterAngle); 
     context.save(); 

     context.translate(0, -radius); 
     context.fillText(s, 0, 0); 
     context.restore(); 

     context.rotate(letterAngle); 
    } 
    context.restore(); 
} 
4

在我的博客,我走在創建使用HTML5畫布圓形的文字相當密切關注:

blog.graphicsgen.com

在這個例子中,選項包括圓形的文本對齊方式(左,中,右)從給定的角度,內向和外向文本,字距(字符之間的可調差距)以及半徑內部或外部的文本。

還有一個jsfiddle與一個工作示例。

這是如下:

document.body.appendChild(getCircularText("ROUNDED TEXT LOOKS BEST IN CAPS!", 250, 0, "center", false, true, "Arial", "18pt", 2)); 

function getCircularText(text, diameter, startAngle, align, textInside, inwardFacing, fName, fSize, kerning) { 
    // text:   The text to be displayed in circular fashion 
    // diameter:  The diameter of the circle around which the text will 
    //    be displayed (inside or outside) 
    // startAngle: In degrees, Where the text will be shown. 0 degrees 
    //    if the top of the circle 
    // align:  Positions text to left right or center of startAngle 
    // textInside: true to show inside the diameter. False to show outside 
    // inwardFacing: true for base of text facing inward. false for outward 
    // fName:  name of font family. Make sure it is loaded 
    // fSize:  size of font family. Don't forget to include units 
    // kearning:  0 for normal gap between letters. positive or 
    //    negative number to expand/compact gap in pixels 
//------------------------------------------------------------------------ 

    // declare and intialize canvas, reference, and useful variables 
    align = align.toLowerCase(); 
    var mainCanvas = document.createElement('canvas'); 
    var ctxRef = mainCanvas.getContext('2d'); 
    var clockwise = align == "right" ? 1 : -1; // draw clockwise for aligned right. Else Anticlockwise 
    startAngle = startAngle * (Math.PI/180); // convert to radians 

    // calculate height of the font. Many ways to do this 
    // you can replace with your own! 
    var div = document.createElement("div"); 
    div.innerHTML = text; 
    div.style.position = 'absolute'; 
    div.style.top = '-10000px'; 
    div.style.left = '-10000px'; 
    div.style.fontFamily = fName; 
    div.style.fontSize = fSize; 
    document.body.appendChild(div); 
    var textHeight = div.offsetHeight; 
    document.body.removeChild(div); 

    // in cases where we are drawing outside diameter, 
    // expand diameter to handle it 
    if (!textInside) diameter += textHeight * 2; 

    mainCanvas.width = diameter; 
    mainCanvas.height = diameter; 
    // omit next line for transparent background 
    mainCanvas.style.backgroundColor = 'lightgray'; 
    ctxRef.fillStyle = 'black'; 
    ctxRef.font = fSize + ' ' + fName; 

    // Reverse letters for align Left inward, align right outward 
    // and align center inward. 
    if (((["left", "center"].indexOf(align) > -1) && inwardFacing) || (align == "right" && !inwardFacing)) text = text.split("").reverse().join(""); 

    // Setup letters and positioning 
    ctxRef.translate(diameter/2, diameter/2); // Move to center 
    startAngle += (Math.PI * !inwardFacing); // Rotate 180 if outward 
    ctxRef.textBaseline = 'middle'; // Ensure we draw in exact center 
    ctxRef.textAlign = 'center'; // Ensure we draw in exact center 

    // rotate 50% of total angle for center alignment 
    if (align == "center") { 
     for (var j = 0; j < text.length; j++) { 
      var charWid = ctxRef.measureText(text[j]).width; 
      startAngle += ((charWid + (j == text.length-1 ? 0 : kerning))/(diameter/2 - textHeight))/2 * -clockwise; 
     } 
    } 

    // Phew... now rotate into final start position 
    ctxRef.rotate(startAngle); 

    // Now for the fun bit: draw, rotate, and repeat 
    for (var j = 0; j < text.length; j++) { 
     var charWid = ctxRef.measureText(text[j]).width; // half letter 
     // rotate half letter 
     ctxRef.rotate((charWid/2)/(diameter/2 - textHeight) * clockwise); 
     // draw the character at "top" or "bottom" 
     // depending on inward or outward facing 
     ctxRef.fillText(text[j], 0, (inwardFacing ? 1 : -1) * (0 - diameter/2 + textHeight/2)); 

     ctxRef.rotate((charWid/2 + kerning)/(diameter/2 - textHeight) * clockwise); // rotate half letter 
    } 

    // Return it 
    return (mainCanvas); 
}