Текстовые элементы играют ключевую роль в визуализации данных: заголовки, подписи осей, аннотации, метки значений, легенды и интерактивные подсказки формируют читаемость графика и влияют на восприятие информации. В экосистеме Vega и Vega-Lite текст представлен как полноценный графический примитив, обладающий собственными свойствами позиционирования, форматирования и поведения.
В Vega-Lite текст чаще всего используется через
mark: "text".
const spec = {
data: {
values: [
{ category: "A", value: 28 },
{ category: "B", value: 55 },
{ category: "C", value: 43 }
]
},
mark: "text",
encoding: {
x: { field: "category", type: "nominal" },
y: { field: "value", type: "quantitative" },
text: { field: "value" }
}
};
В данном примере:
x определяет горизонтальное положение;y — вертикальное;text выводит содержимое текстовой метки.mark: {
type: "text",
fontSize: 24
}
mark: {
type: "text",
color: "darkred"
}
mark: {
type: "text",
font: "Arial"
}
mark: {
type: "text",
fontWeight: "bold"
}
Допустимые значения:
"normal""bold"100, 200,
400, 700Текстовые элементы можно выравнивать относительно координаты.
mark: {
type: "text",
align: "center"
}
Варианты:
"left""center""right"mark: {
type: "text",
baseline: "middle"
}
Варианты:
"top""middle""bottom""alphabetic"Часто текст необходимо немного сдвинуть относительно точки.
mark: {
type: "text",
dx: 10
}
mark: {
type: "text",
dy: -10
}
mark: {
type: "text",
angle: -45
}
Полезно для:
Одна из наиболее распространённых задач — отображение числовых значений поверх баров.
const spec = {
data: {
values: [
{ month: "Jan", sales: 120 },
{ month: "Feb", sales: 98 },
{ month: "Mar", sales: 143 }
]
},
layer: [
{
mark: "bar",
encoding: {
x: { field: "month", type: "ordinal" },
y: { field: "sales", type: "quantitative" }
}
},
{
mark: {
type: "text",
dy: -10,
color: "black"
},
encoding: {
x: { field: "month", type: "ordinal" },
y: { field: "sales", type: "quantitative" },
text: { field: "sales" }
}
}
]
};
Используется механизм layer, позволяющий накладывать
несколько визуальных слоёв.
Текстовые значения могут автоматически форматироваться.
formattext: {
field: "price",
format: "$.2f"
}
Результат:
$12.45
text: {
field: "ratio",
format: ".1%"
}
Результат:
45.3%
text: {
field: "date",
type: "temporal",
format: "%d.%m.%Y"
}
Популярные спецификаторы:
| Формат | Описание |
|---|---|
%Y |
год |
%m |
месяц |
%d |
день |
%H |
часы |
%M |
минуты |
Vega-Lite поддерживает условные выражения.
color: {
condition: {
test: "datum.value > 50",
value: "green"
},
value: "red"
}
text: {
condition: {
test: "datum.value > 100",
value: "High"
},
value: "Low"
}
Через calculate можно создавать динамические
подписи.
transform: [
{
calculate: "datum.sales + ' units'",
as: "label"
}
]
Далее:
text: {
field: "label"
}
calculate: "'Line 1\\nLine 2'"
limitmark: {
type: "text",
limit: 100
}
Текст автоматически обрезается при превышении ширины.
mark: {
type: "text",
ellipsis: "..."
}
Текст может реагировать на наведение и события.
encoding: {
size: {
condition: {
param: "hover",
value: 20
},
value: 12
}
}
params: [
{
name: "hover",
select: {
type: "point",
on: "mouseover"
}
}
]
Текстовые элементы часто комбинируются с всплывающими подсказками.
encoding: {
tooltip: [
{ field: "name" },
{ field: "value" }
]
}
В Vega текст задаётся через объект marks.
{
"type": "text",
"encode": {
"enter": {
"x": { "value": 100 },
"y": { "value": 50 },
"text": {
"value": "Hello Vega"
},
"fontSize": {
"value": 24
}
}
}
}
В Vega состояние элемента разделяется на несколько фаз.
| Секция | Назначение |
|---|---|
enter |
начальное состояние |
update |
обновление |
hover |
состояние наведения |
exit |
удаление |
"text": {
"signal": "datum.value"
}
Сигналы (signals) позволяют динамически вычислять
значения.
signals: [
{
name: "fontSize",
value: 18
}
]
fontSize: {
signal: "fontSize"
}
Vega поддерживает реактивное обновление текста через сигналы.
signals: [
{
name: "label",
value: "Start",
on: [
{
events: "click",
update: "'Clicked'"
}
]
}
]
from: {
data: "table"
}
text: {
field: "name"
}
{
type: "text",
from: {
data: "table"
},
encode: {
enter: {
x: { field: "x" },
y: { field: "y" },
text: {
field: "label"
}
}
}
}
Текстовые метки активно используются для пояснений на графике.
{
type: "text",
encode: {
enter: {
x: { value: 300 },
y: { value: 100 },
text: {
value: "Peak value"
},
fill: {
value: "red"
}
}
}
}
Аннотации часто состоят из линии и подписи.
layer: [
{
mark: "rule"
},
{
mark: "text"
}
]
mark: {
type: "text",
opacity: 0.5
}
mark: {
type: "text",
cursor: "pointer"
}
mark: {
type: "text",
clip: true
}
Vega корректно работает с Unicode-символами.
text: {
value: "Пример текста"
}
Поддерживаются:
Текстовые элементы являются дорогими для рендеринга, особенно в SVG.
limit.Преимущества:
Недостатки:
Преимущества:
Недостатки:
vegaEmbed("#view", spec, {
renderer: "canvas"
});
Подписи осей автоматически генерируются системой шкал.
axis: {
labelAngle: -45
}
axis: {
labelFontSize: 14
}
title: {
text: "Sales by Month",
fontSize: 24,
color: "darkblue"
}
title: {
text: "Main Title",
subtitle: "Subtitle"
}
legend: {
labelFontSize: 12,
titleFontSize: 14
}
calculate: "datum.name + ': ' + datum.value"
calculate: "format(datum.value, '.2f')"
В текстовых вычислениях часто используются expression functions.
calculate: "upper(datum.category)"
| Функция | Назначение |
|---|---|
upper() |
верхний регистр |
lower() |
нижний регистр |
substring() |
подстрока |
length() |
длина строки |
format() |
форматирование |
fontSize: {
signal: "width / 30"
}
opacity: {
signal: "datum.value > 10 ? 1 : 0"
}
layer: [
{
mark: "rect"
},
{
mark: {
type: "text",
color: "white"
}
}
]
mark: {
type: "text",
dx: 8
}
Размер текста может зависеть от данных.
encoding: {
size: {
field: "population"
}
}
Проблема наложения текста является одной из главных в визуализации.
transform: [
{
window: [
{
op: "rank",
as: "rank"
}
]
}
]
Можно выводить только топ-N элементов.
Текст улучшает доступность визуализации:
const spec = {
data: {
values: [
{ category: "A", value: 40 },
{ category: "B", value: 25 },
{ category: "C", value: 35 }
]
},
layer: [
{
mark: {
type: "arc",
outerRadius: 120
},
encoding: {
theta: {
field: "value",
type: "quantitative"
},
color: {
field: "category",
type: "nominal"
}
}
},
{
mark: {
type: "text",
radius: 140
},
encoding: {
theta: {
field: "value",
type: "quantitative"
},
text: {
field: "category"
}
}
}
]
};
const spec = {
params: [
{
name: "hover",
select: {
type: "point",
on: "mouseover"
}
}
],
mark: "text",
encoding: {
x: { field: "x", type: "quantitative" },
y: { field: "y", type: "quantitative" },
text: { field: "label" },
color: {
condition: {
param: "hover",
value: "red"
},
value: "black"
}
}
};