0
# Scales & Projections
1
2
Vega's scale and projection system provides data encoding through scales that map data values to visual properties, color schemes for categorical and continuous data, and geographic projections for cartographic visualizations.
3
4
## Capabilities
5
6
### Scale System
7
8
Core scale creation and management for data encoding.
9
10
```typescript { .api }
11
/**
12
* Create or access a scale function
13
* @param type - Scale type identifier
14
* @param scale - Optional scale configuration object
15
* @returns Scale function or scale registry entry
16
*/
17
function scale(type: string, scale?: ScaleConfig): ScaleFunction | any;
18
19
/**
20
* Access color scheme by name
21
* @param name - Color scheme name
22
* @param scheme - Optional scheme definition to register
23
* @returns Color scheme array or registration result
24
*/
25
function scheme(name: string, scheme?: ColorScheme): string[] | any;
26
27
interface ScaleConfig {
28
/** Scale domain (input range) */
29
domain?: any[];
30
31
/** Scale range (output range) */
32
range?: any[];
33
34
/** Scale type-specific parameters */
35
[key: string]: any;
36
}
37
38
interface ScaleFunction {
39
/** Map domain value to range value */
40
(value: any): any;
41
42
/** Get or set the scale domain */
43
domain(): any[];
44
domain(domain: any[]): ScaleFunction;
45
46
/** Get or set the scale range */
47
range(): any[];
48
range(range: any[]): ScaleFunction;
49
50
/** Create inverted scale function */
51
invert?(value: any): any;
52
53
/** Get scale bandwidth (for band scales) */
54
bandwidth?(): number;
55
56
/** Get scale step (for band scales) */
57
step?(): number;
58
59
/** Copy the scale */
60
copy(): ScaleFunction;
61
}
62
63
type ColorScheme = string[] | { [key: string]: string[] };
64
```
65
66
### Scale Types
67
68
Built-in scale types for different data mappings.
69
70
```typescript { .api }
71
/** Linear scale for continuous numeric data */
72
type LinearScale = ScaleFunction & {
73
/** Get scale ticks */
74
ticks(count?: number): number[];
75
76
/** Get tick format function */
77
tickFormat(count?: number, specifier?: string): (value: number) => string;
78
79
/** Set interpolator function */
80
interpolate(interpolator: (a: any, b: any) => (t: number) => any): LinearScale;
81
82
/** Set clamping behavior */
83
clamp(clamp: boolean): LinearScale;
84
clamp(): boolean;
85
86
/** Set nice domain boundaries */
87
nice(count?: number): LinearScale;
88
};
89
90
/** Log scale for exponential data */
91
type LogScale = ScaleFunction & {
92
/** Set logarithm base */
93
base(base: number): LogScale;
94
base(): number;
95
96
/** Get scale ticks */
97
ticks(count?: number): number[];
98
99
/** Get tick format function */
100
tickFormat(count?: number, specifier?: string): (value: number) => string;
101
102
/** Set clamping behavior */
103
clamp(clamp: boolean): LogScale;
104
clamp(): boolean;
105
106
/** Set nice domain boundaries */
107
nice(): LogScale;
108
};
109
110
/** Power scale with configurable exponent */
111
type PowScale = ScaleFunction & {
112
/** Set power exponent */
113
exponent(exponent: number): PowScale;
114
exponent(): number;
115
116
/** Get scale ticks */
117
ticks(count?: number): number[];
118
119
/** Get tick format function */
120
tickFormat(count?: number, specifier?: string): (value: number) => string;
121
122
/** Set clamping behavior */
123
clamp(clamp: boolean): PowScale;
124
clamp(): boolean;
125
126
/** Set nice domain boundaries */
127
nice(count?: number): PowScale;
128
};
129
130
/** Square root scale (power scale with exponent 0.5) */
131
type SqrtScale = PowScale;
132
133
/** Symmetric log scale for data including zero */
134
type SymlogScale = ScaleFunction & {
135
/** Set linear threshold around zero */
136
constant(constant: number): SymlogScale;
137
constant(): number;
138
139
/** Get scale ticks */
140
ticks(count?: number): number[];
141
142
/** Get tick format function */
143
tickFormat(count?: number, specifier?: string): (value: number) => string;
144
145
/** Set clamping behavior */
146
clamp(clamp: boolean): SymlogScale;
147
clamp(): boolean;
148
149
/** Set nice domain boundaries */
150
nice(): SymlogScale;
151
};
152
153
/** Identity scale (passthrough) */
154
type IdentityScale = ScaleFunction;
155
156
/** Time scale for temporal data */
157
type TimeScale = ScaleFunction & {
158
/** Get scale ticks */
159
ticks(interval?: any): Date[];
160
161
/** Get tick format function */
162
tickFormat(count?: number, specifier?: string): (value: Date) => string;
163
164
/** Set clamping behavior */
165
clamp(clamp: boolean): TimeScale;
166
clamp(): boolean;
167
168
/** Set nice domain boundaries */
169
nice(interval?: any): TimeScale;
170
};
171
172
/** UTC time scale */
173
type UTCScale = TimeScale;
174
175
/** Sequential scale for continuous color mapping */
176
type SequentialScale = ScaleFunction & {
177
/** Set interpolator function */
178
interpolator(interpolator: (t: number) => any): SequentialScale;
179
interpolator(): (t: number) => any;
180
181
/** Set clamping behavior */
182
clamp(clamp: boolean): SequentialScale;
183
clamp(): boolean;
184
};
185
186
/** Diverging scale for data with meaningful center */
187
type DivergingScale = ScaleFunction & {
188
/** Set interpolator function */
189
interpolator(interpolator: (t: number) => any): DivergingScale;
190
interpolator(): (t: number) => any;
191
192
/** Set clamping behavior */
193
clamp(clamp: boolean): DivergingScale;
194
clamp(): boolean;
195
};
196
197
/** Quantile scale for statistical distributions */
198
type QuantileScale = ScaleFunction & {
199
/** Get quantiles array */
200
quantiles(): number[];
201
};
202
203
/** Quantize scale for uniform binning */
204
type QuantizeScale = ScaleFunction & {
205
/** Get thresholds array */
206
thresholds(): number[];
207
208
/** Set nice domain boundaries */
209
nice(count?: number): QuantizeScale;
210
};
211
212
/** Threshold scale for custom breakpoints */
213
type ThresholdScale = ScaleFunction & {
214
/** Set threshold values */
215
thresholds(thresholds: number[]): ThresholdScale;
216
thresholds(): number[];
217
};
218
219
/** Ordinal scale for categorical data */
220
type OrdinalScale = ScaleFunction & {
221
/** Get unknown value handler */
222
unknown(): any;
223
unknown(value: any): OrdinalScale;
224
};
225
226
/** Band scale for bar charts and similar */
227
type BandScale = ScaleFunction & {
228
/** Get bandwidth of each band */
229
bandwidth(): number;
230
231
/** Get step between band starts */
232
step(): number;
233
234
/** Set padding between bands */
235
padding(padding: number): BandScale;
236
padding(): number;
237
238
/** Set inner padding between bands */
239
paddingInner(padding: number): BandScale;
240
paddingInner(): number;
241
242
/** Set outer padding at scale edges */
243
paddingOuter(padding: number): BandScale;
244
paddingOuter(): number;
245
246
/** Set alignment of bands within range */
247
align(align: number): BandScale;
248
align(): number;
249
250
/** Round band positions to integers */
251
round(round: boolean): BandScale;
252
round(): boolean;
253
};
254
255
/** Point scale for scatterplots */
256
type PointScale = ScaleFunction & {
257
/** Get step between points */
258
step(): number;
259
260
/** Set padding at scale edges */
261
padding(padding: number): PointScale;
262
padding(): number;
263
264
/** Set alignment of points within range */
265
align(align: number): PointScale;
266
align(): number;
267
268
/** Round point positions to integers */
269
round(round: boolean): PointScale;
270
round(): boolean;
271
};
272
```
273
274
### Interpolation Functions
275
276
Value interpolation for continuous scales.
277
278
```typescript { .api }
279
/**
280
* Create interpolation function for continuous scales
281
* @param type - Interpolation type
282
* @param options - Interpolation options
283
* @returns Interpolation function
284
*/
285
function interpolate(type: string, options?: InterpolationOptions): (a: any, b: any) => (t: number) => any;
286
287
/**
288
* Color interpolation for color scales
289
* @param colors - Array of color values
290
* @param type - Interpolation type ('rgb', 'hsl', 'lab', etc.)
291
* @param options - Interpolation options
292
* @returns Color interpolation function
293
*/
294
function interpolateColors(colors: any[], type?: string, options?: InterpolationOptions): (t: number) => string;
295
296
/**
297
* Range interpolation for scale ranges
298
* @param range - Range values to interpolate
299
* @returns Range interpolation function
300
*/
301
function interpolateRange(range: any[]): (t: number) => any;
302
303
/**
304
* Create quantized interpolator
305
* @param interpolator - Base interpolation function
306
* @param count - Number of discrete steps
307
* @returns Quantized interpolation function
308
*/
309
function quantizeInterpolator(interpolator: (t: number) => any, count: number): (t: number) => any;
310
311
interface InterpolationOptions {
312
/** Color space for color interpolation */
313
colorSpace?: 'rgb' | 'hsl' | 'hcl' | 'lab' | 'cubehelix';
314
315
/** Gamma correction for color interpolation */
316
gamma?: number;
317
318
/** Use shorter hue path for hue interpolation */
319
hue?: 'shorter' | 'longer' | 'increasing' | 'decreasing';
320
}
321
```
322
323
### Scale Transformations
324
325
Scale manipulation utilities for panning and zooming.
326
327
```typescript { .api }
328
/**
329
* Pan linear scale by specified offset
330
* @param scale - Linear scale to pan
331
* @param offset - Pan offset amount
332
* @returns New panned scale
333
*/
334
function panLinear(scale: LinearScale, offset: number): LinearScale;
335
336
/**
337
* Pan logarithmic scale by specified offset
338
* @param scale - Log scale to pan
339
* @param offset - Pan offset amount
340
* @returns New panned scale
341
*/
342
function panLog(scale: LogScale, offset: number): LogScale;
343
344
/**
345
* Pan power scale by specified offset
346
* @param scale - Power scale to pan
347
* @param offset - Pan offset amount
348
* @returns New panned scale
349
*/
350
function panPow(scale: PowScale, offset: number): PowScale;
351
352
/**
353
* Pan symmetric log scale by specified offset
354
* @param scale - Symlog scale to pan
355
* @param offset - Pan offset amount
356
* @returns New panned scale
357
*/
358
function panSymlog(scale: SymlogScale, offset: number): SymlogScale;
359
360
/**
361
* Zoom linear scale by specified factor
362
* @param scale - Linear scale to zoom
363
* @param anchor - Zoom anchor point
364
* @param factor - Zoom factor (>1 zooms in, <1 zooms out)
365
* @returns New zoomed scale
366
*/
367
function zoomLinear(scale: LinearScale, anchor: number, factor: number): LinearScale;
368
369
/**
370
* Zoom logarithmic scale by specified factor
371
* @param scale - Log scale to zoom
372
* @param anchor - Zoom anchor point
373
* @param factor - Zoom factor
374
* @returns New zoomed scale
375
*/
376
function zoomLog(scale: LogScale, anchor: number, factor: number): LogScale;
377
378
/**
379
* Zoom power scale by specified factor
380
* @param scale - Power scale to zoom
381
* @param anchor - Zoom anchor point
382
* @param factor - Zoom factor
383
* @returns New zoomed scale
384
*/
385
function zoomPow(scale: PowScale, anchor: number, factor: number): PowScale;
386
387
/**
388
* Zoom symmetric log scale by specified factor
389
* @param scale - Symlog scale to zoom
390
* @param anchor - Zoom anchor point
391
* @param factor - Zoom factor
392
* @returns New zoomed scale
393
*/
394
function zoomSymlog(scale: SymlogScale, anchor: number, factor: number): SymlogScale;
395
```
396
397
### Geographic Projections
398
399
Geographic coordinate system transformations.
400
401
```typescript { .api }
402
/**
403
* Create or access a geographic projection
404
* @param type - Projection type identifier
405
* @param projection - Optional projection configuration
406
* @returns Projection function or projection registry entry
407
*/
408
function projection(type: string, projection?: ProjectionConfig): ProjectionFunction | any;
409
410
interface ProjectionConfig {
411
/** Projection center coordinates [longitude, latitude] */
412
center?: [number, number];
413
414
/** Projection rotation [yaw, pitch, roll] */
415
rotate?: [number, number, number?];
416
417
/** Projection scale factor */
418
scale?: number;
419
420
/** Projection translation offset [x, y] */
421
translate?: [number, number];
422
423
/** Clipping extent [[x0, y0], [x1, y1]] */
424
clipExtent?: [[number, number], [number, number]];
425
426
/** Clipping angle in degrees */
427
clipAngle?: number;
428
429
/** Precision for adaptive resampling */
430
precision?: number;
431
432
/** Projection-specific parameters */
433
[key: string]: any;
434
}
435
436
interface ProjectionFunction {
437
/** Project geographic coordinates to screen coordinates */
438
(coordinates: [number, number]): [number, number] | null;
439
440
/** Inverse projection from screen to geographic coordinates */
441
invert?(coordinates: [number, number]): [number, number] | null;
442
443
/** Get or set projection center */
444
center(): [number, number];
445
center(center: [number, number]): ProjectionFunction;
446
447
/** Get or set projection rotation */
448
rotate(): [number, number, number?];
449
rotate(angles: [number, number, number?]): ProjectionFunction;
450
451
/** Get or set projection scale */
452
scale(): number;
453
scale(scale: number): ProjectionFunction;
454
455
/** Get or set projection translation */
456
translate(): [number, number];
457
translate(translate: [number, number]): ProjectionFunction;
458
459
/** Get or set clipping extent */
460
clipExtent(): [[number, number], [number, number]] | null;
461
clipExtent(extent: [[number, number], [number, number]] | null): ProjectionFunction;
462
463
/** Get or set clipping angle */
464
clipAngle(): number | null;
465
clipAngle(angle: number | null): ProjectionFunction;
466
467
/** Get or set precision */
468
precision(): number;
469
precision(precision: number): ProjectionFunction;
470
471
/** Fit projection to geographic bounds */
472
fitExtent?(extent: [[number, number], [number, number]], object: any): ProjectionFunction;
473
474
/** Fit projection to geographic size */
475
fitSize?(size: [number, number], object: any): ProjectionFunction;
476
477
/** Copy the projection */
478
copy(): ProjectionFunction;
479
}
480
```
481
482
### Built-in Color Schemes
483
484
Predefined color schemes for data visualization.
485
486
```typescript { .api }
487
/** Categorical color schemes */
488
interface CategoricalSchemes {
489
/** 10-color categorical palette */
490
category10: string[];
491
492
/** 20-color categorical palette */
493
category20: string[];
494
495
/** 20b-color categorical palette */
496
category20b: string[];
497
498
/** 20c-color categorical palette */
499
category20c: string[];
500
501
/** Accent color scheme */
502
accent: string[];
503
504
/** Dark2 color scheme */
505
dark2: string[];
506
507
/** Paired color scheme */
508
paired: string[];
509
510
/** Pastel1 color scheme */
511
pastel1: string[];
512
513
/** Pastel2 color scheme */
514
pastel2: string[];
515
516
/** Set1 color scheme */
517
set1: string[];
518
519
/** Set2 color scheme */
520
set2: string[];
521
522
/** Set3 color scheme */
523
set3: string[];
524
525
/** Tableau10 color scheme */
526
tableau10: string[];
527
528
/** Tableau20 color scheme */
529
tableau20: string[];
530
}
531
532
/** Sequential color schemes */
533
interface SequentialSchemes {
534
/** Blues sequential scheme */
535
blues: string[];
536
537
/** Greens sequential scheme */
538
greens: string[];
539
540
/** Oranges sequential scheme */
541
oranges: string[];
542
543
/** Purples sequential scheme */
544
purples: string[];
545
546
/** Reds sequential scheme */
547
reds: string[];
548
549
/** Greys sequential scheme */
550
greys: string[];
551
552
/** Turbo perceptually uniform scheme */
553
turbo: string[];
554
555
/** Viridis perceptually uniform scheme */
556
viridis: string[];
557
558
/** Plasma perceptually uniform scheme */
559
plasma: string[];
560
561
/** Inferno perceptually uniform scheme */
562
inferno: string[];
563
564
/** Magma perceptually uniform scheme */
565
magma: string[];
566
567
/** Cividis colorblind-friendly scheme */
568
cividis: string[];
569
}
570
571
/** Diverging color schemes */
572
interface DivergingSchemes {
573
/** Blue-Red diverging scheme */
574
blueorange: string[];
575
576
/** Blue-White-Red diverging scheme */
577
bluewhitered: string[];
578
579
/** Brown-Blue-Green diverging scheme */
580
brownbluegreen: string[];
581
582
/** Purple-Green diverging scheme */
583
purplegreen: string[];
584
585
/** Purple-Orange diverging scheme */
586
purpleorange: string[];
587
588
/** Red-Blue diverging scheme */
589
redblue: string[];
590
591
/** Red-Grey diverging scheme */
592
redgrey: string[];
593
594
/** Red-Yellow-Blue diverging scheme */
595
redyellowblue: string[];
596
597
/** Red-Yellow-Green diverging scheme */
598
redyellowgreen: string[];
599
600
/** Spectral diverging scheme */
601
spectral: string[];
602
}
603
```
604
605
## Usage Examples
606
607
### Basic Scale Usage
608
609
```typescript
610
import { scale } from "vega";
611
612
// Create linear scale
613
const xScale = scale('linear')
614
.domain([0, 100])
615
.range([0, 400]);
616
617
console.log(xScale(50)); // 200
618
619
// Create ordinal scale
620
const colorScale = scale('ordinal')
621
.domain(['A', 'B', 'C'])
622
.range(['red', 'green', 'blue']);
623
624
console.log(colorScale('B')); // 'green'
625
```
626
627
### Time Scale
628
629
```typescript
630
import { scale } from "vega";
631
632
const timeScale = scale('time')
633
.domain([new Date('2023-01-01'), new Date('2023-12-31')])
634
.range([0, 500]);
635
636
// Map date to pixel position
637
const position = timeScale(new Date('2023-06-15'));
638
639
// Get nice tick values
640
const ticks = timeScale.ticks(5);
641
const tickFormat = timeScale.tickFormat(5, '%b');
642
```
643
644
### Band Scale for Bar Charts
645
646
```typescript
647
import { scale } from "vega";
648
649
const xScale = scale('band')
650
.domain(['Q1', 'Q2', 'Q3', 'Q4'])
651
.range([0, 400])
652
.padding(0.1);
653
654
// Get bar positions and widths
655
const barWidth = xScale.bandwidth();
656
const q2Position = xScale('Q2');
657
658
console.log(`Q2 bar at ${q2Position}, width ${barWidth}`);
659
```
660
661
### Color Schemes
662
663
```typescript
664
import { scheme, scale } from "vega";
665
666
// Use built-in color scheme
667
const colors = scheme('category10');
668
const colorScale = scale('ordinal')
669
.domain(['A', 'B', 'C'])
670
.range(colors);
671
672
// Sequential color scale
673
const seqColors = scheme('blues');
674
const heatmapScale = scale('sequential')
675
.domain([0, 100])
676
.range(seqColors);
677
```
678
679
### Custom Interpolation
680
681
```typescript
682
import { scale, interpolate, interpolateColors } from "vega";
683
684
// Custom color interpolation
685
const customColors = interpolateColors(['#ff0000', '#00ff00', '#0000ff'], 'lab');
686
687
const colorScale = scale('linear')
688
.domain([0, 100])
689
.range([0, 1])
690
.interpolate(() => customColors);
691
692
console.log(colorScale(50)); // Interpolated color
693
```
694
695
### Geographic Projections
696
697
```typescript
698
import { projection } from "vega";
699
700
// Create Mercator projection
701
const proj = projection('mercator')
702
.scale(1000)
703
.center([0, 0])
704
.translate([400, 300]);
705
706
// Project coordinates
707
const [x, y] = proj([-74, 40.7]); // NYC coordinates
708
console.log(`NYC at screen coordinates: ${x}, ${y}`);
709
710
// Inverse projection
711
const [lng, lat] = proj.invert([x, y]);
712
console.log(`Back to geo coordinates: ${lng}, ${lat}`);
713
```
714
715
### Scale Transformations
716
717
```typescript
718
import { scale, panLinear, zoomLinear } from "vega";
719
720
const baseScale = scale('linear')
721
.domain([0, 100])
722
.range([0, 500]);
723
724
// Pan the scale
725
const pannedScale = panLinear(baseScale, 50);
726
console.log(pannedScale.domain()); // [50, 150]
727
728
// Zoom the scale
729
const zoomedScale = zoomLinear(baseScale, 50, 2);
730
console.log(zoomedScale.domain()); // [25, 75]
731
```
732
733
### Quantile Scale
734
735
```typescript
736
import { scale } from "vega";
737
738
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
739
740
const quantileScale = scale('quantile')
741
.domain(data)
742
.range(['low', 'medium', 'high']);
743
744
console.log(quantileScale(3)); // 'low'
745
console.log(quantileScale(7)); // 'medium'
746
console.log(quantileScale(9)); // 'high'
747
748
// Get quantile boundaries
749
const quantiles = quantileScale.quantiles();
750
console.log(quantiles); // [3.25, 6.75]
751
```
752
753
### Threshold Scale
754
755
```typescript
756
import { scale } from "vega";
757
758
const thresholdScale = scale('threshold')
759
.domain([0, 50, 100])
760
.range(['low', 'medium', 'high', 'very high']);
761
762
console.log(thresholdScale(-10)); // 'low'
763
console.log(thresholdScale(25)); // 'low'
764
console.log(thresholdScale(75)); // 'medium'
765
console.log(thresholdScale(150)); // 'very high'
766
```
767
768
### Complex Projection Setup
769
770
```typescript
771
import { projection } from "vega";
772
773
// Albers projection for US maps
774
const usProjection = projection('albers')
775
.rotate([96, 0])
776
.center([-0.6, 38.7])
777
.parallels([29.5, 45.5])
778
.scale(1000)
779
.translate([400, 250]);
780
781
// Fit projection to bounding box
782
const bounds = {
783
type: "FeatureCollection",
784
features: [/* GeoJSON features */]
785
};
786
787
usProjection.fitSize([800, 500], bounds);
788
```