-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathXX-layout.qmd
257 lines (220 loc) · 12.4 KB
/
XX-layout.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
```{r}
#| echo: false
source("code/before_script.R")
```
# Map layout {#sec-map-layout}
<!-- tm_layout -->
<!-- which features are the most important to explain? -->
## Positions {#sec-positions}
## Layout {#sec-layout}
### Colors {#sec-lcolors}
<!-- e.g. background colors -->
### Frame {#sec-lframe}
### Margins {#sec-lmargins}
### Typography {#sec-ltypography}
<!-- Font faces and font families -->
The decision about the used fonts is often neglected when creating programmable plots and maps.
Most often, the default fonts are used in these kinds of graphs.
This, however, could be a missed opportunity.
A lot of map information is expressed by text, including text labels (@sec-text), legend labels, text in attribute layers (@sec-attributes-layers), or the map title (@sec-layout-elements).
The used fonts impact the tone of the map [@guidero_typography_2017], and their customization allows for a map to stand out from maps using default options.
<!-- role of font faces and font families: -->
<!-- - highlight different levels/importance -->
As we mentioned above, many different map elements can be expressed or can use fonts.
In theory, we are able to set different fonts to each of them.
However, this could result in a confusing visual mix that would hinder our map information.
Therefore, the decision on the used fonts should be taken after considering the main map message, expected map audience, other related graph styles, etc.
In the following three sections, we explain font families and font faces, and give some overall tips on font selections, show how to define used fonts, and how to customize fonts on maps.
#### Font families and faces {#sec-fonts}
```{r}
#| echo: false
library(tmap)
data("World")
bf = c("plain", "italic", "bold", "bold.italic")
tm_bf = tm_shape(World) +
tm_borders(col_alpha = 0) +
tm_credits("plain", fontface = "plain", position = c("center", "center"),
size = 2) +
tm_credits("italic", fontface = "italic", position = c("center", "center"),
size = 2) +
tm_credits("bold", fontface = "bold", position = c("center", "center"),
size = 2) +
tm_credits("bold.italic", fontface = "bold.italic", position = c("center", "center"),
size = 2) +
tm_layout(frame = FALSE)
```
```{r}
#| echo: false
library(tmap)
data("World")
# ff = c("Times", "Helvetica", "Courier")
ff = c("serif", "sans", "monospace")
tm_ff = tm_shape(World) +
tm_borders(col_alpha = 0) +
tm_credits("serif", fontfamily = "serif", position = c("center", "center"),
size = 2) +
tm_credits("sans", fontfamily = "sans", position = c("center", "center"),
size = 2) +
tm_credits("monospace", fontfamily = "monospace", position = c("center", "center"),
size = 2) +
tm_layout(frame = FALSE)
```
```{r}
#| label: fig-fonts
#| message: false
#| echo: false
#| layout-ncol: 2
#| fig-cap: Basic font families, and font faces implemented in the tmap package.
#| fig-subcap:
#| - Font families
#| - Font faces
tm_ff
tm_bf
```
In **tmap**, fonts are represented by a font family (@fig-fonts-1) and a font face (@fig-fonts-2).
A font family is a collection of closely related lettering designs.
Examples of font families include *Times*, *Helvetica*, *Courier*, *Palatino*, etc.
On the other hand, font faces, such as *italic* or *bold*, influence the orientation or width of the fonts.
A *font* is, thus, a combination of a selected font family and font face.
There are a few general font families, such as serifs, sans serifs, and monospaced fonts.
Fonts from the serif family have small lines (known as *a serif*) attached to the end of some letters.
Notice, for example, short horizontal lines on the bottom of letters *r*, *i*, and *f* or vertical lines at the ends of the letter *s* in the top row of @fig-fonts-1.
The fonts in this family are often viewed as more formal.
On the other hand, the sans serif family do not have serifs and is considered more informal and modern.
The last font family, monospaced fonts, is often used in computer programming (IDEs, software text editors), but less often on maps.
A distinguishing feature of the monospaced fonts is that each letter or character in this family has the same width.
Therefore, letters, such as *i* and *a* will occupy the same space in the monospaced fonts.
<!-- explain what are font faces -->
Mixing the use of serif and sans serif fonts often works well for maps.
However, a rule of thumb is not to mix more than two font families on one map.
A sans serif font can be used to label cultural objects, while serif fonts to label physical features.
Then, italics, for example, can be used to distinguish water areas.
The role of bold font faces, together with increased font size, is to highlight the hierarchy of labels -- larger, bold fonts indicate more prominent map features.
Additionally, customizing the fonts' colors can be helpful to distinguish different groups of map objects.
<!-- cite - https://www.axismaps.com/guide/labeling -->
The decision on which fonts to use should also relates to the expected map look and feel.
Each font family has a distinct personality (creates a "semantic effect"), which can affect how the map is perceived.
<!-- references - https://gistbok.ucgis.org/bok-topics/typography -->
Some fonts are more formal, some are less.
Some fonts have a modern look, while others look more traditional.
<!-- add examples -->
Another important concern is personal taste or map branding.
We should filter the decision about the used fonts based on our preferences or even our sense of beauty as it could create more personal and unique maps.
We just need to remember about the readability of the fonts -- they should not be too elaborate as it can hinder the main map message.
<!-- suggested fonts or references??? -->
#### Fonts available in **tmap** {#sec-fonts-tmap}
Before we discuss how to set a font family and its face, it is important to highlight that a different set of fonts could exist for each operating system (and even each computer).
Additionally, which fonts are available and how they are supported depends on the used *graphic device*.
A graphic device is a place where a plot or map is rendered.
The most commonly it is a some kind of a screen device, where we can see our plot or map directly after running the R code.
Other graphic devices allow for saving plots or maps as files in various formats (e.g., `.png`, `.jpg`, `.pdf`).
Therefore, it is possible to get different fonts on your map on the screen, and a (slightly) different one when saved to a file.
Visit `?Devices` or read the Graphic Devices chapter of @peng2016exploratory to learn more about graphic devices.
The **tmap** package has two mechanism to select a font family.
The first one is by specifying on of three general font families: `"serif"`, `"sans"`, or `"monospace"`.
It tries to match selected general font family with a font family existing on the operating system.
<!-- https://github.com/r-lib/systemfonts#system-defaults -->
For example, `"serif"` could the `"Times"` font family, `"sans"` -- `"Helvetica"` or `"Arial"`, and `"monospace"` -- `"Courier"` (@fig-fonts-1).
The second mechanism allows to select a font family based on its name (e.g., `"Times"` or `"Palatino"`).
Next, a member of the selected font families can be selected with one of the font faces: `"plain"`, `"italic"`, `"bold"`, and `"bold.italic"` (@fig-fonts-2).
<!-- build-in fonts only -->
As mentioned before, available fonts depend on the computer setup (including operating system) and used graphic device.
Fonts available on the operating system can be checked with the `system_fonts()` function of the **systemfonts** package [@R-systemfonts] (result not shown).
```{r}
#| eval: false
library(systemfonts)
system_fonts()
```
Information on installing and debugging custom fonts can be found in [a blog post](https://yjunechoe.github.io/posts/2021-06-24-setting-up-and-debugging-custom-fonts/) by June Choe and in the **showtext** package [@R-showtext] documentation.
The next step is to either view or save the map.
This also means that we need to carry over our fonts to the output window/file, which largely depends on the selected graphic device.
In general, screen device or graphical raster output formats, such as PNG, JPEG, or TIFF, works well with custom fonts as they rasterize them during saving.
In case of any problems with graphical raster outputs, it is possible to try alternative graphics devices implemented in the **ragg** package [@R-ragg].
On the other hand, graphical vector formats, such as PDF or SVG, could have some problems with saving maps containing custom fonts^[You can get the `invalid font type` error when saving the file.].
The PDF device in R, by default, adds metadata about the used fonts, but does not store them.
When the PDF reader shows the document, it tries to locate the font on your computer, and use other fonts when the expected one does not exist.
An alternative approach is called embedding, which adds a copy of each necessary font to the PDF file itself.
Gladly, the creation of a PDF with proper fonts can be achieved in a few ways.
Firstly, it could be worth trying some alternative graphic devices such as `cairo_pdf` or `svglite::svglite`.
The second option is to use the **showtext** package [@R-showtext], which converts text into color-filled polygonal outlines for graphical vector formats.
<!-- footnote: if/when the device argument is added to tmap_save, then mention saving to ragg/cairo_pdf -->
Thirdly, the **extrafont** [@R-extrafont] package allows embedding the fonts in the PDF file, which makes PDFs properly displayed on computers that do not have the given font.
<!-- ref to map_save!! -->
#### Fonts on maps {#sec-fonts-on-maps}
```{r}
#| message: false
library(tmap)
library(sf)
ei_borders = read_sf("data/easter_island/ei_border.gpkg")
ei_points = read_sf("data/easter_island/ei_points.gpkg")
volcanos = subset(ei_points, type == "volcano")
```
<!-- explain defaults -->
By default, **tmap** uses the `"sans"` font family with the `"plain"` font face (@fig-fonts).
There are, however, three ways to customize the used fonts.
The first one is to change all of the fonts and font faces for the whole map at once (@fig-mfonts-1).
This can be done with the `text.fontfamily` and `text.fontface` arguments of `tm_layout()`.
```{r}
#| label: font1
#| eval: false
tm_shape(ei_borders) +
tm_polygons() +
tm_shape(volcanos) +
tm_text(text = "name", size = "elevation") +
tm_credits("Data source: OSM") +
tm_title("Volcanos of Easter Island") +
tm_layout(text.fontface = "italic",
text.fontfamily = "serif")
```
The second way is to specify just some text elements independently (@fig-mfonts-2).
Many **tmap** functions, such as `tm_text()` or `tm_credits()`, have their own `fontfamily` and `fontface` arguments that can be adjusted.
Additionally, `tm_layout()` allows to customize fonts for other map elements using prefixed arguments, such as, `title.fontface` or `legend.title.fontfamily`.
```{r}
#| label: font2
#| eval: false
tm_shape(ei_borders) +
tm_polygons() +
tm_shape(volcanos) +
tm_text(text = "name", size = "elevation", fontfamily = "sans") +
tm_credits("Data source: OSM", fontface = "bold") +
tm_title("Volcanos of Easter Island") +
tm_layout(title.fontface = "bold.italic",
legend.title.fontfamily = "monospace")
```
```{r}
#| label: fig-mfonts
#| echo: false
#| layout-ncol: 2
#| fig-cap: Examples of one font (font family and font face) used for all of the
#| map elements (title, text labels, legend, and text annotation), and different
#| fonts used for different map elements.
#| fig-subcap:
#| - One font for all elements
#| - Different fonts for different elements
tm_shape(ei_borders) +
tm_polygons() +
tm_shape(volcanos) +
tm_text(text = "name", size = "elevation") +
tm_credits("Data source: OSM") +
tm_title("Volcanos of Easter Island") +
tm_layout(text.fontface = "italic",
text.fontfamily = "serif")
tm_shape(ei_borders) +
tm_polygons() +
tm_shape(volcanos) +
tm_text(text = "name", size = "elevation", fontfamily = "sans") +
tm_credits("Data source: OSM", fontface = "bold") +
tm_title("Volcanos of Easter Island") +
tm_title_in("B") +
tm_layout(title.fontface = "bold.italic",
legend.title.fontfamily = "monospace")
```
<!-- The third way is to use a different *tmap style* - see section \@ref() for more details. -->
```{r}
#| eval: false
#| echo: false
#saving tests
tmap_save(tmt2, "tmt2.png")
tmap_save(tmt2, "tmt2.pdf")
```
<!-- ## Legend {#sec-llegend} -->