Advanced styling capabilities for path-based and fill-based layers, including dash patterns, path offsets, and texture-based pattern fills for enhanced visual representation.
import { PathStyleExtension, FillStyleExtension } from "@deck.gl/extensions";
import type {
PathStyleExtensionProps,
PathStyleExtensionOptions,
FillStyleExtensionProps,
FillStyleExtensionOptions,
FillStyleModuleProps
} from "@deck.gl/extensions";Adds dash and offset capabilities to PathLayer and composite layers that render paths, enabling advanced line styling and positioning.
/**
* Adds selected features to the PathLayer and composite layers that render the PathLayer
* Provides dash and offset capabilities for advanced path styling
*/
class PathStyleExtension extends LayerExtension<PathStyleExtensionOptions> {
static extensionName: 'PathStyleExtension';
static defaultProps: PathStyleExtensionDefaultProps;
constructor(options?: Partial<PathStyleExtensionOptions>);
isEnabled(layer: Layer): boolean;
getShaders(extension: this): any;
initializeState(context: LayerContext, extension: this): void;
updateState(params: UpdateParameters, extension: this): void;
getDashOffsets(path: number[] | number[][]): number[];
}
interface PathStyleExtensionProps<DataT = any> {
/**
* Accessor for dash array [dashSize, gapSize] for each path.
* Only effective if dash option is enabled.
* @default {type: 'accessor', value: [0, 0]}
*/
getDashArray?: Accessor<DataT, [number, number]>;
/**
* Accessor for path offset (perpendicular to path direction) for each path.
* Positive values offset to the right, negative to the left.
* Only effective if offset option is enabled.
* @default {type: 'accessor', value: 0}
*/
getOffset?: Accessor<DataT, number>;
/**
* If true, adjust dash pattern to align with path length.
* Ensures dashes start and end at path endpoints.
* @default false
*/
dashJustified?: boolean;
/**
* If true, gaps in dash patterns are pickable (respond to mouse events).
* If false, only the dash segments are pickable.
* @default false
*/
dashGapPickable?: boolean;
}
interface PathStyleExtensionOptions {
/**
* Enable dash pattern functionality.
* @default false
*/
dash: boolean;
/**
* Enable path offset functionality.
* @default false
*/
offset: boolean;
/**
* Use high-precision dash calculations for very long paths.
* @default false
*/
highPrecisionDash: boolean;
}
interface PathStyleExtensionDefaultProps {
getDashArray: {type: 'accessor', value: [0, 0]};
getOffset: {type: 'accessor', value: 0};
dashJustified: false;
dashGapPickable: false;
}Adds pattern fill capabilities to layers that render fills, such as PolygonLayer and ScatterplotLayer, enabling texture-based pattern rendering.
/**
* Adds selected features to layers that render a "fill"
* Provides pattern filling capability using texture atlases
*/
class FillStyleExtension extends LayerExtension<FillStyleExtensionOptions> {
static extensionName: 'FillStyleExtension';
static defaultProps: FillStyleExtensionDefaultProps;
constructor(options?: Partial<FillStyleExtensionOptions>);
isEnabled(layer: Layer): boolean;
getShaders(extension: this): any;
initializeState(context: LayerContext, extension: this): void;
updateState(params: UpdateParameters, extension: this): void;
draw(params: any, extension: this): void;
finalizeState(): void;
getPatternFrame(name: string): number[];
}
interface FillStyleExtensionProps<DataT = any> {
/**
* Enable/disable pattern fill functionality.
* @default true
*/
fillPatternEnabled?: boolean;
/**
* Texture atlas containing pattern images.
* Can be a URL string or texture source object.
*/
fillPatternAtlas?: string | TextureSource;
/**
* Mapping of pattern names to their positions in the atlas.
* Can be a URL to JSON mapping or mapping object.
*/
fillPatternMapping?: string | Record<string, PatternFrame>;
/**
* If true, pattern acts as a mask (shows through base color).
* If false, pattern replaces the base color entirely.
* @default true
*/
fillPatternMask?: boolean;
/**
* Accessor to retrieve pattern name for each object.
* @default d => d.pattern
*/
getFillPattern?: AccessorFunction<DataT, string>;
/**
* Accessor for pattern scale factor for each object.
* @default {type: 'accessor', value: 1}
*/
getFillPatternScale?: Accessor<DataT, number>;
/**
* Accessor for pattern offset [x, y] for each object.
* @default {type: 'accessor', value: [0, 0]}
*/
getFillPatternOffset?: Accessor<DataT, [number, number]>;
}
interface FillStyleExtensionOptions {
/**
* Enable pattern fill functionality.
* @default false
*/
pattern: boolean;
}
interface FillStyleExtensionDefaultProps {
fillPatternEnabled: true;
fillPatternAtlas: {type: 'image', value: null, async: true, parameters: {lodMaxClamp: 0}};
fillPatternMapping: {type: 'object', value: {}, async: true};
fillPatternMask: true;
getFillPattern: {type: 'accessor', value: (d: any) => d.pattern};
getFillPatternScale: {type: 'accessor', value: 1};
getFillPatternOffset: {type: 'accessor', value: [0, 0]};
}
interface PatternFrame {
x: number;
y: number;
width: number;
height: number;
}
interface TextureSource {
// WebGL texture or image source
}
interface FillStyleModuleProps {
project: ProjectProps;
fillPatternEnabled?: boolean;
fillPatternMask?: boolean;
fillPatternTexture: Texture;
}Usage Examples:
import { PathLayer, PolygonLayer } from "@deck.gl/layers";
import { PathStyleExtension, FillStyleExtension } from "@deck.gl/extensions";
// Dashed path lines
const dashedPathLayer = new PathLayer({
id: "dashed-paths",
data: pathData,
extensions: [new PathStyleExtension({ dash: true })],
getPath: d => d.coordinates,
getDashArray: d => [20, 10], // 20 unit dash, 10 unit gap
dashJustified: true, // Align dashes with path endpoints
getWidth: 5
});
// Offset paths (useful for multiple lanes)
const offsetPathLayer = new PathLayer({
id: "offset-paths",
data: roadData,
extensions: [new PathStyleExtension({ offset: true })],
getPath: d => d.centerline,
getOffset: d => d.laneOffset, // Offset from centerline
getWidth: 3
});
// Combined dash and offset
const styledPathLayer = new PathLayer({
id: "styled-paths",
data: pathData,
extensions: [new PathStyleExtension({ dash: true, offset: true })],
getPath: d => d.coordinates,
getDashArray: d => d.style === 'dotted' ? [5, 5] : [0, 0],
getOffset: d => d.side === 'right' ? 10 : -10,
dashGapPickable: false, // Only dash segments are clickable
getWidth: 2
});
// Pattern-filled polygons
const patternPolygonLayer = new PolygonLayer({
id: "pattern-polygons",
data: polygonData,
extensions: [new FillStyleExtension({ pattern: true })],
getPolygon: d => d.coordinates,
fillPatternAtlas: './patterns.png', // Texture atlas image
fillPatternMapping: './patterns.json', // Pattern mapping file
getFillPattern: d => d.patternType, // Pattern name from data
getFillPatternScale: d => d.scale || 1,
getFillPatternOffset: [0, 0],
fillPatternMask: true // Pattern shows through base color
});
// Dynamic pattern scaling and positioning
const dynamicPatternLayer = new PolygonLayer({
id: "dynamic-patterns",
data: polygonData,
extensions: [new FillStyleExtension({ pattern: true })],
getPolygon: d => d.coordinates,
fillPatternAtlas: patternTexture,
fillPatternMapping: {
'stripes': { x: 0, y: 0, width: 64, height: 64 },
'dots': { x: 64, y: 0, width: 64, height: 64 },
'crosshatch': { x: 0, y: 64, width: 64, height: 64 }
},
getFillPattern: d => d.pattern,
getFillPatternScale: d => d.density, // Scale based on data
getFillPatternOffset: d => [d.offsetX, d.offsetY], // Custom offset
fillPatternMask: false // Replace base color entirely
});// For very long paths requiring precise dash calculations
const precisionDashLayer = new PathLayer({
extensions: [new PathStyleExtension({
dash: true,
highPrecisionDash: true
})],
getPath: d => d.longPath, // Very long geographical path
getDashArray: [1000, 500], // Large dash pattern in meters
dashJustified: true
});// Using a pre-loaded texture atlas
const textureAtlas = device.createTexture({
data: patternImage,
width: 256,
height: 256
});
const patternLayer = new PolygonLayer({
extensions: [new FillStyleExtension({ pattern: true })],
fillPatternAtlas: textureAtlas,
fillPatternMapping: {
'brick': { x: 0, y: 0, width: 64, height: 64 },
'wood': { x: 64, y: 0, width: 64, height: 64 },
'metal': { x: 0, y: 64, width: 64, height: 64 }
}
});// Apply styling based on data properties
const conditionalStyledLayer = new PathLayer({
extensions: [new PathStyleExtension({ dash: true, offset: true })],
getDashArray: d => {
switch(d.roadType) {
case 'highway': return [0, 0]; // Solid line
case 'local': return [10, 5]; // Dashed
case 'trail': return [5, 10]; // Dotted
default: return [0, 0];
}
},
getOffset: d => d.direction === 'eastbound' ? 5 : -5
});