Visualization
Configure the Radar and other data visualizations
Overview
Visualizations are interactive data displays configured in the settings.visualization array. Currently, the Radar visualization is the primary supported type.
import type { Config, Visualizations } from "@envisioning/app";
const Radar: Visualizations["radar"] = {
type: "radar",
label: { en: "Radar" },
entityPageId: "technology",
distance: [{ joinKey: "trl" }],
group: [{ joinKey: "collection" }],
};
const settings: Config["settings"] = {
visualization: [Radar],
// ...
};Radar Visualization
The Radar displays entities as dots arranged in a circular layout with configurable dimensions.
Core Properties
| Property | Type | Required | Description |
|---|---|---|---|
type | "radar" | Yes | Visualization type |
label | I18n | Yes | Display label |
entityPageId | string | Yes | Target page for entity clicks |
distance | array | Yes | Radial position metric(s) |
group | array | No | Slice grouping metric(s) |
bubble | array | No | Bubble size metric(s) |
bar | array | No | Bar chart metric(s) |
connections | array | No | Connection line metric(s) |
sort | array | No | Sort options for entities |
settings | object | No | Visual appearance settings |
preferences | object | No | User preference toggles |
Metric Dimensions
Each dimension (distance, group, bubble, bar, connections) accepts an array of metric configurations:
{
distance: [
{
label: { en: "TRL" },
joinKey: "trl",
scale: { type: "linear" },
ticksStep: 1,
},
],
}Dimension Properties
| Property | Type | Description |
|---|---|---|
label | I18n | Optional override label |
joinKey | string | Schema join key for the metric |
scale | object | D3 scale configuration |
ticksStep | number | Step for tick rendering |
isInwards | boolean | When true, higher values map toward the center; when false, toward the edge (default true) |
tickMargin | number | Symmetric padding before min and after max as tickMargin * ticksStep (0–1, default 0.5). Direction respects the distance option's isInwards. |
addClosingRing | boolean | Render closing ring at scale boundary on closing side (default true). When false, renders a ring at the metric domain boundary instead (if not already a tick). Does not affect scale range. |
offset | number | Label displacement along tick band as a multiple of band width (-1 = outer edge, 0 = on tick value, 1 = toward center; range -1–1). Default 0. Direction respects the distance option's isInwards. |
showOption | boolean | Show in secondary menu (default: true) |
forceDomain | [number, number] | Override metric domain |
overrideSettings | object | Distance only. Optional per-distance overrides for entity, range, and bubble rendering (see below) |
overrideSettings (distance only)
Optional object on a distance option. When that distance scale is active, any set keys override the chart-level settings for entity rendering only. The object and each key inside it are optional; unset keys fall back to chart settings.
| Key | Type | Description |
|---|---|---|
hitRadius | number | Dot and range hit area radius |
dotRadius | number | Entity dot radius |
dotPadding | number | Padding around dot for current/hover ring |
rangeStrokeWidth | number | Range line stroke width (min 0) |
rangeOpacity | number | Range line opacity (0–1) |
forceRangeColor | string | false | Range line color (false = follow dot color; or token, hex, template) |
maxBubbleRadius | number | Maximum bubble radius |
bubbleOpacity | number | Bubble fill opacity |
distance: [
{ label: { en: "TRL" }, joinKey: "trl", ticksStep: 1 },
{
label: { en: "Cost" },
joinKey: "cost",
ticksStep: 1,
overrideSettings: {
dotRadius: 2,
rangeStrokeWidth: 10,
},
},
],Scale Types
// Linear scale (default)
scale: { type: "linear" }
// Symmetric log scale (supports zero)
scale: { type: "symlog", constant: 1 }
// Power scale
scale: { type: "pow", exponent: 2 }
// Square root scale
scale: { type: "sqrt" }Distance (Radial Position)
Controls where entities appear from center to edge:
distance: [
{
label: { en: "NDC Impact Fit" },
joinKey: "ndcImpact",
ticksStep: 1,
},
{
label: { en: "TRL" },
joinKey: "trl",
ticksStep: 1,
},
],Group (Slices)
Divides the radar into pie-like slices:
group: [
{
label: { en: "Collection" },
joinKey: "collection",
},
{
label: { en: "TRL" },
joinKey: "trl",
},
{
label: { en: "None" },
joinKey: "", // Empty string = no grouping
},
],Bubble (Size)
Controls entity dot size:
bubble: [
{
label: { en: "Funding Opportunities" },
joinKey: "fundingOpportunities",
},
{
label: { en: "Cost" },
joinKey: "cost",
},
],Bar (Bar Charts)
Adds bar chart display for metrics:
bar: [
{
label: { en: "TRL" },
joinKey: "trl",
ticksStep: 1,
},
{
label: { en: "Cost" },
joinKey: "cost",
},
],Sort Options
Define how entities can be sorted:
sort: [
{
label: { en: "Title" },
ascCriteria: { title: 1 },
},
{
label: { en: "TRL" },
ascCriteria: { "trl.value": 1 },
descCriteria: null, // null = hide asc/desc toggle
},
],Preferences
Configure user-toggleable features:
preferences: {
magneticTitles: {
default: true,
showOption: true,
label: { en: "Magnetic Titles" },
},
showTail: {
default: true,
},
showNumber: {
default: true,
},
showBubble: {
default: true,
},
showBar: {
default: true,
},
showOrigin: {
default: true,
},
showConnections: {
default: true,
showOption: false, // Hide from preferences menu
},
},| Preference | Description |
|---|---|
magneticTitles | Labels follow cursor |
showTail | Show connecting lines to dots |
showNumber | Show entity numbers |
showBubble | Show bubble size |
showBar | Show bar charts |
showOrigin | Show origin point |
showConnections | Show connection lines |
Visual Settings
Fine-tune radar appearance:
settings: {
// Layout
innerRadius: 150,
outerRadius: 400,
outerPadding: 50,
sliceGap: 0.02,
// Badge (center logo)
badgeSize: 180,
// Dots
dotRadius: 6,
hitRadius: 10,
// Labels
titleSize: 16,
titlePadding: 10,
hoverPadding: 5,
// Ticks
tickLabelSize: 12,
tickLabelWeight: 400,
tickStrokeWidth: 1,
// Numbers
numberPadding: 5,
numberWeight: 500,
// Bubbles
maxBubbleRadius: 30,
bubbleOpacity: 0.5,
// Bars
barSize: 20,
barPadding: 2,
barStrokeWidth: 1,
// Tails
tailGap: 2,
tailOpacity: 0.5,
tailStrokeWidth: 2,
},Complete Example
import type { Visualizations } from "@envisioning/app";
export const Radar: Visualizations["radar"] = {
type: "radar",
label: { en: "Radar" },
entityPageId: "technology",
sort: [
{ label: { en: "Title" }, ascCriteria: { title: 1 } },
{ label: { en: "TRL" }, ascCriteria: { "trl.value": 1 } },
{ label: { en: "Cost" }, ascCriteria: { "cost.value": 1 } },
],
group: [
{ label: { en: "Collection" }, joinKey: "collection" },
{ label: { en: "TRL" }, joinKey: "trl" },
{ label: { en: "None" }, joinKey: "" },
],
distance: [
{ label: { en: "NDC Impact" }, joinKey: "ndcImpact", ticksStep: 1 },
{ label: { en: "TRL" }, joinKey: "trl", ticksStep: 1 },
],
bubble: [
{ label: { en: "Funding" }, joinKey: "fundingOpportunities" },
{ label: { en: "Cost" }, joinKey: "cost" },
],
bar: [
{ label: { en: "TRL" }, joinKey: "trl", ticksStep: 1 },
{ label: { en: "Cost" }, joinKey: "cost" },
],
preferences: {
magneticTitles: { default: true },
showTail: { default: true },
showNumber: { default: true },
showBubble: { default: true },
showBar: { default: true },
showOrigin: { default: true },
showConnections: { default: true, showOption: false },
},
settings: {
innerRadius: 150,
outerRadius: 400,
badgeSize: 180,
titleSize: 16,
dotRadius: 6,
tailStrokeWidth: 2,
maxBubbleRadius: 30,
tickLabelSize: 12,
outerPadding: 50,
},
};Validation
The configuration validates that:
entityPageIdexists in the pages array- All
joinKeyvalues exist in the schema joins
If validation fails:
Page "technology" not found in pages. Check visualization: radar
Join key "trl" not found in the schema. Check: radar - distance, joinKey: trl