如何在不指定其位置两次的情况下围绕其中心旋转符号?

How can I rotate a symbol around its center without specifying its position twice?

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

前两个我有解决方案(虽然可能有更好的解决方案)但第三个没有。我可以用这个将 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% 之类的。也许用 -1010 而不是 020 的坐标定义符号会有帮助?我应该定义符号的 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>

截图如下:

有没有一种干净的方法来做我想做的事情?围绕其中心旋转符号似乎是人们一直都会做的事情。

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

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

如您所见,我可以为符号指定宽度和高度,在本例中为 width="20" height="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>

您可以使用 transform="translate(x, y) 坐标设置您的 属性,而不是使用 xy 坐标设置它们,这样,[=14= 的原点参数] 方法将保持不变 (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>