是否有一种使用CSS3 / Canvas来弯曲/弧形文本的方法?

57

我正在尝试使用CSS3、HTML Canvas或者SVG(如下图所示)实现弯曲文字效果。这是否可能?如果可能,我该如何实现这个效果?

更新:澄清一下:将以动态方式样式化的文本。

弧形或弯曲文本示例


http://tavmjong.free.fr/INKSCAPE/MANUAL/web/svg_tests.php该网页展示了使用SVG可以实现的效果。仔细查看源代码可能有助于您找到解决方案。 - Vishal Seth
@Gabriel,奇怪的问题:那是什么字体?它看起来很好看。 - Winfield Trail
@sudowned:已经有一段时间了,但我相信它是 Futura。 - gabriel
希望这可以帮到你:http://stackoverflow.com/questions/7251177/curving-an-image-that-starts-as-a-rectangle-uploaded-by-user-preferably-using/29118400#29118400 - Sajith
10个回答

37

SVG可以直接支持文本沿着路径排列,不过它并不会把单个字符沿着路径弯曲。以下是创建该效果的示例:

...
<defs>
  <path id="textPath" d="M10 50 C10 0 90 0 90 50"/>
</defs>
<text fill="red">
  <textPath xlink:href="#textPath">Text on a Path</textPath>
</text>
...

3
为什么这不是答案?看起来是迄今为止最好的解决方案。 - user1637281

22

你可以使用canvas完成此操作,尝试使用以下代码作为示例:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Testing min-width and max-width</title>
    <style type="text/css">

    </style>

  </head>
  <body>
      <canvas id="cnv"></canvas>
      <script type="text/javascript" charset="utf-8">
          cnv = document.getElementById("cnv");
          cnv.width = 500;
          cnv.height = 300;
          ctx = cnv.getContext("2d");
          ctx.font = "bold 12px sans-serif";
          text = "abcdefghijklm"
          for (i = 0; i < text.length; i++) {
              ctx.fillText(text[i], 300, 100);
              ctx.rotate(0.1);
          }
      </script>
  </body>
</html>

它可能不完全正确,但我相信你能够调整它以满足你的喜好;)


2
对于IE浏览器,您必须使用excanvas:请查看此链接http://diveintohtml5.org/canvas.html#ie - Jakub Hampl
3
下面的SVG解决方案似乎更容易。为什么你不用这种方法呢? - user1637281

13

你可以使用一些CSS来实现,但我相信你不会很快在IE上运行。另一方面,酷的一点是文本是可选的:D

.num1 {
  -webkit-transform: translate(0px, 30px) rotate(-35deg);
}
.num2 {
  -webkit-transform: translate(0px, 25px) rotate(-25deg);
}
.num3 {
  -webkit-transform: translate(0px, 23px) rotate(0deg);
}
.num4 {
  -webkit-transform: translate(0px, 25px) rotate(25deg);
}
.num5 {
  -webkit-transform: translate(0px, 30px) rotate(35deg);
}

span {display: inline-block; margin: 1px;}
<div style="width: 300px; height: 300px; margin: 50px auto">
    <span class="num1">a</span><span class="num2">b</span><span class="num3">c</span><span class="num4">d</span><span class="num5">e</span>
</div>


坦白地说,我不关心IE浏览器。这个网站是为iPhone优化的,所以我只担心它在Webkit中能够正确显示。对于使用JavaScript技巧实现动态文本的建议,我可能可以尝试一下。谢谢。 - gabriel
IE9+支持CSS3 2D变换,而IE8及以下版本支持微软的矩阵变换,但在处理上略有不同。 - JayC
1
@JayC 是的,这篇帖子已经两年了。我相信使用“-ms-”前缀应该大部分能够正常工作,尽管我没有测试的手段。 - Jakub Hampl

11

太棒了!它非常容易使用。请注意,它需要另一个插件(“Lettering.js是必需的”)。 - Rav
加载时间太长了。 - user9437856

4

有一个使用CSS3曲线文本的jQuery插件,名为arctext.js。它相当不错,并且有一系列配置选项。我猜它在IE8上无法工作,但我猜大多数CSS3东西都不能!

还有一个演示页面,其中包含一些示例,请点击这里


3
您可以像这样使用SVG与<textPath>

function updateMessage(str) {
  document.getElementById("MyMessage").textContent = str;
}
<button onClick="updateMessage('The text has changed');">Change the text</button>
<svg viewBox="0 0 1000 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <path id="CurvedPath"
          d="M 0 150 Q 325 50 650 150 " />
  </defs>
  <text font-size="54" x='325' y='50'  text-anchor="middle"  fill="darkgreen" font-family=Arial,Helvetica  style="text-shadow: 2px 2px 3px gray;">
    <textPath id='MyMessage' xlink:href="#CurvedPath">THIS TEXT IS CURVED</textPath>
  </text>
</svg>


3
这个教程会用HTML5和画布(canvas)告诉你如何做。另一个答案提出了类似的想法,使用的是canvas.rotate方法,而这个教程还使用了canvas.translate。
以下是教程中的完整代码:

function drawTextAlongArc(context, str, centerX, centerY, radius, angle) {
  var len = str.length,
    s;
  context.save();
  context.translate(centerX, centerY);
  context.rotate(-1 * angle / 2);
  context.rotate(-1 * (angle / len) / 2);
  for (var n = 0; n < len; n++) {
    context.rotate(angle / len);
    context.save();
    context.translate(0, -1 * radius);
    s = str[n];
    context.fillText(s, 0, 0);
    context.restore();
  }
  context.restore();
}
var canvas = document.getElementById('myCanvas'),
  context = canvas.getContext('2d'),
  centerX = canvas.width / 2,
  centerY = canvas.height - 30,
  angle = Math.PI * 0.8,
  radius = 150;

context.font = '30pt Calibri';
context.textAlign = 'center';
context.fillStyle = 'blue';
context.strokeStyle = 'blue';
context.lineWidth = 4;
drawTextAlongArc(context, 'Text along arc path', centerX, centerY, radius, angle);

// draw circle underneath text
context.arc(centerX, centerY, radius - 10, 0, 2 * Math.PI, false);
context.stroke();
<!DOCTYPE HTML>
<html>

<head>
  <style>
    body {
      margin: 0px;
      padding: 0px;
    }
  </style>
</head>

<body>
  <canvas id="myCanvas" width="578" height="250"></canvas>
</body>

</html>


2
<embed width="100" height="100" type="image/svg+xml" src="path.svg">
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
      <path id="textPath" d="M10 50 C10 0 90 0 90 50"/>
    </defs>
  </svg>
</embed>

1
我使用上面提到的教程(作者是Simon Tewsi)编写了一个更好的解决方案,解决字距问题。不使用任何库,纯JS。
http://jsfiddle.net/fidnut/cjccg74f/中查看。
function drawTextAlongArcInside(ctx, str, font, color, radius, angle, centerX, centerY, wspace)

注意:SO 要求我在这里放置 JSFiddle 的所有代码。我认为这不明智,因为代码太多了,所以我只添加函数的名称。

-1

还有一个transform: skew(x, y),它不使用画布。


没有产生期望的结果。 - Victor Zamanian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接