【问题标题】:Is there a way to reliably rotate SVG text within a resizable graphic?有没有办法在可调整大小的图形中可靠地旋转 SVG 文本?
【发布时间】:2019-03-26 14:47:21
【问题描述】:

我正在构建一个 SVG,它显示带有轴标签的相当标准的 X-Y 图。我希望 y 轴标签(在图表的左侧)垂直显示,整个文本旋转 90 度。例如,要绘制 velocity / time 图表,y 轴将是“速度”,V 显示在图表顶部,“y”显示在底部。

我的 SVG 是用 % 计算的所有尺寸和距离构建的,例如一条线可能会以这种方式呈现:

<line x1="5%" y1="8%" x2="10%" y2="6%" />

这样做是为了让图形“调整大小”以填充封闭应用程序、网页等为其提供的任何空间。

我知道如何旋转文本 (transform="rotate(Θ, cx, cy)"),但这不适用于 cxcy 值的百分比。我尝试将文本包装在&lt;g&gt; 中并旋转它(同样使用&lt;svg&gt;),但坐标系似乎是从父级继承的,所以我不能围绕@987654330 的“原点”旋转@ 或&lt;svg&gt; 然后将最终项目相对于外部坐标系放置(至少我还没有弄清楚如何)。

鉴于我对所有内容都使用百分比,有没有办法以我想要的方式旋转文本?

【问题讨论】:

    标签: svg text


    【解决方案1】:

    首先要注意的是,变换不会继承,而是为元素及其所有子元素定义一个新的坐标系。这可能看起来像是语义上的细节,但要理解 SVG,您需要考虑当前坐标系及其转换,否则规范的大部分内容看起来会令人困惑。

    transform attributeCSS transforms 的转换目前并不真正兼容。 SVG rotate() 函数不能可靠地跨浏览器获取单元标识符,CSS rotate() 函数没有旋转中心参数,但可以使用 transform-origin 属性。因此,您的问题有两种解决方案。两者都以文本锚作为旋转中心来描述

    CSS 方式

    transform-origin 是一个 CSS 属性,它采用两个长度的列表来描述旋转中心。默认情况下,旋转中心是旋转对象的中心。对于文本内容,这可能会对 vertical 中心的位置造成一些不确定性。最好定义一个显式的transform-box:view-box 并再次使用定位属性。

    line {
        stroke: red;
    }
    
    text {
        font-family: sans-serif;
        font-size: 15px;
    }
    
    .cross {
        transform: rotate(90deg);
        transform-origin: 20% 20%;
        transform-box: view-box;
    }
    <svg width="200" height="150">
        <line x1="20%" x2="20%" y1="0" y2="100%" />
        <line x1="0" x2="100%" y1="20%" y2="20%" />
        <text class="along" x="20%" y="20%">label</text>
        <text class="cross" x="20%" y="20%">label</text>
    </svg>

    注意 IE/Edge do not support 这个语法。

    SVG 方式

    SVG 支持产生新坐标系的第二种机制:定义新视口。为此,您必须嵌套一个 &lt;svg&gt; 元素。虽然目前不完全支持在&lt;svg&gt; 元素上定义transform 属性,但您可以设置新的xy 属性以有效实现翻译。

    这样,您可以先将文本定位在其本地坐标系的原点,将其旋转到位,然后再将其移动到具有百分比长度的新位置。

    line {
        stroke: red;
    }
    
    text {
        font-family: sans-serif;
        font-size: 15px;
    }
    
    svg svg {
        overflow: visible;
    }
    <svg width="200" height="150">
        <line x1="20%" x2="20%" y1="0" y2="100%" />
        <line x1="0" x2="100%" y1="20%" y2="20%" />
        <text class="along" x="20%" y="20%">label</text>
        <svg x="20%" y="20%">
            <!-- x, y and transform center all default to 0 -->
            <text class="cross" transform="rotate(90)">label</text>
        </svg>
    </svg>

    您需要在内部 svg 上设置 overflow:visible 以确保最终位于新视口之外的内容仍然可见。 (在上面的示例中,情况并非如此,但如果您使用例如 text-anchor:middle,则标签将从负 y 值开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      • 2010-11-08
      • 2021-08-30
      • 2021-03-14
      • 1970-01-01
      • 2018-02-27
      相关资源
      最近更新 更多