rect

Элемент rect используется для построения прямоугольников и лежит в основе огромного количества визуализаций:

  • тепловых карт;
  • календарных диаграмм;
  • матриц корреляции;
  • stacked bar chart;
  • waterfall chart;
  • interval-графиков;
  • фоновых областей;
  • Gantt-подобных диаграмм;
  • двумерных распределений.

В Vega-Lite прямоугольники описываются через "mark": "rect", а в низкоуровневой Vega — через mark-тип "rect" с набором координат и свойств.


Базовая структура rect в Vega-Lite

Минимальная спецификация:

{
  "data": {
    "values": [
      {"x1": 0, "x2": 100, "y1": 0, "y2": 50}
    ]
  },
  "mark": "rect",
  "encoding": {
    "x": {"field": "x1", "type": "quantitative"},
    "x2": {"field": "x2"},
    "y": {"field": "y1", "type": "quantitative"},
    "y2": {"field": "y2"}
  }
}

Прямоугольник определяется четырьмя границами:

Канал Назначение
x левая граница
x2 правая граница
y верхняя граница
y2 нижняя граница

Координатные каналы

x и x2

Каналы задают горизонтальный диапазон.

"x": {"field": "start"},
"x2": {"field": "end"}

Если x2 отсутствует, Vega-Lite вычисляет ширину автоматически на основе бэндинга шкалы.

Пример категориального rect:

{
  "mark": "rect",
  "encoding": {
    "x": {
      "field": "category",
      "type": "ordinal"
    }
  }
}

В этом случае ширина прямоугольника определяется шириной полосы (band).


y и y2

Аналогично работают вертикальные границы.

"y": {"field": "low"},
"y2": {"field": "high"}

Часто используются для interval-графиков:

{
  "data": {
    "values": [
      {"day": "Mon", "min": 12, "max": 20}
    ]
  },
  "mark": "rect",
  "encoding": {
    "x": {"field": "day", "type": "ordinal"},
    "y": {"field": "min", "type": "quantitative"},
    "y2": {"field": "max"}
  }
}

Rect как heatmap

Наиболее распространённое применение — тепловые карты.

{
  "data": {
    "values": [
      {"hour": 1, "day": "Mon", "value": 12},
      {"hour": 2, "day": "Mon", "value": 18},
      {"hour": 1, "day": "Tue", "value": 22}
    ]
  },
  "mark": "rect",
  "encoding": {
    "x": {
      "field": "hour",
      "type": "ordinal"
    },
    "y": {
      "field": "day",
      "type": "ordinal"
    },
    "color": {
      "field": "value",
      "type": "quantitative"
    }
  }
}

Каждая комбинация x/y превращается в ячейку.


Размеры прямоугольников

width и height

Можно задавать фиксированные размеры:

{
  "mark": {
    "type": "rect",
    "width": 40,
    "height": 20
  }
}

Однако чаще размеры вычисляются автоматически через шкалы.


band

Для категориальных шкал используется параметр band.

"x": {
  "field": "month",
  "type": "ordinal",
  "band": 0.8
}

Значение:

Значение Эффект
1 полная ширина ячейки
0.5 половина ширины
0 нулевая ширина

Цвет прямоугольников

color

Основной канал окраски:

"color": {
  "field": "temperature",
  "type": "quantitative"
}

fill

Явное указание цвета:

{
  "mark": {
    "type": "rect",
    "fill": "steelblue"
  }
}

stroke

Контур прямоугольника:

{
  "mark": {
    "type": "rect",
    "stroke": "black",
    "strokeWidth": 2
  }
}

Скругление углов

cornerRadius

{
  "mark": {
    "type": "rect",
    "cornerRadius": 6
  }
}

Индивидуальные радиусы

{
  "mark": {
    "type": "rect",
    "cornerRadiusTopLeft": 10,
    "cornerRadiusTopRight": 10
  }
}

Поддерживаются:

  • cornerRadiusTopLeft
  • cornerRadiusTopRight
  • cornerRadiusBottomLeft
  • cornerRadiusBottomRight

Прозрачность

opacity

{
  "mark": {
    "type": "rect",
    "opacity": 0.5
  }
}

fillOpacity

Прозрачность только заливки:

{
  "mark": {
    "type": "rect",
    "fillOpacity": 0.3
  }
}

strokeOpacity

Прозрачность контура:

{
  "mark": {
    "type": "rect",
    "strokeOpacity": 0.7
  }
}

Rect и биннинг

Rect идеально сочетается с bin.

Двумерный histogram heatmap

{
  "data": {
    "url": "data/cars.json"
  },
  "mark": "rect",
  "encoding": {
    "x": {
      "bin": true,
      "field": "Horsepower",
      "type": "quantitative"
    },
    "y": {
      "bin": true,
      "field": "Miles_per_Gallon",
      "type": "quantitative"
    },
    "color": {
      "aggregate": "count",
      "type": "quantitative"
    }
  }
}

Здесь rect отображает плотность распределения.


Layering с rect

Rect часто используется как фон.

Подсветка области

{
  "layer": [
    {
      "mark": {
        "type": "rect",
        "color": "#eeeeee"
      },
      "encoding": {
        "x": {"datum": 10},
        "x2": {"datum": 20}
      }
    },
    {
      "mark": "line",
      "encoding": {
        "x": {"field": "x"},
        "y": {"field": "y"}
      }
    }
  ]
}

Прямоугольник создаёт shaded region.


Условная окраска

condition

{
  "mark": "rect",
  "encoding": {
    "color": {
      "condition": {
        "test": "datum.value > 50",
        "value": "red"
      },
      "value": "green"
    }
  }
}

Rect в Vega

В Vega rect работает более низкоуровнево.

Базовый rect mark

