
本文翻译自:
https://dzone.com/articles/circle-text-css-amp-js
在本文中,我将分享如何通过CSS和JS代码生成圆形文本。此技术的要点是为每个字母制作一个span
元素,并将其稍微旋转。然后,你可以通过调整字体大小和圆半径来生成你所需的圆形文本。
在在线Web应用程序中已经实现了类似的技术,例如MockoFun中的圆形文本生成器。

那么如何使用CSS和JavaScript将文本沿着圆形边缘排列呢?
圆形文本的HTML代码
<div>
<fieldset>
<label>Text:</label>
<input type="text" class="text" value="CIRCLE TEXT">
<label>Radius:</label>
<input class="radius" type="range" min="100" max="1000" value="500">
</fieldset>
</div>
<div class="curved-text">CIRCLE TEXT</div>
HTML代码非常简单。这里的div.curved-text
元素实际上是唯一重要的元素,因为那就是我们编写圆形文本的地方。
另一个div
元素仅包含弧形文本的配置选项:
输入弧形文本的内容 调整圆形文本的半径
圆形文本的CSS代码
.curved-text{
position:relative;
display:inline-block;
margin:0 auto;
font-size:32px;
}
.curved-text span{
min-width:0.5em;
text-align:center;
padding:30px;
margin:0px;
}
为了创建圆形文本效果,我们仅使用两个CSS类:
curved-text
:CSS类,用于弧形、圆形文本将驻留的wrapper元素curved-text span
:CSS类,用于组成圆形文本的每一个字母
圆形文本的JavaScript代码
import jquery from "https://cdn.skypack.dev/jquery@~3.5.1";
function updateCurvedText($curvedText, radius) {
$curvedText.css("min-width", "initial");
$curvedText.css("min-height", "initial");
var w = $curvedText.width(),
h = $curvedText.height();
$curvedText.css("min-width", w + "px");
$curvedText.css("min-height", h + "px");
var text = $curvedText.text();
var html = "";
Array.from(text).forEach(function (letter) {
html += `<span>${letter}</span>`;
});
$curvedText.html(html);
var $letters = $curvedText.find("span");
$letters.css({
position: "absolute",
height:`${radius}px`,
// backgroundColor:"orange",
transformOrigin:"bottom center"
});
var circleLength = 2 * Math.PI * radius;
var angleRad = w/(2*radius);
var angle = 2 * angleRad * 180/Math.PI/text.length;
$letters.each(function(idx,el){
$(el).css({
transform:`translate(${w/2}px,0px) rotate(${idx * angle - text.length*angle/2}deg)`
})
});
}
var $curvedText = $(".curved-text");
updateCurvedText($curvedText,500);
function settingsChanged(){
$curvedText.text($(".text").val());
updateCurvedText($curvedText,$(".radius").val());
}
$(".radius").on("input change",settingsChanged);
$(".text").on("input change",settingsChanged);
JavaScript代码是真正实现圆形文本的地方。
首先,我们导入jQuery库。你不使用jQuery也可以,但是在本示例中,我发现用jQuery操作HTML元素来完成圆形文本的设置非常方便。
updateCurvedText()
函数包含两个参数:
$curvedText
:对弧形文本wrapper元素的引用radius
:弧形/圆形文本的半径
那么这个函数是如何工作以及如何创建圆形文本的呢:
...
$curvedText.css("min-width", "initial");
$curvedText.css("min-height", "initial");
var w = $curvedText.width(),
h = $curvedText.height();
$curvedText.css("min-width", w + "px");
$curvedText.css("min-height", h + "px");
var text = $curvedText.text();
...
首先,我们重置文本包装器外框的min-width
和min-height
属性。这使得我们能够以正常的直线形式实际测量文本的尺寸。
之所以这样做,是因为当我们弯曲文本时,我们希望最终得到的元素尺寸不小于原始文本。否则,调整其半径时,该元素将在其位置上到处跳跃。
存储宽(w
),高(h
)以及text
,以备后用。
...
var html = "";
Array.from(text).forEach(function (letter) {
html += `<span>${letter}</span>`;
});
$curvedText.html(html);
...
接下来,我们需要将要弯曲文本的每个字母包装到span
元素中。只需遍历文本的每个字符,并在其周围添加一个span
元素即可。然后,用新的HTML代码替换包装器的内容。
请注意,span
元素将使用我们之前定义的CSS代码。
只需再执行几个步骤,就可以大功告成了!
...
var $letters = $curvedText.find("span");
$letters.css({
position: "absolute",
height:`${radius}px`,
transformOrigin:"bottom center"
});
...

假设,弧形文本的每个字母都变成一个矩形元素,其高度设置为所需圆形文本的半径值。我们还需要将transformOrigin
设置为矩形的底部中心,因为我们希望将每个字母旋转一定角度以将字母分布在一个圆上。
上面图片的目的就是为了让大家了解元素如何变换的思路。之所以添加position:absolute
样式的原因是,我们希望所有字母最初是重叠的。目的是因为我们想围绕相同的原点旋转这些矩形。
现在,最后一步——文本以圆圈形式实际旋转:
...
var circleLength = 2 * Math.PI * radius;
var angleRad = w/(2*radius);
var angle = 2 * angleRad * 180/Math.PI/text.length;
$letters.each(function(idx,el){
$(el).css({
transform:`translate(${w/2}px,0px) rotate(${idx * angle - text.length*angle/2}deg)`
})
});
...
解释一下代码:
变量circleLength
实际上并没有用到。这只是告诉大家如何计算圆的长度。
当我们已知切片边缘的长度时,这有助于我们确定圆形切片的角度。我们只需将此长度除以整体圆半径的两倍即可。
在我们的例子中,圆形切片的长度是初始文本的宽度。这里有一个前提是,无论你如何弯曲文本,字母的组合宽度始终是相同的。
通过使用之前提到的公式angleRad = w /(2 * radius)
,可以给出一个以弧度为单位的角度。CSS喜欢使用"度"来做单位。
因此,我们只需要将弧度转换为度。然后,我们将其除以文本中的字母数。这样,我们就有了旋转每个字母所需的角度步长。
计算出角度后,我们应用CSS将每个字母平移到单词的中心,然后以相同的角度(乘以字母在单词中的索引)旋转每个字母。
当我们旋转每个字母时,由于我们从角度值0开始,所以我们的终点又回到了从顶部开始的弧形文本。
很好,但是如果圆里面的文本居中并左右平衡,效果会更好。
因此,每次旋转字母时,我们只需要减去text.length * angle / 2
即可。
结论
现在你知道如何在CSS和JS中制作弧形文本或圆形文本了吧。
(本文完)

点赞和分享就是最大的支持❤️




