代码之家  ›  专栏  ›  技术社区  ›  Christopher Schultz

是否有方法在可调整大小的图形中可靠地旋转SVG文本?

  •  0
  • Christopher Schultz  · 技术社区  · 6 年前

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

    我的svg是用所有大小和距离计算出来的 % ,例如,一条线可以这样呈现:

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

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

    我知道如何旋转文字( transform="rotate(Θ, cx, cy)" )但这不适用于 cx cy 价值观。我试过用 <g> 旋转(同样地 <svg> ,但坐标系似乎继承自父坐标系,因此无法围绕 <G> <SVG> 然后将最后一个项目相对于外部坐标系放置(至少我还没有弄清楚如何放置)。

    考虑到我对所有内容都使用百分比,有没有办法按照我喜欢的方式旋转文本?

    1 回复  |  直到 6 年前
        1
  •  0
  •   ccprog    6 年前

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

    转换为 transform attribute CSS transforms 目前并不完全兼容。SVG rotate() 函数不能可靠地跨浏览器获取单元标识符,并且css 旋转() 函数没有旋转中心的参数,但可以使用 transform-origin 财产。因此,你的问题有两种解决方法。两者都以文本锚定为旋转中心进行描述

    css方式

    变换原点 是一个css属性,使用两个长度的列表来描述旋转中心。默认情况下,旋转的中心是旋转对象的中心。对于文本内容,这可能会对 垂直的 中间的谎言。最好定义一个显式的 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支持产生新坐标系的第二种机制:定义新的视区。为此,你必须筑巢 <svg> 元素。在当前定义 转型 属性 <SVG> 元素不完全受支持,您可以设置新的 x y 有效实现翻译的属性。

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

    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>

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