【问题标题】:flip svg coordinate system翻转svg坐标系
【发布时间】:2010-10-02 13:50:36
【问题描述】:

有没有办法翻转 SVG 坐标系,使 [0,0] 在左下角而不是左上角?

【问题讨论】:

    标签: svg coordinate-systems cartesian


    【解决方案1】:

    我做了很多实验,唯一合乎逻辑的方法如下:

    <g transform="translate(0,400)">
    <g transform="scale(1,-1)">
    

    其中 400 是图像的高度。这是做什么的,它将所有内容向下移动,以便图像的顶部现在是图像的底部,然后缩放操作翻转 Y 坐标,以便现在离开页面/图像的位被翻转回来以填充留下的空间。

    【讨论】:

    • 您需要第一次翻译吗?我已经通过viewbox="-200 -200 400 400" 实现了这一点。
    • 这些操作可以合并到一行。
    • 但是现在文字是颠倒的。
    • 您可以使用单个 matrix 转换而不是单独的 translatescale 转换。要翻转 y 轴,请尝试 &lt;g transform="matrix(1 0 0 -1 0 400"&gt;(400 是图像的高度)。
    • @felix 你是如何解决上行文本问题的?
    【解决方案2】:

    我发现的用于转换为笛卡尔坐标系的最佳组合非常简单:

    css

    svg.cartesian {
      display:flex;
    }
    
    /* Flip the vertical axis in <g> to emulate cartesian. */
    svg.cartesian > g {
      transform: scaleY(-1);
    }
    
    /* Re-flip all <text> element descendants to their original side up. */
    svg.cartesian > g text {
      transform: scaleY(-1);
    }
    <html>
      <head></head>
      <body>
    
      <svg class="cartesian" viewBox="-100 -100 200 200" preserveAspectRatio="xMidYMid meet">
      <g>
        <!-- SVG Start -->
    
        <!-- Vertical / Horizontal Axis: Can be removed if you don't want x/y axes. -->
        <path d="M0 -100 V 200" stroke="green" stroke-width="0.5" stroke-opacity="0.5" />
        <path d="M-100 0 H 200" stroke="green" stroke-width="0.5" stroke-opacity="0.5" />
        
        <!-- Plotting: This is an example plotting two points at (20, 20) and (-50, -35), replace it with your data. -->
        <g transform="translate(20, 20)">
          <circle r="1" />
          <text>(20, 20)</text>
        </g>
        <g transform="translate(-50, -35)">
          <circle r="0.5" />
          <text>(-50, -35)</text>
        </g>
    
        <!-- SVG End -->
      </g>
      </svg>
        </body>
      </html>

    这将通过 css scaleY(-1) 自动取消翻转页面上的所有文本元素。

    【讨论】:

    • 在我看来,这个答案有点被低估了。
    • 谢谢!我很高兴我把它写下来了。每当我需要这样做时,我都会参考它。我刚刚更新了 cmets,解释了这些部件的作用,因此更易于使用。
    • 这可以使用更多的解释。得到它的工作,但不是微不足道的。我会补充一些,但还没有完全理解...
    • @Tony - 我向 cmets 添加了更多信息。让我知道具体有什么令人困惑的地方,我会努力改进它。
    • 感谢您的更新。我在 CSS 中添加了几个 cmets,我认为现在可以理解了。
    【解决方案3】:

    我知道这是旧的,但我在做同样的事情,尝试了@Nippysaurus 版本,但这太烦人了,因为所有东西都会被旋转(所以如果你放图像,你必须把它们旋转回来)。不过还有另一种解决方案

    我所做的只是移动 svg 的 viewBox 并反转 y 轴上的所有坐标(并将对象的高度也移除到其左下角),例如:

    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="300" viewBox="0 -300 200 300">
      <rect x="20" y="-40" width="20" height="20" stroke="black" stroke-width="1px"></rect>
    </svg>
    

    这会将rect 放置在距离svg 左下角20,20 处,参见http://jsfiddle.net/DUVGz/

    【讨论】:

    • 乍一看,这似乎是一个杂项,但是,在尝试了所有其他解决方案之后,我不得不同意 @Guillaume 的观点,即所有 transform 解决方案都是 PIA,因为它对文本的影响等...,所以这是我为 SVG 输出采用的解决方案。
    • 但是转换内部的转换如何扇出? IE。嵌套组...
    【解决方案4】:

    是的,坐标旋转 -90,然后平移 + 新图形的高度就可以了。 W3C 有一个例子。

    【讨论】:

    • 我认为你的想法是旋转 180,然后是 -w 和 -h 的翻译。这个不行,[0,0]还在左上角。
    • 我怀疑您的 SVG 实现不符合标准,这对于(可能)很少使用的功能来说并不奇怪。 -90 的仿射旋转将笛卡尔象限 IV (+x, -y) 移动到象限 I (+x, +y)。旋转 180 度将使您的参考系进入象限 II,原点位于左下方。您的自我回答有效的原因是它与我的原始答案一致,但可能会使用您选择的 SVG 解释器中经过更好测试的位。就个人而言,我只是在我的用户空间代码中计算仿射变换,并对 SVG 功能持悲观态度。
    • 你可能是对的。我在 OS X 10.6 上使用 Safari,所以明天将在 Windows 机器上测试它。
    【解决方案5】:

    如果您不知道 svg 的大小,则可以对整个 SVG 元素使用 CSS 转换:

    #parrot {
        transform-origin: 50% 50%; /* center of rotation is set to the center of the element */
        transform: scale(1,-1);
    }
    

    学分: https://sarasoueidan.com/blog/svg-transformations/#transforming-svgs-with-css

    【讨论】:

      【解决方案6】:
      <g transform="translate(0,400) scale(1,-1)">
      

      也相当于下面的

      <g transform="scale(1,-1) translate(0,-400) ">
      

      【讨论】:

        【解决方案7】:

        另一种方法是使用 D3 v4 scaleLinear 创建一个将为您执行交换的函数。

        import * as d3 from "d3";
        
        ...
        
        // Set the height to the actual value to where you want to shift the coords.
        // Most likely based on the size of the element it is contained within
        let height = 1; 
        let y = d3.scaleLinear()
          .domain([0,1])
          .range([height,0]);
        
        console.log("0 = " + y(0));       // = 1
        console.log("0.5 = " + y(0.5));   // = 0.5
        console.log("1 = " + y(1));       // = 0
        console.log("100 = " + y(100));   // = -99
        console.log("-100 = " + y(-100)); // = 101
        

        runable code via tonic

        【讨论】:

          【解决方案8】:

          我通常所做的是将坐标绘制/放置在笛卡尔平面上 y 轴的负值处。稍后通过将y轴的负值替换为正值来传递坐标。

          【讨论】:

            【解决方案9】:

            我认为将元素旋转 180 度的最简单方法是旋转 180.1 度;

            transform="translate(180.1,0,0)"

            【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-10-02
            • 1970-01-01
            • 2020-11-11
            • 1970-01-01
            • 1970-01-01
            • 2019-05-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多