首页 >web前端 >html教程 >CSS秘密花园: 环形文本_html/css_WEB-ITnose

CSS秘密花园: 环形文本_html/css_WEB-ITnose

WBOY
WBOY原创
2016-06-24 11:22:421406浏览

《 CSS Secrets 》是 @Lea Verou 最新著作,这本书讲解了有关于CSS中一些小秘密。是一本CSSer值得一读的一本书,经过一段时间的阅读,我、@南北和@彦子一起将在W3cplus发布一系列相关的读后感,与大家一起分享。

尽管这不是一个常见的文本效果,有时候有一些比较短的文本需要遵循环形路径显示。这种时候,CSS就弃我们而去了。没有任何CSS属性或功能可以完成这个效果,我们唯一想到的CSS解决方案都非常麻烦,所以我们也就只是想想而已。真的没有什么办法可以实现这样的样式吗?除了使用图像,除了不影响我们文本的整体美观?

在 juliancheal.co.uk 上使用环形文本作为左边的按钮(知道我指的是哪里吗?);注意那里的环形文本是避免打破按钮的唯一办法,按钮形状的中间位置是由孔和螺纹组成的

解决方案

有一些脚本可以完成这个效果。它们通过将每个字母包裹在单独的 元素中,然后旋转到合适的角度来把它们一个一个组合成圆。这个方案不仅非常麻烦,而且还给页面的DOM元素添加了很多不必要的臃肿的标记。

尽管目前没有办法通过纯CSS来完成这个效果,但是我们可以通过一点内联SVG来很简单地完成。SVG本身就支持文本以任何路径显示,环形只不过是路径的一个特殊情况。我们来试一下!

SVG中文本按路径显示的基本方案是通过一个 元素来包裹我们的文本,把它放到一个 元素中。 元素通过 id 引用我们的路径中定义的 元素。在内联SVG中的文本还继承了我们的字体样式(除了 line-height ,因为这是SVG中默认的样式),所以我们不需要担心这个问题,就像我们引入一个外部的SVG图像一样。

可惜, 只可以存在于 元素中,这就是我们为什么不可以使用可读性更好的 元素作为我们的路径圆的原因。

假设我们要把“circular reasoning works because”这句话做成环形文本,占据一个圆圈的整个圆周,如图所示。

我们需要在HTML中添加一个内联SVG,并定义一个圆形路径:

<div class="circular">    <svg viewBox="0 0 100 100">        <path d="M 0,50 a 50,50 0 1,1 0,1 z" id="circle" />    </svg></div>

注意我们是通过 viewBox ,而不是 width 和 height 来定义它的单位。这可以让我们设置坐标系统和长宽比,而不是一个固定的大小。这不仅是因为它更紧凑,还因为它帮我们节省了几行CSS,因为我们不再需要为 元素应用值为 100% 的 width 和 height 值——它会自动调整为其容器的大小。

如果你不清楚 path 的语法,别担心。大家都是一样的,甚至是那些已经了解了SVG path语法的人,还是会忘记语法。如果你好奇,下面这三个命令已经非常好地概括了下面这些语法:

  • M 0,50 : 移动到点 (0,50)
  • a 50,50 0 1,1 0,1 : 从你当前点的位置,画一条圆弧,到一个新的点,新点的位置距原点往右 0 ,往下 1 。圆弧的半径为 50 ,水平和垂直方向都是。除了两种可能的角度,选择两条可能的弧形里边最大的,选择两个点中在右边的,而不是左边那个。
  • z : 通过直线段闭合路径。

为什么SVG路径的语法这么隐蔽?它当初被设计出来的时候,大家觉得没有人会手动编写SVG,所以SVG工作小组尽可能地用了最紧凑的语法,来减少文件大小。

目前,我们的路径只是一个黑色的圆。

我们需要通过 元素添加文本,并通过 xlink:href 属性把它链到我们的圆上,如下:

<div class="circular">    <svg viewBox="0 0 100 100">        <path d="M 0,50 a 50,50 0 1,1 0,1 z" id="circle" />        <text>            <textPath xlink:href="#circle">            circular reasoning works because            </textPath>        </text>    </svg></div>

如上图所示,尽管我们还需要做很多东西,来让它更像样更有可读性,我们已经取得了我们想要的效果,这是CSS很多年内都无法完成的!

下一步是移除我们的圆形路径上的黑色填充。我们并不希望圆形以任何方式显示出来;我们只是想要它作为我们文本的一个引导。有很多方式可以完成,比如把它加入到一个 中(这是专门为此而设计的)。但是,这里我们希望能够尽量较少SVG标签,所以我们直接通过CSS应用一个 fill: none 。

.circular path { fill: none; }

现在黑色的圆已经消失了

我们可以仔细研究其它问题了。下一步最大的问题是,我们大多数的文本是在SVG元素之外的,还被裁剪了。为了解决这个问题,我们需要让我们的容器元素更小一些,然后为SVG元素应用 overflow: visible ,这样它就不会裁剪它的视窗之外的任何内容了:

.circular {    width: 30em;    height: 30em;}.circular svg {    display: block;    overflow: visible;}

你可以在上图中看到效果。注意到我们已经差不多完成了,但是有一些文本还是被裁剪了。原因是SVG元素是根据它的尺寸浮动的,而不是溢出。因此,事实上,溢出盒子边界的 元素不会让整个SVG元素往下浮动。我们需要手动添加一个外边距来完成:

.circular {    width: 30em;    height: 30em;    margin: 3em auto 0;}.circular svg {    display: block;    overflow: visible;}

就是它了!我们的示例现在看起来和下图非常相像

文本也是可访问的。如果我们的圆形文本只有一个实例(如,一个网站的logo),那我们到这里就完成了。但是,如果我们关于这种类型的文本有不止一个实例,我们不希望每次都重复这些SVG标签,可以写一个简短的脚本来自动生成所需的SVG元素,如类似这样的标签:

<div class="circular">    circular reasoning works because</div>

该代码可以通过一个“circular”类遍历所有元素,移除它们的文本并把它存储在一个变量中,并添加必要的SVG元素:

$$('.circular').forEach(function(el) {    var NS = "http://www.w3.org/2000/svg";    var xlinkNS = "http://www.w3.org/1999/xlink";    var svg = document.createElementNS(NS, "svg");    var circle = document.createElementNS(NS, "path");    var text = document.createElementNS(NS, "text");    var textPath = document.createElementNS(NS, "textPath");    svg.setAttribute("viewBox", "0 0 100 100");    circle.setAttribute("d", "M0,50 a50,50 0 1,1 0,1z");    circle.setAttribute("id", "circle");    textPath.textContent = el.textContent;    textPath.setAttributeNS(xlinkNS, "xlink:href", "#circle");    text.appendChild(textPath);    svg.appendChild(circle);    svg.appendChild(text);    el.textContent = '';    el.appendChild(svg);});
声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn