I have some tile symbols that I would like to place on a grid. This is what I'm trying to achieve:
4,2
instead of 85,43
)I have solutions to the first two (there might be better solutions though) but not the third. I can rotate the tile at 4,2
by a quarter turn with this:
<!-- 10/21 = 0.47619047619 -->
<use x="4" y="2" href="#rooftop-0" class="theme-0" transform="rotate(90 4.476 2.476)" />
I really don't like having to specify the tile coordinates twice. Ideally, I would like to write something like this instead:
<use x="4" y="2" href="#rooftop-0" class="theme-0 rotate-1" />
Defining .rotate-1
in the stylesheet doesn't seem to have any effect on the rotation. transform-origin="50% 50%"
seems to be setting the origin to 50%
of the viewport or something. Maybe defining the symbol with coordinates from -10
to 10
instead of 0
to 20
would help? Should I define the viewBox
of the symbols?
Another solution would be manually changing the coordinates of the vertices in the symbol to create the other 3 orientations. I'd rather not!
Anyway, this is what I have so far:
<?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>
Here's a screenshot:
Is there a clean way of doing what I'm trying to do? Rotating a symbol around its center seems like something one would do all the time.
Instead of setting your <use> attributes using x
and y
coordinates, you can set them using transform="translate(x, y)
, this way, the origin parameters of the rotate()
method will stay the same (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>