javascript HTML5 画布圆形文本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6061880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HTML5 Canvas Circle Text
提问by seymar
How do I create circle text (text in a circle shape) with canvas?
如何使用画布创建圆形文本(圆形文本)?
回答by cmptrgeekken
Letters should now be properly oriented:
字母现在应该正确定向:
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();
}
Sample usage:
示例用法:
var ctx = document.getElementById('canvas').getContext('2d');
ctx.font = "bold 30px Serif";
ctx.fillTextCircle("Circle Text ",150,150,75,Math.PI / 2);
The extra space at the end of the string adds some extra padding.
字符串末尾的额外空间添加了一些额外的填充。
Sample output:
示例输出:
回答by Simon Sarris
It can technically be done, but there is no built in way. You'd have to calculate an arc, and draw each letter individually along that arc, figuring out the angle and positioning yourself.
它在技术上是可以做到的,但没有内置的方法。您必须计算一条弧线,然后沿着该弧线单独绘制每个字母,确定角度并自己定位。
Many people end up making their own methods (like the above) for text. Heck, multiline text can't even be done by default!
许多人最终为文本制作了自己的方法(如上述)。哎呀,默认情况下甚至无法完成多行文本!
EDIT:Here is a working example, piggybacking off of cmptrgeekken's work. If you upvote me, upvote him too :P
编辑:这是一个工作示例,搭载 cmptrgeekken 的工作。如果你给我点赞,也给他点赞 :P
What it looks like:
它的样子:
回答by Jralford
On my blog, I take a fairly close look at creating circular text using HTML5 Canvas:
在我的博客中,我仔细研究了如何使用 HTML5 Canvas 创建圆形文本:
In the example, options include rounded text alignment (left, center and right) from a given angle, inward and outward facing text, kerning (adjustable gap between characters) and text inside or outside the radius.
在示例中,选项包括从给定角度的圆形文本对齐(左、中和右)、向内和向外的文本、字距调整(字符之间的可调整间隙)以及半径内或外的文本。
There is also a jsfiddlewith a working example.
还有一个带有工作示例的jsfiddle。
It is as follows:
如下:
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);
}
回答by Servus7
A version in which the size of characters is counted. The spaces between the letters are therefore always the same size.
计算字符大小的版本。因此,字母之间的空格大小始终相同。
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();
}
回答by Tishenko Yuri
It's my modification of this: http://jsfiddle.net/Brfp3/3/But feature allows you to display text clockwise and counterclockwise.
这是我对此的修改: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();
}
Sample usage:
示例用法:
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);
回答by peterhry
CircleType.js doesn't use canvas but achieves the same effect: http://circletype.labwire.ca- also works well in fluid layouts.
CircleType.js 不使用画布,但实现了相同的效果:http://circletype.labwire.ca - 在流体布局中也能很好地工作。