{
  "type": "rect",
  "encode": {
    "enter": {
      "x": {"value": 10},
      "y": {"value": 20},
      "width": {"value": 100},
      "height": {"value": 40},
      "fill": {"value": "steelblue"}
    }
  }
}

enter/update/hover

В Vega можно анимировать и менять состояния.

{
  "type": "rect",
  "encode": {
    "enter": {
      "fill": {"value": "gray"}
    },
    "hover": {
      "fill": {"value": "orange"}
    }
  }
}

Сигналы и rect

Rect может управляться через signals.

{
  "signals": [
    {
      "name": "boxWidth",
      "value": 100
    }
  ],
  "marks": [
    {
      "type": "rect",
      "encode": {
        "update": {
          "width": {"signal": "boxWidth"}
        }
      }
    }
  ]
}

Rect как background layer

Фон всей визуализации

{
  "marks": [
    {
      "type": "rect",
      "encode": {
        "enter": {
          "x": {"value": 0},
          "y": {"value": 0},
          "width": {"signal": "width"},
          "height": {"signal": "height"},
          "fill": {"value": "#fafafa"}
        }
      }
    }
  ]
}

Heatmap с текстом

Rect часто комбинируется с text.

{
  "layer": [
    {
      "mark": "rect",
      "encoding": {
        "x": {"field": "x"},
        "y": {"field": "y"},
        "color": {"field": "value"}
      }
    },
    {
      "mark": "text",
      "encoding": {
        "x": {"field": "x"},
        "y": {"field": "y"},
        "text": {"field": "value"}
      }
    }
  ]
}

Rect и временные интервалы

Rect удобно использовать для временных диапазонов.

Timeline blocks

{
  "data": {
    "values": [
      {
        "task": "Design",
        "start": "2025-01-01",
        "end": "2025-01-10"
      }
    ]
  },
  "mark": "rect",
  "encoding": {
    "x": {
      "field": "start",
      "type": "temporal"
    },
    "x2": {
      "field": "end"
    },
    "y": {
      "field": "task",
      "type": "ordinal"
    }
  }
}

Tooltip

Базовый tooltip

{
  "mark": "rect",
  "encoding": {
    "tooltip": [
      {"field": "value"},
      {"field": "category"}
    ]
  }
}

Интерактивность

Selection

{
  "params": [
    {
      "name": "selectRect",
      "select": "point"
    }
  ],
  "mark": "rect",
  "encoding": {
    "opacity": {
      "condition": {
        "param": "selectRect",
        "value": 1
      },
      "value": 0.3
    }
  }
}

Производительность

Rect считается одним из самых дешёвых mark-типов:

  • рендерится быстрее path;
  • эффективен в Canvas renderer;
  • хорошо масштабируется;
  • подходит для десятков тысяч элементов.

Однако heatmap с очень большим числом ячеек может создавать проблемы:

  • перегрузка DOM при SVG;
  • высокая стоимость tooltip;
  • дорогостоящие transitions.

Для крупных datasets рекомендуется:

"config": {
  "render": "canvas"
}

Rect и scale padding

Padding влияет на расстояния между прямоугольниками.

"x": {
  "field": "category",
  "type": "ordinal",
  "scale": {
    "paddingInner": 0.1,
    "paddingOuter": 0.05
  }
}

Clip

Обрезка прямоугольников:

{
  "mark": {
    "type": "rect",
    "clip": true
  }
}

Элемент не выходит за пределы plotting area.


Blend modes

В Vega доступны режимы смешивания.

{
  "type": "rect",
  "blend": "multiply"
}

Популярные режимы:

  • multiply
  • screen
  • overlay
  • darken
  • lighten

Z-index

Управление порядком слоёв:

{
  "mark": {
    "type": "rect",
    "zindex": 10
  }
}

Cursor

Изменение курсора:

{
  "mark": {
    "type": "rect",
    "cursor": "pointer"
  }
}

ARIA и accessibility

{
  "mark": {
    "type": "rect",
    "aria": true
  }
}

Для accessibility желательно добавлять:

  • tooltip;
  • контрастные цвета;
  • текстовые подписи;
  • описательные title.

Конфигурация rect по умолчанию

config.rect

{
  "config": {
    "rect": {
      "cornerRadius": 4,
      "stroke": "white"
    }
  }
}

Все rect-mark автоматически получают эти параметры.


Отличия rect от bar

rect bar
произвольные границы привязан к baseline
подходит для heatmap ориентирован на bar charts
свободное позиционирование чаще categorical
x/x2/y/y2 x/y + size

Отличия rect от square

rect square
независимые width/height одинаковые стороны
произвольная форма квадрат
interval-графики scatter-like

Частые ошибки

Отсутствие x2/y2

"x": {"field": "a"}

Без x2 поведение зависит от типа шкалы.


Неправильный тип данных

"type": "nominal"

Для interval rect обычно нужен:

"type": "quantitative"

или:

"type": "temporal"

Перекрытие rect

При маленьком padding элементы могут сливаться.


Практические сценарии использования

Матрица корреляции

  • x — переменная;
  • y — переменная;
  • color — коэффициент корреляции.

Calendar heatmap

  • x — день недели;
  • y — неделя;
  • color — активность.

Gantt chart

  • x/x2 — время;
  • y — задача.

Density heatmap

  • binning по двум осям;
  • color как count.

Highlight regions

  • фоновые диапазоны;
  • зоны нормы;
  • интервалы событий.

Рекомендации по использованию

  • heatmap почти всегда строится через rect;
  • для interval visualization лучше использовать x/x2;
  • при больших объёмах данных предпочтителен Canvas renderer;
  • rect особенно эффективен в layered visualization;
  • rounded corners улучшают восприятие dashboard UI;
  • stroke полезен для separation в heatmap;
  • opacity помогает при наложении распределений.