如何围绕符号中心旋转符号而又没有两次指定其位置?

时间:2019-05-10 01:26:52

标签: css svg css-transforms

我有一些图块符号要放置在网格上。这是我要实现的目标:

  • 使用图块坐标来定位符号(例如,4,2而不是85,43
  • 使用像素坐标(而不是图块坐标)来定义符号的顶点
  • 绕符号中心旋转符号而不指定绝对坐标。

我对前两个有解决方案(虽然可能有更好的解决方案),但对第三个没有解决方案。我可以将4,2上的图块旋转四分之一圈:

<!-- 10/21 = 0.47619047619 -->
<use x="4" y="2" href="#rooftop-0" class="theme-0" transform="rotate(90 4.476 2.476)" />

我真的不喜欢必须两次指定图块坐标。理想情况下,我想写这样的东西:

<use x="4" y="2" href="#rooftop-0" class="theme-0 rotate-1" />

在样式表中定义.rotate-1似乎对旋转没有任何影响。 transform-origin="50% 50%"似乎正在将视口等的原点设置为50%。也许用从-1010020的坐标来定义符号会有所帮助?我应该定义符号的viewBox吗?

另一种解决方案是手动更改符号中顶点的坐标以创建其他3个方向。我宁愿不要!

无论如何,这是我到目前为止所拥有的:

<?xml version="1.0" standalone="no"?>
<!-- 21*10+1 = 211 -->
<svg width="211" height="211" version="2.0" xmlns="http://www.w3.org/2000/svg">
  <style>
    .grid-line {
      fill: #DDD;
    }
    .grass-fill {
      fill: #8C8;
    }
    .tile {
      /* 1/21 = 0.04761904761 */
      transform: scale(0.04761904761, 0.04761904761);
    }

    .theme-0 {
      --roof-color-0: #F44;
      --roof-color-1: #F66;
      --roof-color-2: #F88;
      --roof-color-3: #FAA;
    }

    .theme-1 {
      --roof-color-0: #44F;
      --roof-color-1: #66F;
      --roof-color-2: #88F;
      --roof-color-3: #AAF;
    }
  </style>

  <defs>
    <pattern id="grid" width="21" height="21" patternUnits="userSpaceOnUse">
      <rect class="grid-line" x="0" y="0" width="1" height="21" />
      <rect class="grid-line" x="0" y="0" width="21" height="1" />
    </pattern>

    <symbol id="rooftop-0">
      <g class="tile">
        <rect class="grass-fill" width="20" height="20" />
        <polygon style="fill: var(--roof-color-0)" points="3,2 17,2 18,8 2,8" />
        <polygon style="fill: var(--roof-color-1)" points="2,8 18,8 17,14 3,14" />
        <polygon style="fill: var(--roof-color-2)" points="8,8 11,14 11,18 8,18" />
        <polygon style="fill: var(--roof-color-3)" points="8,8 8,18 5,18 5,14" />
      </g>
    </symbol>

    <symbol id="rooftop-1">
      <g class="tile">
        <rect class="grass-fill" width="20" height="20" />
        <polygon style="fill: var(--roof-color-0)" points="2,11 18,11 17,17 3,17" />
        <polygon style="fill: var(--roof-color-1)" points="3,5 17,5 18,11 2,11" />
        <polygon style="fill: var(--roof-color-2)" points="10,11 10,3 13,3 13,5" />
        <polygon style="fill: var(--roof-color-3)" points="10,11 7,5 7,3 10,3" />
      </g>
    </symbol>
  </defs>

  <g>
    <rect fill="#999" width="100%" height="100%" />
    <rect fill="url(#grid)" width="100%" height="100%" />
  </g>

  <g transform="translate(1, 1) scale(21, 21)">
    <use x="3" y="2" href="#rooftop-0" class="theme-1" />
    <!-- 10/21 = 0.47619047619 -->
    <use x="4" y="2" href="#rooftop-0" class="theme-0" transform="rotate(90 4.476 2.476)" />
    <use x="5" y="2" href="#rooftop-1" class="theme-1" />
  </g>
</svg>

以下是屏幕截图:

Screenshot

我真的希望有一种干净的方法来做我想做的事情。围绕其中心旋转符号似乎就像您一直在做的事情。

2 个答案:

答案 0 :(得分:1)

您可以使用x方法的原点参数,而无需使用ytransform="translate(x, y)坐标来设置属性,而是可以使用rotate()来设置它们将保持不变(0.5, 0.5):

<svg viewBox="0 0 211 211">
  <style>
    .grid-line {
      fill: #DDD;
    }
    .grass-fill {
      fill: #8C8;
    }
    .theme-0 {
      --roof-color-0: #F44;
      --roof-color-1: #F66;
      --roof-color-2: #F88;
      --roof-color-3: #FAA;
    }

    .theme-1 {
      --roof-color-0: #44F;
      --roof-color-1: #66F;
      --roof-color-2: #88F;
      --roof-color-3: #AAF;
    }
  </style>

  <defs>
    <pattern id="grid" x="-0.5" y="-0.5" width="20" height="20" patternUnits="userSpaceOnUse">
      <rect class="grid-line" x="0" y="0" width="1" height="20" />
      <rect class="grid-line" x="0" y="0" width="20" height="1" />
    </pattern>

    <symbol id="rooftop-0" viewBox="0 0 20 20">
      <g class="tile" transform="translate(0.5, 0.5) scale(0.95)">
        <rect class="grass-fill" width="20" height="20" />
        <polygon style="fill: var(--roof-color-0)" points="3,2 17,2 18,8 2,8" />
        <polygon style="fill: var(--roof-color-1)" points="2,8 18,8 17,14 3,14" />
        <polygon style="fill: var(--roof-color-2)" points="8,8 11,14 11,18 8,18" />
        <polygon style="fill: var(--roof-color-3)" points="8,8 8,18 5,18 5,14" />
      </g>
    </symbol>

    <symbol id="rooftop-1" viewBox="0 0 20 20">
      <g class="tile"transform="translate(0.5, 0.5) scale(0.95)">
        <rect class="grass-fill" width="20" height="20" />
        <polygon style="fill: var(--roof-color-0)" points="2,11 18,11 17,17 3,17" />
        <polygon style="fill: var(--roof-color-1)" points="3,5 17,5 18,11 2,11" />
        <polygon style="fill: var(--roof-color-2)" points="10,11 10,3 13,3 13,5" />
        <polygon style="fill: var(--roof-color-3)" points="10,11 7,5 7,3 10,3" />
      </g>
    </symbol>
  </defs>
  
  <g>
    <rect fill="#999" width="100%" height="100%" />
    <rect fill="url(#grid)" width="100%" height="100%" />
  </g>
  
  <g transform="scale(20, 20)">
      <use xlink:href="#rooftop-0" class="theme-1" width="1" height="1" transform="translate(4, 2) rotate(0,0.5,0.5)"/>
      <use xlink:href="#rooftop-1" class="theme-0" width="1" height="1" transform="translate(5, 2) rotate(90,0.5,0.5)"/>
      <use xlink:href="#rooftop-0" class="theme-1" width="1" height="1" transform="translate(6, 2) rotate(180,0.5,0.5)"/>
  </g>
</svg>

答案 1 :(得分:0)

我希望这是您要问的:该符号现在具有wiewBox属性:viewBox="0 0 20 20"这意味着该符号的宽度为20个单位,高度为20个单位。现在您可以使用如下符号:

<use xlink:href="#rooftop-0"  width="20" height="20" x="63" y="21"  />

如您所见,在这种情况下,我可以给该符号指定宽度和高度,宽度为=“ 20”,高度=“ 20”,但是您可以根据需要提供任何大小。另外,您可以使用x和y属性来重新定位所用符号。

现在,您还可以使用transform="rotate(90,73,31)"将use元素绕其中心旋转。这会将元素绕{x:73,y:31}点旋转90度

<svg viewBox="0 0 211 211">
  <style>
    .grid-line {
      fill: #DDD;
    }
    .grass-fill {
      fill: #8C8;
    }
    
    .theme-0 {
      --roof-color-0: #F44;
      --roof-color-1: #F66;
      --roof-color-2: #F88;
      --roof-color-3: #FAA;
    }
    
    .theme-1 {
      --roof-color-0: #44F;
      --roof-color-1: #66F;
      --roof-color-2: #88F;
      --roof-color-3: #AAF;
    }
  </style>
  
  <defs>
    <pattern id="grid" width="21" height="21" patternUnits="userSpaceOnUse">
      <rect class="grid-line" x="0" y="0" width="1" height="21" />
      <rect class="grid-line" x="0" y="0" width="21" height="1" />
    </pattern>
    
    <symbol id="rooftop-0" viewBox="0 0 20 20">
      <g class="tile">
        <rect class="grass-fill" width="20" height="20" />
        <polygon style="fill: var(--roof-color-0)" points="3,2 17,2 18,8 2,8" />
        <polygon style="fill: var(--roof-color-1)" points="2,8 18,8 17,14 3,14" />
        <polygon style="fill: var(--roof-color-2)" points="8,8 11,14 11,18 8,18" />
        <polygon style="fill: var(--roof-color-3)" points="8,8 8,18 5,18 5,14" />
      </g>
    </symbol>
    

  </defs>
  
  <g>
    <rect fill="#999" width="100%" height="100%" />
    <rect fill="url(#grid)" width="100%" height="100%" />
  </g>
  
  <g transform="translate(1, 1)">
    <use x="42" y="21" xlink:href="#rooftop-0" class="theme-1" width="20" height="20" />
    
    <use x="63" y="21" xlink:href="#rooftop-0" class="theme-0" width="20" height="20" transform="rotate(90,73,31)" />
  </g>
</svg>